source: ecs_cellMon/Bootloader/SES/main.c @ 3

Last change on this file since 3 was 3, checked in by f.jahn, 20 months ago

fw hinzugfügt-->zed

File size: 44.1 KB
Line 
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
22const uint8_t AES_KEY[16] = {0x5c, 0x38, 0x36, 0x57, 0x60, 0x3d, 0x0e, 0x38, 0x61, 0x1e, 0x4e, 0x21, 0x62, 0x19, 0x47, 0x62};                       
23
24union
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
47union bigEndian
48{
49    uint16_t itself;
50    uint8_t bytes[2];
51};
52
53union flashData
54{
55    uint64_t dwordData[256>>3];
56    uint8_t byteData[256];
57};
58
59// Tick counter
60volatile unsigned int msCounter = 0; 
61
62//-----------------------------------------------------------------------------
63
64void Init(void);
65int16_t WaitForByte(unsigned int toWait);
66void Transmit(uint8_t *pData, int numBytes);
67void TransmitACK(void);
68void TransmitNACK(void);
69void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data);
70void Delay(uint32_t delay_in_ms);
71void TurnErrorLEDOn(uint32_t blink_period, uint32_t how_long_to_keep_blinking);
72void JumpToApplication(void);
73
74//-----------------------------------------------------------------------------
75
76int 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
713void 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
780void Delay(uint32_t D)
781{
782    volatile uint32_t tick_start = msCounter;
783    while (msCounter - tick_start < D);
784}
785
786//-----------------------------------------------------------------------------
787
788void TransmitACK(void)
789{
790    uint8_t TxData = CMD_ACK;
791    Transmit(&TxData, 1);
792}
793
794//-----------------------------------------------------------------------------
795
796void 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  */
810void 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
828void 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
859void SysTick_Handler(void)
860{
861    msCounter++;
862}
863
864//-----------------------------------------------------------------------------
865
866void HardFault_Handler(void)
867{
868    TurnErrorLEDOn(500, -1);
869}
870
871//-----------------------------------------------------------------------------
872
873void NMI_Handler(void)
874{
875    TurnErrorLEDOn(250, -1);
876}
877
878//-----------------------------------------------------------------------------
879
880int16_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
941void 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
1111void 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 ****************************/
Note: See TracBrowser for help on using the repository browser.