/**************************************************************
Description: Bootloader Program
Author: Niklas Langmaack
for problems, bugs, questions and good ideas
mailto:Niklas@Langmaack-IZ.de
===============================================================
This bootloader uses the hardware rs232 capability of the
PICmicro to load the program as fast as possible. It is
configured for 1200 baud, maybe it works even faster.
The loader is located at the end of the program memory and
uses 512 words.
I've written two sample "custom.h" files:
16F876 with 8K words
16F870 with 2K words
It should be no problem to change the values in these files
for your specific application...
The bootloader should work with any Flash PICmicro, that has a
hardware rs232, self-programming capability and at least 1K memory ;-)
At the moment, thats only the PIC16F87x family, but Microchip is
already planing new cool flash devices....we'll C
===============================================================
History:
05.07.2003
v1.1 lots of changes, half the code size of v1.0
changes in detail:
new read_flash() function
optimized save_boot_sect()
some optimization in load_from_pc()
removed main_menu()
rs232 in assembler, no more pointers, shorter texts
one included file for all changes
14.06.2003
v1.0 first final version
**************************************************************/
#include <system.h>
#include "main.h"
#include "custom_16F870.h"
//======================== defs =======================
// var
char a;
char b;
char c;
char i;
//====================== init ==========================
void init()
{
//pragmas
#pragma RESERVE_ADDR_0 goto _main__code
#pragma BOOTLOADER start_adr
//init Hardware RS232
txsta = 00100010b;
rcsta = 10010000b;
spbrg = baud_rate;
}
//=============== functions ========================
void write_flash( char adH, char adL, char datH, char datL )
{
eeadrh = adH; //this function writes one
eeadr = adL; //word of code to the
eedath = datH; //PIC's flash program mem
eedata = datL;
set_bit(eecon1, EEPGD);
set_bit(eecon1, WREN);
eecon2 = 0x55;
eecon2 = 0xAA;
set_bit(eecon1, WR);
nop();
nop();
nop();
}
char read_flash( char adH, char adL, char byte ) //reads one byte (0=lower, 1=upper)
{ //from the given location
eeadrh = adH; //in flash program mem
eeadr = adL;
set_bit(eecon1, EEPGD);
set_bit(eecon1, RD);
nop();
nop();
if (byte == 0)
return eedata;
else
return eedath;
}
/*
copies the first three opcodes of the loaded program to a special adress,
from where the program can be started then
*/
void save_boot_sect()
{
for(i=0; i<3; i++)
{
write_flash(save_boot_adr,0xFC+i,read_flash(0,i,1),read_flash(0,i,0));
}
}
void rep_boot_sect() //this function repairs the boot
{ //sector, so that after a reset
write_flash(0,0,rep1,rep2); //the bootloader will be started
write_flash(0,1,rep3,rep4);
write_flash(0,2,rep5,rep6);
write_flash(0,3,rep7,rep8);
}
void load_from_pc() //the main loading function!
{
char finished;
char adrH;
char adrL;
char dataH;
char dataL;
char length;
put_CR_LF();
put_CR_LF();
asm
{
putchr 'S'
putchr 'u'
putchr 'r'
putchr 'e'
putchr '?'
putchr ' '
putchr 'y'
putchr '/'
putchr 'n'
}
put_CR_LF();
asm putchr '>'
load_loop:
a = getchr();
if (a == 'n')
goto abort;
if (a == 'y')
{
asm
{
putchr 'S'
putchr 'e'
putchr 'n'
putchr 'd'
putchr ' '
putchr 'f'
putchr 'i'
putchr 'l'
putchr 'e'
putchr '!'
}
finished = 0;
while(finished == 0)
{
a = getchr();
if (a == ':')
{
length = hex2char(getchr(),getchr());
adrH = hex2char(getchr(),getchr());
adrL = hex2char(getchr(),getchr());
getchr();
getchr();
adrL = (adrL >> 1) + ((adrH & 1)*128);
adrH = adrH >> 1;
if (adrH < max_adr)
{
i = 0;
while (i < length)
{
dataL = hex2char(getchr(),getchr());
dataH = hex2char(getchr(),getchr());
write_flash(adrH, adrL, dataH, dataL);
i = i + 2;
adrL++;
if (adrL == 0) adrH++;
}
}
else
finished = 1;
}
}
save_boot_sect();
rep_boot_sect();
put_CR_LF();
asm putchr 'O'
asm putchr 'K'
put_CR_LF();
asm
{
putchr 'R'
putchr 'e'
putchr 's'
putchr 'e'
putchr 't'
putchr '!'
}
while(1) nop();
}
else
goto loop;
abort:
}
void run_current() //starts the current program
{
asm goto boot_sect
}
//============================== Main program entry ======================
void main() //in this function, you could think about
{ //writing some code, that tests a pin connected
init(); //to a jumper to automatically start the current
//program...
menu:
put_menu_txt();
loop:
switch( getchr() )
{
case '1': load_from_pc(); break;
case '2': run_current(); break;
case ' ': goto menu; break;
}
goto loop;
}
Copyright © 2002-2006 SourceBoost Technologies