/**** BootLoader ****/#define VERSION "1.0"#define ID "$Id: bloader.c 1300 2009-01-17 08:41:49Z kakl $"#CASE // Case sensitive compiler#include "bloader.h"#include <string.h>#bit CREN = 0x18.4 // USART registers#bit SPEN = 0x18.7#bit OERR = 0x18.1#bit FERR = 0x18.2#INT_RDArs232_handler(){putchar(getc());}void welcome(void) // Welcome message{char REV[50]=ID; // Buffer for concatenate of a version stringchar VER[4]=VERSION; // Buffer for concatenate of a version stringif (REV[strlen(REV)-1]=='$') REV[strlen(REV)-1]=0;printf("\n\r\n\r# BLoader %s (C) 2007 KAKL\n\r",VER); // Welcome messageprintf("#%s\n\r",&REV[4]);}/*-------------------------------- MAIN --------------------------------------*/#SEPARATEvoid real_main(){int8 i=0;welcome();printf("# Boot Loader Test >>>\n\r# ");enable_interrupts(INT_RDA);enable_interrupts(GLOBAL);while(TRUE){printf("%u|",i++);delay_ms(100);}}/*------------------- BOOT LOADER --------------------------------------------*/#define FLASH_BLOCK_SIZE 32#define LOADER_RESERVED getenv("PROGRAM_MEMORY")-26*FLASH_BLOCK_SIZE#define BUFFER_LEN_LOD 46#if FLASH_BLOCK_SIZE != getenv("FLASH_ERASE_SIZE")/2#error Wrong length of the Flash Block Size. getenv("FLASH_ERASE_SIZE")/getenv("FLASH_WRITE_SIZE")#endif#BUILD(INTERRUPT=FLASH_BLOCK_SIZE) // Redirect Interrupt routine above first flash block#ORG 4,5void JumpToTheInterrupt() // Jump to the Interrupt Handler{ #asm GOTO FLASH_BLOCK_SIZE #endasm }#ORG 6,FLASH_BLOCK_SIZE-1 {} // First Flash block is reserved#ORG LOADER_RESERVED,LOADER_RESERVED+FLASH_BLOCK_SIZE-1 auto=0#SEPARATEvoid dummy_main() // Main on the fix position{real_main();}#ORG LOADER_RESERVED+FLASH_BLOCK_SIZE,getenv("PROGRAM_MEMORY")-130 auto=0 defaultunsigned int atoi_b16(char *s) // Convert two hex characters to an int8{unsigned int result = 0;int i;for (i=0; i<2; i++,s++) {if (*s >= 'A')result = 16*result + (*s) - 'A' + 10;elseresult = 16*result + (*s) - '0';}return(result);}void assert(int1 Condition, int8 ErrorCode){if(Condition){putchar('E');putchar(ErrorCode+'1');reset_cpu();}}void pause(){int16 timeout;for(timeout=0; timeout<65535; timeout++); // Delay cca 300ms}#SEPARATEboot_loader(){int buffidx;char buffer[BUFFER_LEN_LOD];int8 checksum, line_type;int16 l_addr,h_addr=0;int16 addr;int32 next_addr;int8 dataidx, i, count;union program_data {int8 i8[16];int16 i16[8];} data;putchar('@');//nesmaze obsluhu preruseni a jump na mainfor(addr=getenv("FLASH_ERASE_SIZE")/2;addr<=LOADER_RESERVED;addr+=getenv("FLASH_ERASE_SIZE")/2){erase_program_eeprom(addr);putchar('.');}putchar('!');while(!kbhit()) restart_wdt();while(TRUE){//---WDTwhile (getc()!=':') restart_wdt(); // Only process data blocks that starts with ':'buffidx = 0; // Read into the buffer until fill is received or buffer is fulldo{buffer[buffidx] = getc();} while ( (buffer[buffidx++] < 'g') && (buffidx < BUFFER_LEN_LOD) );assert(buffidx == BUFFER_LEN_LOD,1); // Error 1 - Buffer Overrun//---WDTrestart_wdt();checksum = 0; // Sum the bytes to find the check sum valuefor (i=0; i<(buffidx-3); i+=2)checksum += atoi_b16 (&buffer[i]);checksum = 0xFF - checksum + 1;assert(checksum != atoi_b16 (&buffer[buffidx-3]),2); // Error 2 - Bad CheckSum// count = atoi_b16 (&buffer[0]); // Get the number of bytes from the buffer// Get the lower 16 bits of addressl_addr = make16(atoi_b16(&buffer[2]),atoi_b16(&buffer[4]));line_type = atoi_b16 (&buffer[6]);addr = make32(h_addr,l_addr);addr /= 2; // PIC16 uses word addresses// If the line type is 1, then data is done being sentif (line_type == 1){putchar('#');reset_cpu();}assert (line_type == 4,4); // Error 4 - Line type 4{if (line_type == 0){// Read old program memory contentfor (i=0,next_addr=addr;i<8;i++)data.i16[i]=read_program_eeprom(next_addr++);// Loops through all of the data and stores it in data// The last 2 bytes are the check sum, hence buffidx-3for (i=8,dataidx=0; i < buffidx-3; i += 2)data.i8[dataidx++]=atoi_b16(&buffer[i]);if (addr == 0){// Write 8 words to the Loader locationaddr=LOADER_RESERVED;for (i=0;i<8;i++)write_program_eeprom(addr++, data.i16[i]);putchar('%');}elseif (addr > 7 && addr < LOADER_RESERVED){// Write 8 wordsfor (i=0;i<8;i++)write_program_eeprom(addr++, data.i16[i]);putchar('*');}else putchar('.');//---WDTrestart_wdt();CREN=0; CREN=1; // Reinitialise USART}}}}#ORG default#ORG getenv("PROGRAM_MEMORY")-129,getenv("PROGRAM_MEMORY")-1 auto=0void main(){int8 timeout;disable_interrupts(GLOBAL);setup_wdt(WDT_2304MS); // Setup Watch Dogsetup_adc_ports(NO_ANALOGS);setup_adc(ADC_OFF);setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);setup_timer_1(T1_DISABLED);setup_timer_2(T2_DISABLED,0,1);setup_comparator(NC_NC_NC_NC);setup_vref(FALSE);setup_oscillator(OSC_8MHZ|OSC_INTRC);for(timeout=0; timeout<255; timeout++) //cca 50s{if (kbhit())if (getc()=='u') // "uf" as Update Firmware{if (getc()=='f'){restart_wdt();boot_loader(); // Update Firmware starter}}else break;putchar('u'); putchar('f'); putchar('?');pause();CREN=0; CREN=1; // Reinitialise USARTrestart_wdt();};CREN=0; CREN=1; // Reinitialise USARTrestart_wdt();goto_address(LOADER_RESERVED); // Jump to the location where is the jump to the main}