1 | // ECS RS485 bootloader firmware for stmG0 MCUs |
---|
2 | |
---|
3 | #ifdef DEBUG |
---|
4 | #include <stdio.h> |
---|
5 | #endif |
---|
6 | #include <string.h> |
---|
7 | |
---|
8 | #include "stm32g0xx.h" |
---|
9 | #include "RTT/SEGGER_RTT.h" |
---|
10 | |
---|
11 | #include "main.h" |
---|
12 | #include "aes.h" |
---|
13 | |
---|
14 | #ifndef DEBUG |
---|
15 | #warning "Don't forget to turn off and turn on the device after first programming" |
---|
16 | #endif |
---|
17 | |
---|
18 | // Bootloader firmware internal version |
---|
19 | __attribute__((aligned (16))) const char FW_VERSION[16] = {"ECS.FW:01.00.01"}; // <Keep Symbols> setting in linker settings prevents this line to be thrown away |
---|
20 | |
---|
21 | //AES128 key |
---|
22 | const uint8_t AES_KEY[16] = {0x5c, 0x38, 0x36, 0x57, 0x60, 0x3d, 0x0e, 0x38, 0x61, 0x1e, 0x4e, 0x21, 0x62, 0x19, 0x47, 0x62}; |
---|
23 | |
---|
24 | union |
---|
25 | { |
---|
26 | uint8_t address_and_crc[5]; |
---|
27 | |
---|
28 | struct __attribute__((packed)) |
---|
29 | { |
---|
30 | uint8_t address[4]; |
---|
31 | uint8_t crc; |
---|
32 | } raw; |
---|
33 | |
---|
34 | struct __attribute__((packed)) |
---|
35 | { |
---|
36 | uint32_t address; |
---|
37 | uint8_t res; |
---|
38 | } mem32; |
---|
39 | |
---|
40 | struct __attribute__((packed)) |
---|
41 | { |
---|
42 | uint8_t* paddress; |
---|
43 | uint8_t res; |
---|
44 | } mem8; |
---|
45 | } u; |
---|
46 | |
---|
47 | union bigEndian |
---|
48 | { |
---|
49 | uint16_t itself; |
---|
50 | uint8_t bytes[2]; |
---|
51 | }; |
---|
52 | |
---|
53 | union flashData |
---|
54 | { |
---|
55 | uint64_t dwordData[256>>3]; |
---|
56 | uint8_t byteData[256]; |
---|
57 | }; |
---|
58 | |
---|
59 | // Tick counter |
---|
60 | volatile unsigned int msCounter = 0; |
---|
61 | |
---|
62 | //----------------------------------------------------------------------------- |
---|
63 | |
---|
64 | void Init(void); |
---|
65 | int16_t WaitForByte(unsigned int toWait); |
---|
66 | void Transmit(uint8_t *pData, int numBytes); |
---|
67 | void TransmitACK(void); |
---|
68 | void TransmitNACK(void); |
---|
69 | void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data); |
---|
70 | void Delay(uint32_t delay_in_ms); |
---|
71 | void TurnErrorLEDOn(uint32_t blink_period, uint32_t how_long_to_keep_blinking); |
---|
72 | void JumpToApplication(void); |
---|
73 | |
---|
74 | //----------------------------------------------------------------------------- |
---|
75 | |
---|
76 | int main(void) |
---|
77 | { |
---|
78 | // UART, PORT A and PORTB initialization |
---|
79 | Init(); |
---|
80 | |
---|
81 | // Saving the time bootloader has started |
---|
82 | uint32_t bl_startup_time = msCounter; |
---|
83 | |
---|
84 | while(1) |
---|
85 | { |
---|
86 | // Waiting for bootloader initialization from host for a 10s |
---|
87 | #ifdef DEBUG |
---|
88 | printf("%s\nWaiting 10s for communication initialization...\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
89 | #endif |
---|
90 | int16_t init = WaitForByte(BOOTLOADER_TIME_TO_WAIT); |
---|
91 | if (init == -1) // Error occurred, during receiption of one byte |
---|
92 | { |
---|
93 | #ifdef DEBUG |
---|
94 | printf("%s\nError during receiption of one byte!\n", RTT_CTRL_TEXT_BRIGHT_RED); |
---|
95 | #endif |
---|
96 | // Checking how much time elapsed since bootloader startup |
---|
97 | if (msCounter - bl_startup_time > BOOTLOADER_TIME_TO_WAIT) |
---|
98 | { |
---|
99 | JumpToApplication(); // Trying to start main program, if crc is correct, if not, going back to wait more for programmer |
---|
100 | bl_startup_time = msCounter; // Resetting start up time |
---|
101 | } |
---|
102 | continue; // if we still have time, we can go back to wait a bit more for correct byte |
---|
103 | } |
---|
104 | else if (init == -2) // Time-out has occured |
---|
105 | { |
---|
106 | #ifdef DEBUG |
---|
107 | printf("%s\nTimeout of 10s!\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
108 | #endif |
---|
109 | JumpToApplication(); |
---|
110 | bl_startup_time = msCounter; // Resetting start up time |
---|
111 | continue; // This command should never be reached if CRC is ok |
---|
112 | } |
---|
113 | else if (init != CMD_INIT) // We received one byte, but it is not one we need |
---|
114 | { |
---|
115 | #ifdef DEBUG |
---|
116 | printf("%s\nWrong INIT byte received! Got %u instead of %u!\n", RTT_CTRL_TEXT_BRIGHT_RED, init, CMD_INIT); |
---|
117 | #endif |
---|
118 | // Checking how much time elapsed since bootloader startup |
---|
119 | if (msCounter - bl_startup_time > BOOTLOADER_TIME_TO_WAIT) |
---|
120 | { |
---|
121 | JumpToApplication(); // Trying to start main program, if crc is correct, if not, going back to wait more for programmer |
---|
122 | bl_startup_time = msCounter; // Resetting start up time |
---|
123 | } |
---|
124 | continue; |
---|
125 | } |
---|
126 | |
---|
127 | #ifdef DEBUG |
---|
128 | printf("%sBootloader is initialized.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
129 | #endif |
---|
130 | |
---|
131 | TransmitACK(); |
---|
132 | |
---|
133 | // Entering command mode |
---|
134 | // We must receive two bytes |
---|
135 | // Waiting for a fist byte |
---|
136 | int16_t first, second; |
---|
137 | while (1) |
---|
138 | { |
---|
139 | first = WaitForByte(5000); |
---|
140 | |
---|
141 | if (first == -2) break; // If timeout happened, then we return to init stage |
---|
142 | else if (first == -1) continue; // If there's an error during reading from USART, then we keep reading |
---|
143 | else |
---|
144 | { |
---|
145 | second = WaitForByte(5000); |
---|
146 | |
---|
147 | if (second < 0) continue; // If timeout or error happened, then we go back to the receiving of the first byte |
---|
148 | else |
---|
149 | { |
---|
150 | uint8_t command = first; |
---|
151 | uint8_t command_xor = ~second; |
---|
152 | |
---|
153 | if ((command == CMD_GETID) && (command_xor == CMD_GETID)) |
---|
154 | { |
---|
155 | #ifdef DEBUG |
---|
156 | printf("%sGot GET_ID command.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
157 | #endif |
---|
158 | uint8_t TxData[5]; |
---|
159 | |
---|
160 | TxData[0] = CMD_ACK; |
---|
161 | TxData[1] = 1; |
---|
162 | // Locating DEV_ID in memory |
---|
163 | uint8_t *dev_id = (uint8_t*)DBG_BASE; |
---|
164 | // Now, we can access it as byte array |
---|
165 | TxData[2] = dev_id[1] & 0x0F; // Clearing upper nibble of the MSB |
---|
166 | TxData[3] = dev_id[0]; |
---|
167 | TxData[4] = CMD_ACK; |
---|
168 | |
---|
169 | Transmit(TxData, 5); |
---|
170 | } |
---|
171 | else if ((command == CMD_GET) && (command_xor == CMD_GET)) |
---|
172 | { |
---|
173 | #ifdef DEBUG |
---|
174 | printf("%sGot GET command.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
175 | #endif |
---|
176 | uint8_t TxData[15]; |
---|
177 | |
---|
178 | uint8_t idx = 0; |
---|
179 | TxData[idx] = CMD_ACK; |
---|
180 | TxData[++idx] = 11; |
---|
181 | TxData[++idx] = BOOTLOADER_VERSION; |
---|
182 | TxData[++idx] = CMD_GET; |
---|
183 | TxData[++idx] = CMD_GET_VER_RPS; |
---|
184 | TxData[++idx] = CMD_GETID; |
---|
185 | TxData[++idx] = CMD_READ_MEMORY; |
---|
186 | TxData[++idx] = CMD_GO; |
---|
187 | TxData[++idx] = CMD_WRITE_MEMORY; |
---|
188 | TxData[++idx] = CMD_ERASE; |
---|
189 | TxData[++idx] = CMD_WRITE_PROTECT; |
---|
190 | TxData[++idx] = CMD_WRITE_UNPROTECT; |
---|
191 | TxData[++idx] = CMD_READOUT_PROTECT; |
---|
192 | TxData[++idx] = CMD_READOUT_UNPROTECT; |
---|
193 | TxData[++idx] = CMD_ACK; |
---|
194 | |
---|
195 | Transmit(TxData, 15); |
---|
196 | } |
---|
197 | else if ((command == CMD_READ_MEMORY) && (command_xor == CMD_READ_MEMORY)) |
---|
198 | { |
---|
199 | #ifdef DEBUG |
---|
200 | printf("%sGot READ_MEMORY command.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
201 | #endif |
---|
202 | uint8_t TxData; |
---|
203 | // !!! Before sending ACK we must check RDP protection |
---|
204 | TransmitACK(); |
---|
205 | |
---|
206 | int error_flag = 0; |
---|
207 | int16_t tmp; |
---|
208 | |
---|
209 | memset(&u, 0, sizeof(u)); |
---|
210 | |
---|
211 | for (int i = 0; i < 5; i++) |
---|
212 | { |
---|
213 | tmp = WaitForByte(5000); |
---|
214 | if (tmp < 0) |
---|
215 | { |
---|
216 | error_flag = 1; |
---|
217 | break; |
---|
218 | } |
---|
219 | else u.address_and_crc[i] = tmp; |
---|
220 | } |
---|
221 | |
---|
222 | if (error_flag) continue; |
---|
223 | |
---|
224 | uint8_t checksum = u.raw.address[0] ^ u.raw.address[1] ^ u.raw.address[2] ^ u.raw.address[3]; |
---|
225 | |
---|
226 | u.mem32.address = __REV(u.mem32.address); |
---|
227 | |
---|
228 | if (checksum == u.raw.crc) |
---|
229 | { |
---|
230 | #ifdef DEBUG |
---|
231 | printf("\t%sAddress 0x%08X requested.\n", RTT_CTRL_TEXT_BRIGHT_GREEN, u.mem32.address); |
---|
232 | #endif |
---|
233 | TransmitACK(); |
---|
234 | |
---|
235 | uint8_t bytesNumber_crc[2]; |
---|
236 | |
---|
237 | error_flag = 0; |
---|
238 | |
---|
239 | for (int i = 0; i < 2; i++) |
---|
240 | { |
---|
241 | tmp = WaitForByte(5000); |
---|
242 | if (tmp < 0) |
---|
243 | { |
---|
244 | error_flag = 1; |
---|
245 | break; |
---|
246 | } |
---|
247 | else bytesNumber_crc[i] = tmp; |
---|
248 | } |
---|
249 | |
---|
250 | if (error_flag) continue; |
---|
251 | |
---|
252 | bytesNumber_crc[1] = ~bytesNumber_crc[1]; |
---|
253 | |
---|
254 | if (bytesNumber_crc[0] == bytesNumber_crc[1]) |
---|
255 | { |
---|
256 | TransmitACK(); |
---|
257 | |
---|
258 | // Checking memory address access possibility |
---|
259 | |
---|
260 | // We do not allow reading from the device, so we send fake data |
---|
261 | uint8_t fakeData[bytesNumber_crc[0]+1]; |
---|
262 | memset(fakeData, 0xEC, bytesNumber_crc[0]+1); |
---|
263 | Transmit(fakeData, bytesNumber_crc[0]+1); |
---|
264 | //Transmit(u.mem8.paddress, bytesNumber_crc[0]+1); |
---|
265 | } |
---|
266 | else TransmitNACK(); |
---|
267 | } |
---|
268 | else |
---|
269 | { |
---|
270 | #ifdef DEBUG |
---|
271 | printf("\n%s Memory address CRC error!", RTT_CTRL_TEXT_BRIGHT_RED); |
---|
272 | #endif |
---|
273 | TransmitNACK(); |
---|
274 | } |
---|
275 | } |
---|
276 | else if ((command == CMD_GET_VER_RPS) && (command_xor == CMD_GET_VER_RPS)) |
---|
277 | { |
---|
278 | uint8_t TxData[5]; |
---|
279 | |
---|
280 | TxData[0] = CMD_ACK; |
---|
281 | TxData[1] = BOOTLOADER_VERSION; |
---|
282 | TxData[2] = 0x00; |
---|
283 | TxData[3] = 0x00; |
---|
284 | |
---|
285 | TxData[4] = CMD_ACK; |
---|
286 | |
---|
287 | Transmit(TxData, 5); |
---|
288 | } |
---|
289 | else if ((command == CMD_ERASE) && (command_xor == CMD_ERASE)) |
---|
290 | { |
---|
291 | #ifdef DEBUG |
---|
292 | printf("%sGot ERASE command.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
293 | #endif |
---|
294 | // !!! Before sending ACK we must check RDP protection |
---|
295 | TransmitACK(); |
---|
296 | |
---|
297 | int16_t numPages = WaitForByte(5000); |
---|
298 | if (numPages < 0) continue; |
---|
299 | else |
---|
300 | { |
---|
301 | uint8_t Pages[numPages + 2]; // + XOR byte |
---|
302 | |
---|
303 | int error_flag = 0; |
---|
304 | int16_t tmp; |
---|
305 | |
---|
306 | for (int i = 0; i < (numPages + 2); i++) |
---|
307 | { |
---|
308 | tmp = WaitForByte(5000); |
---|
309 | if (tmp < 0) |
---|
310 | { |
---|
311 | error_flag = 1; |
---|
312 | break; |
---|
313 | } |
---|
314 | else Pages[i] = tmp; |
---|
315 | } |
---|
316 | |
---|
317 | if (error_flag) continue; |
---|
318 | #ifdef DEBUG |
---|
319 | printf("\tErasing %d pages:", numPages + 1); |
---|
320 | #endif |
---|
321 | uint8_t xor_crc = numPages; |
---|
322 | for (int i = 0; i < (numPages + 1); i++) |
---|
323 | { |
---|
324 | xor_crc ^= Pages[i]; |
---|
325 | #ifdef DEBUG |
---|
326 | printf(" %d", Pages[i]); |
---|
327 | #endif |
---|
328 | } |
---|
329 | #ifdef DEBUG |
---|
330 | printf("\n"); |
---|
331 | #endif |
---|
332 | if (xor_crc == Pages[numPages + 2 - 1]) |
---|
333 | { |
---|
334 | // Is FLASH_CR register locked for writing? |
---|
335 | if (FLASH->CR & FLASH_CR_LOCK) |
---|
336 | { |
---|
337 | // Unlocking FLASH_CR register |
---|
338 | FLASH->KEYR = KEY1; |
---|
339 | FLASH->KEYR = KEY2; |
---|
340 | } |
---|
341 | #ifdef DEBUG |
---|
342 | printf("\t\t%sStarting erasing.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
343 | #endif |
---|
344 | // Erasing corresponding pages, except those containing bootloader itself |
---|
345 | for (int i = 0; i < (numPages + 1); i++) |
---|
346 | { |
---|
347 | if (Pages[i] > BOOTLOADER_LAST_PAGE) // Bootloader occupies first 4-5 pages (2k) |
---|
348 | { |
---|
349 | #ifdef DEBUG |
---|
350 | while (FLASH->SR & FLASH_SR_BSY1) printf("\t%sWaiting for releasing of FLASH memory.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
351 | #else |
---|
352 | while (FLASH->SR & FLASH_SR_BSY1); |
---|
353 | #endif |
---|
354 | // Clearing possible old errors |
---|
355 | FLASH->SR |= FLASH_SR_FASTERR & FLASH_SR_MISERR & FLASH_SR_PGSERR & FLASH_SR_SIZERR & FLASH_SR_PGAERR & FLASH_SR_PROGERR & FLASH_SR_OPERR; |
---|
356 | |
---|
357 | FLASH->CR &= ~FLASH_CR_PNB; |
---|
358 | FLASH->CR |= Pages[i] << FLASH_CR_PNB_Pos; |
---|
359 | |
---|
360 | FLASH->CR |= FLASH_CR_PER; |
---|
361 | |
---|
362 | FLASH->CR |= FLASH_CR_STRT; |
---|
363 | #ifdef DEBUG |
---|
364 | while (FLASH->SR & FLASH_SR_BSY1) printf("\t\t%sWaiting for page %d to be erased...\n", RTT_CTRL_TEXT_BRIGHT_GREEN, Pages[i]); |
---|
365 | #else |
---|
366 | while (FLASH->SR & FLASH_SR_BSY1); |
---|
367 | #endif |
---|
368 | #ifdef DEBUG |
---|
369 | printf("\t\t%sPage %d has been erased.\n", RTT_CTRL_TEXT_BRIGHT_GREEN, Pages[i]); |
---|
370 | #endif |
---|
371 | FLASH->CR &= ~FLASH_CR_PER; |
---|
372 | } |
---|
373 | } |
---|
374 | #ifdef DEBUG |
---|
375 | printf("\t\t%sErasing is finished.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
376 | #endif |
---|
377 | FLASH->CR |= FLASH_CR_LOCK; |
---|
378 | |
---|
379 | TransmitACK(); |
---|
380 | } |
---|
381 | else TransmitNACK(); |
---|
382 | } |
---|
383 | } |
---|
384 | #if BOOTLOADER_VERSION > 0x30 |
---|
385 | else if ((command == CMD_EXT_ERASE) && (command_xor == CMD_EXT_ERASE)) |
---|
386 | { |
---|
387 | printf("%sGot EXTENDED ERASE command.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
388 | |
---|
389 | // !!! Before sending ACK we must check RDP protection |
---|
390 | TransmitACK(); |
---|
391 | |
---|
392 | int error_flag = 0; |
---|
393 | int16_t tmp; |
---|
394 | union bigEndian numPages; |
---|
395 | |
---|
396 | for (int i = 1; i >= 0; i--) |
---|
397 | { |
---|
398 | tmp = WaitForByte(5000, 250); |
---|
399 | if (tmp < 0) |
---|
400 | { |
---|
401 | error_flag = 1; |
---|
402 | break; |
---|
403 | } |
---|
404 | else numPages.bytes[i] = tmp; |
---|
405 | } |
---|
406 | |
---|
407 | if (error_flag) continue; |
---|
408 | |
---|
409 | if ((numPages.itself & 0xFFF0) == 0xFFF0) |
---|
410 | { |
---|
411 | int16_t crc = WaitForByte(5000, 250); |
---|
412 | |
---|
413 | if (crc < 0) continue; |
---|
414 | else |
---|
415 | { |
---|
416 | switch(numPages.itself) |
---|
417 | { |
---|
418 | case 0xFFFF: // Mass erase |
---|
419 | if (crc == 0x00) |
---|
420 | { |
---|
421 | // Perfom erase |
---|
422 | TransmitACK(); |
---|
423 | } |
---|
424 | else |
---|
425 | { |
---|
426 | TransmitNACK(); |
---|
427 | } |
---|
428 | break; |
---|
429 | |
---|
430 | case 0xFFFE: // Bank1 erase |
---|
431 | if (crc == 0x01) |
---|
432 | { |
---|
433 | // Perfom erase |
---|
434 | TransmitACK(); |
---|
435 | } |
---|
436 | else |
---|
437 | { |
---|
438 | TransmitNACK(); |
---|
439 | } |
---|
440 | break; |
---|
441 | |
---|
442 | case 0xFFFD: |
---|
443 | if (crc == 0x02) |
---|
444 | { |
---|
445 | // Perfom erase |
---|
446 | TransmitACK(); |
---|
447 | } |
---|
448 | else |
---|
449 | { |
---|
450 | TransmitNACK(); |
---|
451 | } |
---|
452 | break; |
---|
453 | } |
---|
454 | } |
---|
455 | } |
---|
456 | else |
---|
457 | { |
---|
458 | union bigEndian pageCodes[numPages.itself + 1]; |
---|
459 | |
---|
460 | int error_flag = 0; |
---|
461 | int16_t tmp; |
---|
462 | |
---|
463 | for (int i = 0; i < (numPages.itself + 1); i++) |
---|
464 | { |
---|
465 | for (int j = 1; j >= 0; j--) |
---|
466 | { |
---|
467 | tmp = WaitForByte(5000, 125); |
---|
468 | if (tmp < 0) |
---|
469 | { |
---|
470 | error_flag = 1; |
---|
471 | break; |
---|
472 | } |
---|
473 | else pageCodes[i].bytes[j] = tmp; |
---|
474 | } |
---|
475 | if (error_flag) break; |
---|
476 | } |
---|
477 | |
---|
478 | if (error_flag) continue; |
---|
479 | |
---|
480 | int16_t crc = WaitForByte(5000, 250); |
---|
481 | |
---|
482 | if (crc < 0) continue; |
---|
483 | else |
---|
484 | { |
---|
485 | uint8_t checksum = numPages.bytes[1]; |
---|
486 | checksum ^= numPages.bytes[0]; |
---|
487 | for (int i = 0; i < (numPages.itself + 1); i++) |
---|
488 | { |
---|
489 | checksum ^= pageCodes[i].bytes[1]; |
---|
490 | checksum ^= pageCodes[i].bytes[0]; |
---|
491 | } |
---|
492 | |
---|
493 | if (checksum == crc) |
---|
494 | { |
---|
495 | // Is FLASH_CR register locked for writing? |
---|
496 | if (FLASH->CR & FLASH_CR_LOCK) |
---|
497 | { |
---|
498 | // Unlocking FLASH_CR register |
---|
499 | FLASH->KEYR = KEY1; |
---|
500 | FLASH->KEYR = KEY2; |
---|
501 | } |
---|
502 | |
---|
503 | printf("\t%sStarting erasing.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
504 | |
---|
505 | // Erasing corresponding pages, except those containing bootloader itself |
---|
506 | for (int i = 0; i < (numPages.itself + 1); i++) |
---|
507 | { |
---|
508 | if (pageCodes[i].itself > BOOTLOADER_LAST_PAGE) // Bootloader occupies first 4 pages (2k) |
---|
509 | { |
---|
510 | while (FLASH->SR & FLASH_SR_BSY1) printf("\t%sWaiting for releasing of FLASH memory.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
511 | |
---|
512 | // Clearing possible old errors |
---|
513 | FLASH->SR |= FLASH_SR_FASTERR & FLASH_SR_MISERR & FLASH_SR_PGSERR & FLASH_SR_SIZERR & FLASH_SR_PGAERR & FLASH_SR_PROGERR & FLASH_SR_OPERR; |
---|
514 | |
---|
515 | FLASH->CR &= ~FLASH_CR_PNB; |
---|
516 | FLASH->CR |= pageCodes[i].bytes[0] << FLASH_CR_PNB_Pos; |
---|
517 | |
---|
518 | FLASH->CR |= FLASH_CR_PER; |
---|
519 | |
---|
520 | FLASH->CR |= FLASH_CR_STRT; |
---|
521 | |
---|
522 | while (FLASH->SR & FLASH_SR_BSY1) printf("\t%sWaiting for page %d to be erased...\n", RTT_CTRL_TEXT_BRIGHT_GREEN, pageCodes[i].bytes[0]); |
---|
523 | |
---|
524 | printf("\t%sPage %d has been erased.\n", RTT_CTRL_TEXT_BRIGHT_GREEN, pageCodes[i].bytes[0]); |
---|
525 | |
---|
526 | FLASH->CR &= ~FLASH_CR_PER; |
---|
527 | } |
---|
528 | } |
---|
529 | |
---|
530 | printf("\t%sErasing is finished.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
531 | |
---|
532 | FLASH->CR |= FLASH_CR_LOCK; |
---|
533 | |
---|
534 | TransmitACK(); |
---|
535 | } |
---|
536 | else TransmitNACK(); |
---|
537 | } |
---|
538 | } |
---|
539 | } |
---|
540 | #endif |
---|
541 | else if ((command == CMD_WRITE_MEMORY) && (command_xor == CMD_WRITE_MEMORY)) |
---|
542 | { |
---|
543 | #ifdef DEBUG |
---|
544 | printf("%sGot WRITE MEMORY command.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
545 | #endif |
---|
546 | // !!! Before sending ACK we must check RDP protection |
---|
547 | TransmitACK(); |
---|
548 | |
---|
549 | int error_flag = 0; |
---|
550 | int16_t tmp; |
---|
551 | |
---|
552 | memset(&u, 0, sizeof(u)); |
---|
553 | |
---|
554 | for (int i = 0; i < 5; i++) |
---|
555 | { |
---|
556 | tmp = WaitForByte(5000); |
---|
557 | if (tmp < 0) |
---|
558 | { |
---|
559 | error_flag = 1; |
---|
560 | break; |
---|
561 | } |
---|
562 | else u.address_and_crc[i] = tmp; |
---|
563 | } |
---|
564 | |
---|
565 | if (error_flag) continue; |
---|
566 | |
---|
567 | uint8_t checksum = u.raw.address[0] ^ u.raw.address[1] ^ u.raw.address[2] ^ u.raw.address[3]; |
---|
568 | |
---|
569 | if (checksum == u.raw.crc) |
---|
570 | { |
---|
571 | TransmitACK(); |
---|
572 | |
---|
573 | int16_t bytesNumber = WaitForByte(5000); |
---|
574 | if (bytesNumber < 0) continue; |
---|
575 | { |
---|
576 | if ((bytesNumber + 1) % 4) |
---|
577 | { |
---|
578 | #ifdef DEBUG |
---|
579 | printf("\t%sBytes number must by multiple of 4!\n", RTT_CTRL_TEXT_BRIGHT_RED); |
---|
580 | #endif |
---|
581 | TransmitNACK(); |
---|
582 | } |
---|
583 | else |
---|
584 | { |
---|
585 | union flashData DataToBeWritten; |
---|
586 | |
---|
587 | memset(DataToBeWritten.byteData, 0xFF, 256); |
---|
588 | |
---|
589 | error_flag = 0; |
---|
590 | |
---|
591 | for (int i = 0; i < (bytesNumber + 1); i++) |
---|
592 | { |
---|
593 | tmp = WaitForByte(5000); |
---|
594 | if (tmp < 0) |
---|
595 | { |
---|
596 | error_flag = 1; |
---|
597 | break; |
---|
598 | } |
---|
599 | else DataToBeWritten.byteData[i] = tmp; |
---|
600 | } |
---|
601 | |
---|
602 | if (BLUE_LED_PORT->ODR & GPIOx_ODR(GPIO_ODR_OD, BLUE_LED_PIN)) BLUE_LED_PORT->BRR = GPIOx_BRR(GPIO_BRR_BR, BLUE_LED_PIN); |
---|
603 | else BLUE_LED_PORT->BSRR = GPIOx_BSRR(GPIO_BSRR_BS, BLUE_LED_PIN); |
---|
604 | |
---|
605 | if (error_flag) continue; |
---|
606 | |
---|
607 | // Reading checksum of the above datapacket |
---|
608 | tmp = WaitForByte(5000); |
---|
609 | if (tmp < 0) continue; |
---|
610 | else |
---|
611 | { |
---|
612 | checksum = bytesNumber; |
---|
613 | for (int i = 0; i < (bytesNumber+1); i++) checksum ^= DataToBeWritten.byteData[i]; |
---|
614 | |
---|
615 | if (checksum == tmp) |
---|
616 | { |
---|
617 | u.mem32.address = __REV(u.mem32.address); |
---|
618 | // We need to define whom belongs this memory, which we are going to write |
---|
619 | if ((u.mem32.address >= (FLASH_BASE + BOOTLOADER_PROGRAM_SIZE)) && |
---|
620 | ((u.mem32.address + bytesNumber) < (FLASH_BASE + (FLASH_PAGE_NUMBER - MAIN_APP_PARAM_PAGE_NUM)*FLASH_PAGE_SIZE))) |
---|
621 | { |
---|
622 | // Here we already checked that bootloader is alowed to write in this memory area |
---|
623 | // Data is encrypted, so we must decrypt it |
---|
624 | |
---|
625 | union flashData decryptedData; |
---|
626 | memset(decryptedData.byteData, 0x00, 256); |
---|
627 | #ifdef DEBUG |
---|
628 | printf("\t%sDecrypting %d bytes...", RTT_CTRL_TEXT_BRIGHT_GREEN, bytesNumber + 1); |
---|
629 | #endif |
---|
630 | for (int i = 0; i < (bytesNumber + 1); i += 16) AES128_ECB_decrypt(DataToBeWritten.byteData + i, AES_KEY, decryptedData.byteData + i); |
---|
631 | |
---|
632 | // Is FLASH_CR register locked for writing? |
---|
633 | if (FLASH->CR & FLASH_CR_LOCK) |
---|
634 | { |
---|
635 | // Unlocking FLASH_CR register |
---|
636 | FLASH->KEYR = KEY1; |
---|
637 | FLASH->KEYR = KEY2; |
---|
638 | } |
---|
639 | #ifdef DEBUG |
---|
640 | printf("\t%sStarting programming of %d bytes.\n", RTT_CTRL_TEXT_BRIGHT_GREEN, bytesNumber + 1); |
---|
641 | #endif |
---|
642 | for (int i = 0; i < ((bytesNumber + 1)>>3); i++) |
---|
643 | { |
---|
644 | #ifdef DEBUG |
---|
645 | while (FLASH->SR & FLASH_SR_BSY1) printf("\t%sWaiting for releasing of FLASH memory.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
646 | #else |
---|
647 | while (FLASH->SR & FLASH_SR_BSY1); |
---|
648 | #endif |
---|
649 | |
---|
650 | // Clearing possible old errors |
---|
651 | FLASH->SR |= FLASH_SR_PGSERR & FLASH_SR_SIZERR & FLASH_SR_PGAERR & FLASH_SR_PROGERR; |
---|
652 | |
---|
653 | FLASH_Program_DoubleWord(u.mem32.address + (i<<3), decryptedData.dwordData[i]); |
---|
654 | #ifdef DEBUG |
---|
655 | while (FLASH->SR & FLASH_SR_BSY1) printf("\t%sWaiting for the end of programming.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
656 | #else |
---|
657 | while (FLASH->SR & FLASH_SR_BSY1); |
---|
658 | #endif |
---|
659 | #ifdef DEBUG |
---|
660 | if (FLASH->SR & FLASH_SR_PGSERR & FLASH_SR_SIZERR & FLASH_SR_PGAERR & FLASH_SR_PROGERR) printf("\t%sProgramming of failed.\n", RTT_CTRL_TEXT_BRIGHT_RED); |
---|
661 | else printf("\t%sProgramming of 8 bytes at address 0x%08X performed ok.\n", RTT_CTRL_TEXT_BRIGHT_GREEN, u.mem32.address + (i<<3)); |
---|
662 | #endif |
---|
663 | } |
---|
664 | |
---|
665 | // Clearing PG bit |
---|
666 | FLASH->CR &= ~FLASH_CR_PG; |
---|
667 | |
---|
668 | // Locking back FLASH_CR register |
---|
669 | FLASH->CR |= FLASH_CR_LOCK; |
---|
670 | |
---|
671 | TransmitACK(); |
---|
672 | } |
---|
673 | else |
---|
674 | { |
---|
675 | #ifdef DEBUG |
---|
676 | printf("%sForbidden address of 0x%08X for writing of %d bytes requested!\n", RTT_CTRL_TEXT_BRIGHT_RED, u.mem32.address, bytesNumber + 1); |
---|
677 | #endif |
---|
678 | TransmitACK(); |
---|
679 | } |
---|
680 | } |
---|
681 | else TransmitNACK(); |
---|
682 | } |
---|
683 | } |
---|
684 | } |
---|
685 | } |
---|
686 | else TransmitNACK(); |
---|
687 | } |
---|
688 | else |
---|
689 | { |
---|
690 | #ifdef DEBUG |
---|
691 | printf("%sUnknown command 0x%02X!\n", RTT_CTRL_TEXT_BRIGHT_RED, command); |
---|
692 | #endif |
---|
693 | //if (BLUE_LED_PORT->ODR & GPIO_ODR_OD10) BLUE_LED_PORT->BRR = GPIO_BRR_BR10; |
---|
694 | //else BLUE_LED_PORT->BSRR = GPIO_BSRR_BS10; |
---|
695 | |
---|
696 | TransmitNACK(); |
---|
697 | |
---|
698 | if (msCounter - bl_startup_time > BOOTLOADER_TIME_TO_WAIT) |
---|
699 | { |
---|
700 | JumpToApplication(); |
---|
701 | bl_startup_time = msCounter; // Appending more time for bootloader to start-up; |
---|
702 | break; // Going back to initialization stage |
---|
703 | } |
---|
704 | } |
---|
705 | } // else where we received second byte |
---|
706 | } // else where we received first byte |
---|
707 | } // Commands while(1) loop |
---|
708 | } // main while(1) loop, which waits for connection |
---|
709 | } // int main |
---|
710 | |
---|
711 | //----------------------------------------------------------------------------- |
---|
712 | |
---|
713 | void JumpToApplication(void) |
---|
714 | { |
---|
715 | // Enabling clocking for CRC module |
---|
716 | RCC->AHBENR |= RCC_AHBENR_CRCEN; |
---|
717 | // Resetting CRC unit and loading the content of INIT register into DR register |
---|
718 | CRC->CR |= CRC_CR_RESET; |
---|
719 | // Default POLYSIZE is 32 bit |
---|
720 | // Default POLYNOMIAL is 0x04C11DB7 |
---|
721 | // Default CRC initial value is 0xFFFFFFFF |
---|
722 | #ifdef DEBUG |
---|
723 | printf("%sStarting calculating FW CRC\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
724 | #endif |
---|
725 | for (unsigned int i = 0; i < ((FLASH_PAGE_SIZE * (FLASH_PAGE_NUMBER - MAIN_APP_PARAM_PAGE_NUM)) - BOOTLOADER_PROGRAM_SIZE - CRC_LEN); i += 4) |
---|
726 | { |
---|
727 | #ifdef DEBUG |
---|
728 | printf("\r%s\tAddress: 0x%08X ", RTT_CTRL_TEXT_BRIGHT_GREEN, MAIN_APP_START_ADDRESS + i); |
---|
729 | #endif |
---|
730 | /*if (!(i%256)) |
---|
731 | { |
---|
732 | if (BLUE_LED_PORT->ODR & GPIO_ODR_OD2) BLUE_LED_PORT->BRR = GPIO_BRR_BR2; |
---|
733 | else BLUE_LED_PORT->BSRR = GPIO_BSRR_BS2; |
---|
734 | Delay(35); |
---|
735 | }*/ |
---|
736 | // Putting next 4 bytes into CRC calculation unit |
---|
737 | CRC->DR = __REV(*(uint32_t*)(MAIN_APP_START_ADDRESS + i)); |
---|
738 | } |
---|
739 | #ifdef DEBUG |
---|
740 | printf("%sDone!\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
741 | #endif |
---|
742 | // Extracting CRC saved on last 4 bytes of the used FLASH memory |
---|
743 | uint32_t savedCRC = *(uint32_t*)(FLASH_BASE + (FLASH_PAGE_NUMBER - MAIN_APP_PARAM_PAGE_NUM)*FLASH_PAGE_SIZE - CRC_LEN); |
---|
744 | |
---|
745 | if (CRC->DR == savedCRC) |
---|
746 | { |
---|
747 | #ifdef DEBUG |
---|
748 | printf("%s\tCRCs are equal.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
749 | Delay(500); |
---|
750 | #endif |
---|
751 | // Disabling clocking for CRC module |
---|
752 | RCC->AHBENR &= ~RCC_AHBENR_CRCEN; |
---|
753 | // Resetting SysTick settings |
---|
754 | SysTick->CTRL = SysTick->LOAD = SysTick->VAL = 0; |
---|
755 | __disable_irq(); |
---|
756 | |
---|
757 | // Changing vector table address to the beginning of the main application |
---|
758 | SCB->VTOR = MAIN_APP_START_ADDRESS; |
---|
759 | // Setting stack pointer |
---|
760 | __set_MSP(*(__IO uint32_t*)MAIN_APP_START_ADDRESS); |
---|
761 | __enable_irq(); |
---|
762 | // Executing first command from main app |
---|
763 | ((void(*)(void))(*(__IO uint32_t*)(MAIN_APP_START_ADDRESS + 4)))(); |
---|
764 | |
---|
765 | // In normal situation, program flow should never reach this loop |
---|
766 | while(1) TurnErrorLEDOn(125, -1); |
---|
767 | } |
---|
768 | else |
---|
769 | { |
---|
770 | #ifdef DEBUG |
---|
771 | printf("%sCRC error!\n", RTT_CTRL_TEXT_BRIGHT_RED); |
---|
772 | #endif |
---|
773 | TurnErrorLEDOn(250, 5000); |
---|
774 | //return -1; |
---|
775 | } |
---|
776 | } |
---|
777 | |
---|
778 | //----------------------------------------------------------------------------- |
---|
779 | |
---|
780 | void Delay(uint32_t D) |
---|
781 | { |
---|
782 | volatile uint32_t tick_start = msCounter; |
---|
783 | while (msCounter - tick_start < D); |
---|
784 | } |
---|
785 | |
---|
786 | //----------------------------------------------------------------------------- |
---|
787 | |
---|
788 | void TransmitACK(void) |
---|
789 | { |
---|
790 | uint8_t TxData = CMD_ACK; |
---|
791 | Transmit(&TxData, 1); |
---|
792 | } |
---|
793 | |
---|
794 | //----------------------------------------------------------------------------- |
---|
795 | |
---|
796 | void TransmitNACK(void) |
---|
797 | { |
---|
798 | uint8_t TxData = CMD_NACK; |
---|
799 | Transmit(&TxData, 1); |
---|
800 | } |
---|
801 | |
---|
802 | //----------------------------------------------------------------------------- |
---|
803 | |
---|
804 | /** |
---|
805 | * @brief Program double-word (64-bit) at a specified address. |
---|
806 | * @param Address Specifies the address to be programmed. |
---|
807 | * @param Data Specifies the data to be programmed. |
---|
808 | * @retval None |
---|
809 | */ |
---|
810 | void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data) |
---|
811 | { |
---|
812 | /* Set PG bit */ |
---|
813 | SET_BIT(FLASH->CR, FLASH_CR_PG); |
---|
814 | |
---|
815 | /* Program first word */ |
---|
816 | *(uint32_t *)Address = (uint32_t)Data; |
---|
817 | |
---|
818 | /* Barrier to ensure programming is performed in 2 steps, in right order |
---|
819 | (independently of compiler optimization behavior) */ |
---|
820 | __ISB(); |
---|
821 | |
---|
822 | /* Program second word */ |
---|
823 | *(uint32_t *)(Address + 4U) = (uint32_t)(Data >> 32U); |
---|
824 | } |
---|
825 | |
---|
826 | //----------------------------------------------------------------------------- |
---|
827 | |
---|
828 | void Transmit(uint8_t *pData, int numBytes) |
---|
829 | { |
---|
830 | // Disabling Receiver |
---|
831 | //UART->CR1 &= ~USART_CR1_RE; |
---|
832 | #ifdef DEBUG |
---|
833 | const int SCREEN_LIMIT = 40; |
---|
834 | |
---|
835 | printf("\t%sSending %d bytes: ", RTT_CTRL_TEXT_BRIGHT_GREEN, numBytes); |
---|
836 | #endif |
---|
837 | for (int i = 0; i < numBytes; i++) |
---|
838 | { |
---|
839 | // Checking whether transmitter is free |
---|
840 | while (!(UART->ISR & USART_ISR_TXE_TXFNF)); |
---|
841 | |
---|
842 | UART->TDR = pData[i]; |
---|
843 | #ifdef DEBUG |
---|
844 | if (i <= SCREEN_LIMIT) printf("%02X", pData[i]); |
---|
845 | #endif |
---|
846 | } |
---|
847 | #ifdef DEBUG |
---|
848 | if (numBytes > SCREEN_LIMIT) printf("...\n"); |
---|
849 | else printf("\n"); |
---|
850 | #endif |
---|
851 | |
---|
852 | //while (!(UART->ISR & USART_ISR_TC)); |
---|
853 | // Enabling Receiver |
---|
854 | //UART->CR1 |= USART_CR1_RE; |
---|
855 | } |
---|
856 | |
---|
857 | //----------------------------------------------------------------------------- |
---|
858 | |
---|
859 | void SysTick_Handler(void) |
---|
860 | { |
---|
861 | msCounter++; |
---|
862 | } |
---|
863 | |
---|
864 | //----------------------------------------------------------------------------- |
---|
865 | |
---|
866 | void HardFault_Handler(void) |
---|
867 | { |
---|
868 | TurnErrorLEDOn(500, -1); |
---|
869 | } |
---|
870 | |
---|
871 | //----------------------------------------------------------------------------- |
---|
872 | |
---|
873 | void NMI_Handler(void) |
---|
874 | { |
---|
875 | TurnErrorLEDOn(250, -1); |
---|
876 | } |
---|
877 | |
---|
878 | //----------------------------------------------------------------------------- |
---|
879 | |
---|
880 | int16_t WaitForByte(unsigned int toWait) |
---|
881 | { |
---|
882 | // Waiting until we receive one byte via UART |
---|
883 | unsigned int ledStartTime = msCounter; |
---|
884 | unsigned int loopStartTime = msCounter; |
---|
885 | |
---|
886 | while (!(UART->ISR & USART_ISR_RXNE_RXFNE)) |
---|
887 | { |
---|
888 | if (msCounter - loopStartTime >= toWait) break; |
---|
889 | |
---|
890 | if (msCounter - ledStartTime >= BLUE_LED_PERIOD) |
---|
891 | { |
---|
892 | ledStartTime = msCounter; |
---|
893 | if (BLUE_LED_PORT->ODR & GPIOx_ODR(GPIO_ODR_OD, BLUE_LED_PIN)) BLUE_LED_PORT->BRR = GPIOx_BRR(GPIO_BRR_BR, BLUE_LED_PIN); |
---|
894 | else BLUE_LED_PORT->BSRR = GPIOx_BSRR(GPIO_BSRR_BS, BLUE_LED_PIN); |
---|
895 | } |
---|
896 | } |
---|
897 | |
---|
898 | // Checking if timeout occured |
---|
899 | if (msCounter - loopStartTime >= toWait) return -2; |
---|
900 | |
---|
901 | // Checking Overrun error |
---|
902 | if (UART->ISR & USART_ISR_ORE) |
---|
903 | { |
---|
904 | #ifdef DEBUG |
---|
905 | printf("%sOverrun error is detected!\n", RTT_CTRL_TEXT_BRIGHT_RED); |
---|
906 | #endif |
---|
907 | UART->ICR = USART_ICR_ORECF; |
---|
908 | volatile int unused = UART->RDR & 0xFF; |
---|
909 | return -1; |
---|
910 | } |
---|
911 | if (UART->ISR & USART_ISR_NE) |
---|
912 | { |
---|
913 | #ifdef DEBUG |
---|
914 | printf("%sNoise is detected!\n", RTT_CTRL_TEXT_BRIGHT_RED); |
---|
915 | #endif |
---|
916 | UART->ICR = USART_ICR_NECF; |
---|
917 | return -1; |
---|
918 | } |
---|
919 | if (UART->ISR & USART_ISR_FE) |
---|
920 | { |
---|
921 | #ifdef DEBUG |
---|
922 | printf("%sFrame error is detected!\n", RTT_CTRL_TEXT_BRIGHT_RED); |
---|
923 | #endif |
---|
924 | UART->ICR = USART_ICR_FECF; |
---|
925 | return -1; |
---|
926 | } |
---|
927 | if (UART->ISR & USART_ISR_PE) |
---|
928 | { |
---|
929 | #ifdef DEBUG |
---|
930 | printf("%sParity error is detected!\n", RTT_CTRL_TEXT_BRIGHT_RED); |
---|
931 | #endif |
---|
932 | UART->ICR = USART_ICR_PECF; |
---|
933 | return -1; |
---|
934 | } |
---|
935 | |
---|
936 | return (UART->RDR & 0xFF); |
---|
937 | } |
---|
938 | |
---|
939 | //----------------------------------------------------------------------------- |
---|
940 | |
---|
941 | void Init(void) |
---|
942 | { |
---|
943 | // Systick timer initialization |
---|
944 | SysTick_Config(SystemCoreClock/1000); |
---|
945 | |
---|
946 | #ifdef DEBUG |
---|
947 | printf(RTT_CTRL_CLEAR); |
---|
948 | printf("%sProgram started (%s)\n", RTT_CTRL_TEXT_BRIGHT_GREEN, FW_VERSION); |
---|
949 | #endif |
---|
950 | |
---|
951 | #ifdef DEBUG |
---|
952 | if (RCC->CR & RCC_CR_HSION) printf("%sHSI is turned on.\n", RTT_CTRL_TEXT_BRIGHT_GREEN); |
---|
953 | else |
---|
954 | { |
---|
955 | printf("%sHSI is not turned on! Program stopped!\n", RTT_CTRL_TEXT_BRIGHT_RED); |
---|
956 | TurnErrorLEDOn(500, -1); |
---|
957 | } |
---|
958 | #else |
---|
959 | if (!(RCC->CR & RCC_CR_HSION)) TurnErrorLEDOn(500, -1); |
---|
960 | #endif |
---|
961 | |
---|
962 | #ifdef DEBUG |
---|
963 | if (RCC->CR & RCC_CR_HSIRDY) printf("HSI is ready.\n"); |
---|
964 | else while (!(RCC->CR & RCC_CR_HSIRDY)) printf("%sWaiting for HSI to be ready!\n", RTT_CTRL_TEXT_YELLOW); |
---|
965 | #else |
---|
966 | while (!(RCC->CR & RCC_CR_HSIRDY)); |
---|
967 | #endif |
---|
968 | //printf("Checking RDP level.\n"); |
---|
969 | |
---|
970 | // Checking state of RDP protection |
---|
971 | if (((FLASH->OPTR & FLASH_OPTR_RDP) == 0xAA) || ((FLASH->OPTR & FLASH_OPTR_RDP) == 0xCC)) |
---|
972 | { |
---|
973 | #ifdef DEBUG |
---|
974 | // Checking whether SWD debugger is connected or not |
---|
975 | if (SWD_PORT->IDR & SWD_PIN_MSK) |
---|
976 | { |
---|
977 | #endif |
---|
978 | // Debugger is not connected |
---|
979 | // Is FLASH_CR register locked for writing? |
---|
980 | if (FLASH->CR & FLASH_CR_LOCK) |
---|
981 | { |
---|
982 | // Unlocking FLASH_CR register |
---|
983 | FLASH->KEYR = KEY1; |
---|
984 | FLASH->KEYR = KEY2; |
---|
985 | } |
---|
986 | |
---|
987 | // Unlocking FLASH option register |
---|
988 | if (FLASH->CR & FLASH_CR_OPTLOCK) |
---|
989 | { |
---|
990 | FLASH->OPTKEYR = OPTKEY1; |
---|
991 | FLASH->OPTKEYR = OPTKEY2; |
---|
992 | } |
---|
993 | |
---|
994 | // Setting RDP level to 1 |
---|
995 | FLASH->OPTR &= ~FLASH_OPTR_RDP; |
---|
996 | FLASH->OPTR |= 0xEC; // Any value except 0xAA and 0xCC |
---|
997 | |
---|
998 | while (FLASH->SR & FLASH_SR_BSY1); |
---|
999 | |
---|
1000 | FLASH->CR |= FLASH_CR_OPTSTRT; |
---|
1001 | |
---|
1002 | while (FLASH->SR & FLASH_SR_BSY1); |
---|
1003 | |
---|
1004 | //printf("RDP is set!\n"); |
---|
1005 | |
---|
1006 | // Updating option bytes by resetting of the device |
---|
1007 | FLASH->CR |= FLASH_CR_OBL_LAUNCH; |
---|
1008 | |
---|
1009 | // If we can reach below code then something went wrong |
---|
1010 | TurnErrorLEDOn(100, -1); |
---|
1011 | #ifdef DEBUG |
---|
1012 | } |
---|
1013 | #endif |
---|
1014 | } |
---|
1015 | |
---|
1016 | // Activating clocking for PORT A and PORT B |
---|
1017 | RCC->IOPENR |= RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOBEN | RCC_IOPENR_GPIODEN; |
---|
1018 | |
---|
1019 | // Setting PA9, PA10 and PA12 pins to Alternate Function mode (2) |
---|
1020 | UART_PORT->MODER &= ~GPIOx_MODER(GPIO_MODER_MODE, UART_TX_PIN) & |
---|
1021 | ~GPIOx_MODER(GPIO_MODER_MODE, UART_RX_PIN) & |
---|
1022 | ~GPIOx_MODER(GPIO_MODER_MODE, UART_TX_EN_PIN); |
---|
1023 | UART_PORT->MODER |= (2 << GPIOx_MODER_Pos(GPIO_MODER_MODE, UART_TX_PIN)) | |
---|
1024 | (2 << GPIOx_MODER_Pos(GPIO_MODER_MODE, UART_RX_PIN)) | |
---|
1025 | (2 << GPIOx_MODER_Pos(GPIO_MODER_MODE, UART_TX_EN_PIN)); |
---|
1026 | |
---|
1027 | // Setting pullup for PA10 (RX pin) |
---|
1028 | UART_PORT->PUPDR &= ~GPIOx_PUPDR(GPIO_PUPDR_PUPD, UART_RX_PIN); |
---|
1029 | UART_PORT->PUPDR |= (1<<GPIOx_PUPDR_Pos(GPIO_PUPDR_PUPD, UART_RX_PIN)); |
---|
1030 | |
---|
1031 | // Setting alternate function for PA9, PA10 and PA12 (UART dependant, see MCU datasheet file) |
---|
1032 | #if UART_RX_PIN > 7 |
---|
1033 | UART_PORT->AFR[1] &= ~GPIO_AFRH_AFSEL(GPIO_AFRH_AFSEL, UART_RX_PIN); |
---|
1034 | UART_PORT->AFR[1] |= (UART_RX_ALT_FUNC_NUM << GPIO_AFRH_AFSEL_Pos(GPIO_AFRH_AFSEL, UART_RX_PIN)); |
---|
1035 | #else |
---|
1036 | UART_PORT->AFR[0] &= ~GPIO_AFRL_AFSEL(GPIO_AFRL_AFSEL, UART_RX_PIN); |
---|
1037 | UART_PORT->AFR[0] |= (UART_RX_ALT_FUNC_NUM << GPIO_AFRH_AFSEL_Pos(GPIO_AFRH_AFSEL, UART_RX_PIN)); |
---|
1038 | #endif |
---|
1039 | #if UART_TX_PIN > 7 |
---|
1040 | UART_PORT->AFR[1] &= ~GPIO_AFRH_AFSEL(GPIO_AFRH_AFSEL, UART_TX_PIN); |
---|
1041 | UART_PORT->AFR[1] |= (UART_TX_ALT_FUNC_NUM << GPIO_AFRH_AFSEL_Pos(GPIO_AFRH_AFSEL, UART_TX_PIN)); |
---|
1042 | #else |
---|
1043 | UART_PORT->AFR[0] &= ~GPIO_AFRL_AFSEL(GPIO_AFRL_AFSEL, UART_TX_PIN); |
---|
1044 | UART_PORT->AFR[0] |= (UART_TX_ALT_FUNC_NUM << GPIO_AFRH_AFSEL_Pos(GPIO_AFRH_AFSEL, UART_TX_PIN)); |
---|
1045 | #endif |
---|
1046 | #if UART_TX_EN_PIN > 7 |
---|
1047 | UART_PORT->AFR[1] &= ~GPIO_AFRH_AFSEL(GPIO_AFRH_AFSEL, UART_TX_EN_PIN); |
---|
1048 | UART_PORT->AFR[1] |= (UART_TXEN_ALT_FUNC_NUM << GPIO_AFRH_AFSEL_Pos(GPIO_AFRH_AFSEL, UART_TX_EN_PIN)); |
---|
1049 | #else |
---|
1050 | UART_PORT->AFR[0] &= ~GPIO_AFRL_AFSEL(GPIO_AFRL_AFSEL, UART_TX_EN_PIN); |
---|
1051 | UART_PORT->AFR[0] |= (UART_TXEN_ALT_FUNC_NUM << GPIO_AFRH_AFSEL_Pos(GPIO_AFRH_AFSEL, UART_TX_EN_PIN)); |
---|
1052 | #endif |
---|
1053 | |
---|
1054 | // Setting LED PORT to output for LED |
---|
1055 | BLUE_LED_PORT->MODER &= ~GPIOx_MODER(GPIO_MODER_MODE, BLUE_LED_PIN); |
---|
1056 | RED_LED_PORT->MODER &= ~GPIOx_MODER(GPIO_MODER_MODE, RED_LED_PIN); |
---|
1057 | BLUE_LED_PORT->MODER |= (1 << GPIOx_MODER_Pos(GPIO_MODER_MODE, BLUE_LED_PIN)); |
---|
1058 | RED_LED_PORT->MODER |= (1 << GPIOx_MODER_Pos(GPIO_MODER_MODE, RED_LED_PIN)); |
---|
1059 | |
---|
1060 | // Activating clocking for UART |
---|
1061 | RCC->APBENR2 |= RCC_APBENR2_USART1EN; |
---|
1062 | |
---|
1063 | // Before changing some settings in USART we must make sure that it turned off |
---|
1064 | UART->CR1 &= ~USART_CR1_UE; |
---|
1065 | |
---|
1066 | // Setting 1 start bit, 9 data bits |
---|
1067 | UART->CR1 &= ~USART_CR1_M1; |
---|
1068 | UART->CR1 |= USART_CR1_M0; |
---|
1069 | |
---|
1070 | // Setting oversampling to 16 |
---|
1071 | UART->CR1 &= ~USART_CR1_OVER8; |
---|
1072 | |
---|
1073 | // Enabling parity control with EVEN parity |
---|
1074 | UART->CR1 |= USART_CR1_PCE; |
---|
1075 | |
---|
1076 | // Enabling transmitter and receiver |
---|
1077 | UART->CR1 |= USART_CR1_TE | USART_CR1_RE; |
---|
1078 | |
---|
1079 | UART->CR1 |= USART_CR1_DEAT | USART_CR1_DEDT; |
---|
1080 | |
---|
1081 | // |
---|
1082 | //UART->CR2 |= USART_CR2_SWAP; |
---|
1083 | |
---|
1084 | // Enabling RS485 transmitter driver control |
---|
1085 | UART->CR3 |= USART_CR3_DEM; |
---|
1086 | |
---|
1087 | #ifdef DEBUG |
---|
1088 | // Setting baud rate to 19200 |
---|
1089 | UART->BRR = 833; |
---|
1090 | #else |
---|
1091 | // Setting baud rate to 19200 |
---|
1092 | UART->BRR = 833; |
---|
1093 | #endif |
---|
1094 | |
---|
1095 | // Finally, turning USART on |
---|
1096 | UART->CR1 |= USART_CR1_UE; |
---|
1097 | |
---|
1098 | // Start up sequence |
---|
1099 | for (int i = 0; i < 5; i++) |
---|
1100 | { |
---|
1101 | BLUE_LED_PORT->BSRR = GPIOx_BSRR(GPIO_BSRR_BS, BLUE_LED_PIN); |
---|
1102 | Delay(150); |
---|
1103 | BLUE_LED_PORT->BSRR = GPIOx_BSRR(GPIO_BSRR_BR, BLUE_LED_PIN); |
---|
1104 | Delay(150); |
---|
1105 | } |
---|
1106 | |
---|
1107 | } |
---|
1108 | |
---|
1109 | //----------------------------------------------------------------------------- |
---|
1110 | |
---|
1111 | void TurnErrorLEDOn(uint32_t bp, uint32_t hl) |
---|
1112 | { |
---|
1113 | // Turning off blue led |
---|
1114 | BLUE_LED_PORT->BSRR = GPIOx_BSRR(GPIO_BSRR_BR, BLUE_LED_PIN); |
---|
1115 | uint32_t tickStart = msCounter; |
---|
1116 | |
---|
1117 | while(msCounter - tickStart < hl) |
---|
1118 | { |
---|
1119 | RED_LED_PORT->BSRR = GPIOx_BSRR(GPIO_BSRR_BS, RED_LED_PIN); |
---|
1120 | Delay(bp); |
---|
1121 | RED_LED_PORT->BSRR = GPIOx_BSRR(GPIO_BSRR_BR, RED_LED_PIN); |
---|
1122 | Delay(bp); |
---|
1123 | } |
---|
1124 | } |
---|
1125 | |
---|
1126 | /*************************** End of file ****************************/ |
---|