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