Rev Author Line No. Line
1300 kakl 1 /**** BootLoader ****/
1705 kakl 2 #define VERSION "1.1"
1299 kakl 3 #define ID "$Id: bloader.c 1705 2010-12-05 19:24:34Z kakl $"
1297 kakl 4  
5 #CASE // Case sensitive compiler
6  
1705 kakl 7 #define FLASH_BLOCK_SIZE 32
8 #define BLOADER_MAIN_LENGTH 139 // Rezervovane misto pro main BootLoaderu
9 #define RESERVED_BLOCKS 24 // Pocet rezervovanych bloku Flash pro BootLoader
10 #define LOADER_RESERVED getenv("PROGRAM_MEMORY")-RESERVED_BLOCKS*FLASH_BLOCK_SIZE
11 #define BUFFER_LEN_LOD 46
12 #if FLASH_BLOCK_SIZE != getenv("FLASH_ERASE_SIZE")/2
13 #error Wrong length of the Flash Block Size. getenv("FLASH_ERASE_SIZE")/getenv("FLASH_WRITE_SIZE")
14 #endif
15  
1297 kakl 16 #include "bloader.h"
1300 kakl 17 #include <string.h>
1297 kakl 18  
19 #bit CREN = 0x18.4 // USART registers
20 #bit SPEN = 0x18.7
21 #bit OERR = 0x18.1
22 #bit FERR = 0x18.2
23  
24  
25 #INT_RDA
1705 kakl 26 void rs232_handler()
1297 kakl 27 {
1298 kakl 28 putchar(getc());
1297 kakl 29 }
30  
1300 kakl 31 void welcome(void) // Welcome message
32 {
33 char REV[50]=ID; // Buffer for concatenate of a version string
34 char VER[4]=VERSION; // Buffer for concatenate of a version string
1297 kakl 35  
1300 kakl 36 if (REV[strlen(REV)-1]=='$') REV[strlen(REV)-1]=0;
1705 kakl 37 printf("\r\n\r\n# BLoader %s (C) 2007 KAKL\r\n",VER); // Welcome message
38 printf("#%s\r\n",&REV[4]);
1300 kakl 39 }
40  
41  
1297 kakl 42 /*-------------------------------- MAIN --------------------------------------*/
43 #SEPARATE
44 void real_main()
45 {
46 int8 i=0;
47  
1300 kakl 48 welcome();
49  
1705 kakl 50 printf("# Reserved: %Lu\r\n", RESERVED_BLOCKS*FLASH_BLOCK_SIZE);
51  
52 printf("# Boot Loader Test >>>\r\n# ");
1297 kakl 53 enable_interrupts(INT_RDA);
54 enable_interrupts(GLOBAL);
55 while(TRUE)
56 {
1300 kakl 57 printf("%u|",i++);
1297 kakl 58 delay_ms(100);
59 }
60 }
61  
62  
63 /*------------------- BOOT LOADER --------------------------------------------*/
64  
65 #BUILD(INTERRUPT=FLASH_BLOCK_SIZE) // Redirect Interrupt routine above first flash block
66 #ORG 4,5
67 void JumpToTheInterrupt() // Jump to the Interrupt Handler
68 { #asm GOTO FLASH_BLOCK_SIZE #endasm }
69 #ORG 6,FLASH_BLOCK_SIZE-1 {} // First Flash block is reserved
70  
71  
72 #ORG LOADER_RESERVED,LOADER_RESERVED+FLASH_BLOCK_SIZE-1 auto=0
73 #SEPARATE
1298 kakl 74 void dummy_main() // Main on the fix position
1297 kakl 75 {
76 real_main();
77 }
78  
1705 kakl 79 #ORG LOADER_RESERVED+FLASH_BLOCK_SIZE,getenv("PROGRAM_MEMORY")-BLOADER_MAIN_LENGTH auto=0 default
1297 kakl 80  
81 unsigned int atoi_b16(char *s) // Convert two hex characters to an int8
82 {
83 unsigned int result = 0;
84 int i;
85  
86 for (i=0; i<2; i++,s++) {
87 if (*s >= 'A')
88 result = 16*result + (*s) - 'A' + 10;
89 else
90 result = 16*result + (*s) - '0';
91 }
92  
93 return(result);
94 }
95  
96 void assert(int1 Condition, int8 ErrorCode)
97 {
98 if(Condition)
99 {
100 putchar('E');
101 putchar(ErrorCode+'1');
102 reset_cpu();
103 }
104 }
105  
106 void pause()
107 {
108 int16 timeout;
109  
110 for(timeout=0; timeout<65535; timeout++); // Delay cca 300ms
111 }
112  
113 #SEPARATE
1705 kakl 114 void boot_loader()
1297 kakl 115 {
116 int buffidx;
117 char buffer[BUFFER_LEN_LOD];
118  
119 int8 checksum, line_type;
120 int16 l_addr,h_addr=0;
121 int16 addr;
122 int32 next_addr;
123  
1705 kakl 124 int8 dataidx, i;
1297 kakl 125 union program_data {
126 int8 i8[16];
127 int16 i16[8];
128 } data;
129  
130 putchar('@');
131  
132 //nesmaze obsluhu preruseni a jump na main
133 for(addr=getenv("FLASH_ERASE_SIZE")/2;addr<=LOADER_RESERVED;addr+=getenv("FLASH_ERASE_SIZE")/2)
134 {
135 erase_program_eeprom(addr);
136 putchar('.');
137 }
138  
139 putchar('!');
140  
141 while(!kbhit()) restart_wdt();
142  
143 while(TRUE)
144 {
145 //---WDT
146 while (getc()!=':') restart_wdt(); // Only process data blocks that starts with ':'
147  
1300 kakl 148 buffidx = 0; // Read into the buffer until fill is received or buffer is full
1297 kakl 149 do
150 {
151 buffer[buffidx] = getc();
1300 kakl 152 } while ( (buffer[buffidx++] < 'g') && (buffidx < BUFFER_LEN_LOD) );
1297 kakl 153 assert(buffidx == BUFFER_LEN_LOD,1); // Error 1 - Buffer Overrun
154  
155 //---WDT
156 restart_wdt();
157  
158 checksum = 0; // Sum the bytes to find the check sum value
159 for (i=0; i<(buffidx-3); i+=2)
160 checksum += atoi_b16 (&buffer[i]);
161 checksum = 0xFF - checksum + 1;
162 assert(checksum != atoi_b16 (&buffer[buffidx-3]),2); // Error 2 - Bad CheckSum
163  
164 // count = atoi_b16 (&buffer[0]); // Get the number of bytes from the buffer
165  
166 // Get the lower 16 bits of address
167 l_addr = make16(atoi_b16(&buffer[2]),atoi_b16(&buffer[4]));
168  
169 line_type = atoi_b16 (&buffer[6]);
170  
171 addr = make32(h_addr,l_addr);
172  
173 addr /= 2; // PIC16 uses word addresses
174  
175 // If the line type is 1, then data is done being sent
176 if (line_type == 1)
177 {
178 putchar('#');
179 reset_cpu();
180 }
181  
182 assert (line_type == 4,4); // Error 4 - Line type 4
183  
184 {
185  
186 if (line_type == 0)
187 {
188 // Read old program memory content
1298 kakl 189 for (i=0,next_addr=addr;i<8;i++)
1297 kakl 190 data.i16[i]=read_program_eeprom(next_addr++);
191 // Loops through all of the data and stores it in data
192 // The last 2 bytes are the check sum, hence buffidx-3
193 for (i=8,dataidx=0; i < buffidx-3; i += 2)
194 data.i8[dataidx++]=atoi_b16(&buffer[i]);
195  
1298 kakl 196 if (addr == 0)
1297 kakl 197 {
1298 kakl 198  
1297 kakl 199 // Write 8 words to the Loader location
200 addr=LOADER_RESERVED;
1298 kakl 201 for (i=0;i<8;i++)
1297 kakl 202 write_program_eeprom(addr++, data.i16[i]);
203 putchar('%');
204 }
205 else
206 if (addr > 7 && addr < LOADER_RESERVED)
207 {
208 // Write 8 words
209 for (i=0;i<8;i++)
210 write_program_eeprom(addr++, data.i16[i]);
211 putchar('*');
212 }
213 else putchar('.');
214 //---WDT
1300 kakl 215 restart_wdt();
216 CREN=0; CREN=1; // Reinitialise USART
1297 kakl 217 }
218 }
219 }
220 }
221  
222 #ORG default
223  
1705 kakl 224 #ORG getenv("PROGRAM_MEMORY")-BLOADER_MAIN_LENGTH+1,getenv("PROGRAM_MEMORY")-1 auto=0
1297 kakl 225 void main()
226 {
227 int8 timeout;
228  
229 disable_interrupts(GLOBAL);
230 setup_wdt(WDT_2304MS); // Setup Watch Dog
231 setup_adc_ports(NO_ANALOGS);
232 setup_adc(ADC_OFF);
233 setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
234 setup_timer_1(T1_DISABLED);
235 setup_timer_2(T2_DISABLED,0,1);
236 setup_comparator(NC_NC_NC_NC);
237 setup_vref(FALSE);
238 setup_oscillator(OSC_8MHZ|OSC_INTRC);
239  
240 for(timeout=0; timeout<255; timeout++) //cca 50s
241 {
242 if (kbhit())
243 if (getc()=='u') // "uf" as Update Firmware
244 {
245 if (getc()=='f')
246 {
247 restart_wdt();
248 boot_loader(); // Update Firmware starter
249 }
250 }
251 else break;
1300 kakl 252 putchar('u'); putchar('f'); putchar('?');
1297 kakl 253 pause();
254 CREN=0; CREN=1; // Reinitialise USART
255 restart_wdt();
256 };
257  
258 CREN=0; CREN=1; // Reinitialise USART
259 restart_wdt();
1298 kakl 260 goto_address(LOADER_RESERVED); // Jump to the location where is the jump to the main
1297 kakl 261 }
1298 kakl 262