|
 |
Untitled Document
/******************************************************
* BOOT LOADER CODE FOR THE PIC16F877 *
* CIRCUIT CELLAR ONLINE VERSION *
* CODE LAST UPDATED 12/31/2000 *
* WRITTEN BY: FRED EADY *
******************************************************/
#include <16F877.H>
#include
#fuses HS,NOWDT,NOPROTECT, NOBROWNOUT, NOLVP, PUT
#id 0X1231
/******************************************************
* DEFINE END OF USER CODE SPACE *
******************************************************/
#define MAXADDR 0x1D00
/******************************************************
* DEFINE INTEL HEX BUFFER AREA OF 64 BYTES IN BANK 2 *
******************************************************/
#define BUFFER_LEN 64
int buffaddr;
#byte buffaddr = 0xA0
char buffer[BUFFER_LEN];
#byte buffer = 0xA1
/******************************************************
* DEFINE FLOW CONTROL PINS *
******************************************************/
#define CTSON output_low(PIN_B2)
#define CTSOFF output_high(PIN_B2)
#define RTS input(PIN_B1)
/******************************************************
* TELL COMPILER NOT TO PLACE THIS CODE INLINE *
******************************************************/
#SEPARATE
unsigned int atoi_b16(char *s);
/******************************************************
* INLINE RECEIVE CHARACTER ROUTINE *
******************************************************/
#inline
char rxchar(){
char serial_in;
#asm
norx:
btfss RCIF
goto norx
movf RCREG,W
movwf serial_in
#endasm
return(serial_in);
}
/******************************************************
* INLINE TRANSMIT CHARACTER ROUTINE *
******************************************************/
#inline
void txchar(char s){
char serial_out;
serial_out = s;
#asm
notx:
btfss TXIF
goto notx
movf serial_out,W
movwf TXREG
#endasm
}
/******************************************************
* ASCII TO INTEGER CONVERSION ROUTINE *
******************************************************/
#ORG 0x1D80,0x1DCF
unsigned int atoi_b16(char *s){
unsigned int result = 0;
int i;
for (i=0; i<2; i++) {
if (*s >= 'A' && *s <= 'F')
result = 16*result + (*s) - 'A' + 10;
else if (*s >= '0' && *s <= '9')
result = 16*result + (*s) - '0';
s++;
}
return(result);
}
/******************************************************
* MAIN BOOT LOADER ROUTINE *
******************************************************/
#ORG 0x1DD0,0x1FFF
void main (void)
{
char byte_in;
short code_good, not_done,no_char,bootcodeflag;
int i, count, line_type, cs, check_sum,addrl;
long bootaddr,data,addr,addrh,bootcodeaddr,timrl,timrh;
/******************************************************
* GET BOOTCODE VECTOR ADDRESS *
******************************************************/
#asm
movphw bootcode
movwf addrh
movplw bootcode
movwf addrl
#endasm
bootcodeaddr = addrh << 8 | addrl;
/******************************************************
* INITIALIZE THE PIC UART 2400/N/8/1 *
* RB1 = RTS RB2 = CTS *
******************************************************/
TRISB = 0XFB;
CTSOFF;
SPBRG = 0X2F;
TXSTA = 0x22;
SPEN = 1;
CREN=1;
/******************************************************
* WAIT FOR UPLOAD COMMAND FROM TERA TERM *
* IF NO COMMAND RECEIVED DURING TIMOUT, RUN BOOTCODE *
* u = download new code
******************************************************/
timrl=0x20; // DELAY VALUE
timrh=0xFFFF; // DELAY VALUE
no_char = TRUE;
CTSON;
do{
if(bit_test(PIR1,5)){
byte_in = rxchar();
no_char = FALSE;
}
--timrh;
if(timrh == 0x00){
txchar('*');
--timrl;
timrh =0xFFFF;
}
}while ((timrl != 0x00) && (no_char == TRUE));
if(timrl != 0x00 && no_char == FALSE && byte_in == 'u'){
CTSOFF;
goto download;
}
/******************************************************
* BOOTCODE VECTOR *
******************************************************/
#asm
clrf PCLATH
bootcode:
nop
nop
nop
nop
goto 0x00
#endasm
/******************************************************
* DOWNLOAD INTEL HEX FILE FROM TERA TERM PRO *
******************************************************/
download:
//not_done = TRUE;
CTSON;
while (1){
buffaddr = 0;
code_good = TRUE;
do {
buffer[buffaddr++] = rxchar();
} while ((buffer[buffaddr-1] != 0x0D) && (buffaddr<=BUFFER_LEN));
CTSOFF;
/******************************************************
* INTEL HEX PROCESSOR *
* : = START OF HEX LINE *
* AA = NUMBER OF BYTES IN THE ASCII LINE *
* BBCC = LINE ADDRESS *
* DD = LINE TYPE *
******************************************************/
/******************************************************
* PROCESS THE INTEL HEX LINE HEADER *
******************************************************/
//:
if (buffer[0] == ':') {
//:AA
count = atoi_b16 (&buffer[1]);
//:AABB
addr = atoi_b16 (&buffer[3]);
//:AABBCC
addr = (addr << 8) | atoi_b16 (&buffer[5]);
//:AABBCCDD
line_type = atoi_b16 (&buffer[7]);
/******************************************************
* ADJUST THE ADDRESS *
******************************************************/
if (addr != 0)
addr /= 2;
/******************************************************
* END OF HEX FILE DATA IS LINE TYPE = 0X01 *
******************************************************/
if (line_type == 1)
break;
/******************************************************
* COMPUTE THE HEX LINE CHECKSUM *
******************************************************/
else {
cs = 0;
for (i=1; i<(buffaddr-3); i+=2)
cs += atoi_b16 (&buffer[i]);
cs = 0xFF - cs + 1;
check_sum = atoi_b16 (&buffer[buffaddr-3]);
if (check_sum != cs)
code_good = FALSE;
/******************************************************
* PROCESS THE INTEL HEX DATA AREA *
******************************************************/
else {
i = 9;
while (i < buffaddr-3) {
data = atoi_b16 (&buffer[i+2]);
data = (data << 8 ) | atoi_b16 (&buffer[i]);
/******************************************************
* PLACE BOOT VECTOR IN BOOTCODE AREA IF addr < 0X0004*
******************************************************/
bootcodeflag = FALSE;
if(addr < 0x0004){
bootcodeflag = TRUE;
bootaddr = addr + bootcodeaddr;
write_program_eeprom (bootaddr,data);
}
/******************************************************
* WRITE THE INTEL HEX DATA TO PROGRAM MEMORY *
******************************************************/
if((bootcodeflag == FALSE) && (addr < MAXADDR)){
write_program_eeprom (addr,data);
}
++addr;
i += 4;
}
}
}
}
CTSON;
}
/******************************************************
* IF INTEL HEX DOWNLOAD IS SUCCESSFUL *
* SEND g TO TERA TERM AND RESTART *
******************************************************/
CREN = 0;
timrh = 0xFFFF;
timrl = 0x40;
CTSON;
do{
--timrh;
if(timrh == 0x00){
txchar('*');
--timrl;
timrh =0xFFFF;
}
}while (timrl != 0x00);
if (code_good)
txchar('g');
/******************************************************
* IF INTEL HEX DOWNLOAD IS IN ERROR *
* PUT NOPs AT BOOTCODE VECTOR AREA *
* SEND e TO TERA TERM AND RESTART *
******************************************************/
else{
addr = 0x00;
data = 0x00;
while (addr < 4){
bootaddr = addr + bootcodeaddr;
write_program_eeprom (bootaddr,data);
++addr;
}
txchar('E');
}
/******************************************************
* ABSOLUTE RESET VECTOR TO LOCATION 0X0000 *
******************************************************/
#asm
MOVLW 0x00
MOVWF 0x0A
GOTO 0x00
#endasm
}
|
 |