Bootload from SD card to sector 0, and jump to sector 24 where new firmware resides
Fork of Panel-Controller-Bootloader by
flash.c@0:c3a652eff606, 2015-04-21 (annotated)
- Committer:
- bonchenko
- Date:
- Tue Apr 21 09:30:11 2015 +0000
- Revision:
- 0:c3a652eff606
Able to remove flash content, write new firmware from sd card, and jump to that new firmware. But its still not running completely
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
bonchenko | 0:c3a652eff606 | 1 | #include "flash.h" |
bonchenko | 0:c3a652eff606 | 2 | #include "usart.h" |
bonchenko | 0:c3a652eff606 | 3 | #include "rtc.h" |
bonchenko | 0:c3a652eff606 | 4 | #include "main.h" |
bonchenko | 0:c3a652eff606 | 5 | |
bonchenko | 0:c3a652eff606 | 6 | uint32_t BlockNbr = 0; |
bonchenko | 0:c3a652eff606 | 7 | uint32_t UserMemoryMask = 0; |
bonchenko | 0:c3a652eff606 | 8 | |
bonchenko | 0:c3a652eff606 | 9 | FLASH_RESULT FlashFirmware(void) |
bonchenko | 0:c3a652eff606 | 10 | { |
bonchenko | 0:c3a652eff606 | 11 | USART_SendString("Flashing...\r\n"); |
bonchenko | 0:c3a652eff606 | 12 | /* Get the number of block (4 or 2 pages) from where the user program will be loaded */ |
bonchenko | 0:c3a652eff606 | 13 | BlockNbr = (ApplicationAddress - 0x08000000) >> 12; |
bonchenko | 0:c3a652eff606 | 14 | UserMemoryMask = ((uint32_t)~((1 << BlockNbr) - 1)); |
bonchenko | 0:c3a652eff606 | 15 | |
bonchenko | 0:c3a652eff606 | 16 | if ((FLASH_GetWriteProtectionOptionByte() & UserMemoryMask) != UserMemoryMask) |
bonchenko | 0:c3a652eff606 | 17 | { |
bonchenko | 0:c3a652eff606 | 18 | FLASH_DisableWriteProtectionPages(); |
bonchenko | 0:c3a652eff606 | 19 | } |
bonchenko | 0:c3a652eff606 | 20 | |
bonchenko | 0:c3a652eff606 | 21 | FATFS fatfs; |
bonchenko | 0:c3a652eff606 | 22 | FIL file; |
bonchenko | 0:c3a652eff606 | 23 | u8 buffer[1024]; |
bonchenko | 0:c3a652eff606 | 24 | UINT btr = 1024; |
bonchenko | 0:c3a652eff606 | 25 | UINT br = 0; |
bonchenko | 0:c3a652eff606 | 26 | UINT index = 0; |
bonchenko | 0:c3a652eff606 | 27 | |
bonchenko | 0:c3a652eff606 | 28 | USART_SendString("F_Mount\r\n"); |
bonchenko | 0:c3a652eff606 | 29 | FRESULT result = f_mount(0, &fatfs); |
bonchenko | 0:c3a652eff606 | 30 | USART_SendString("F_Mount finished\r\n"); |
bonchenko | 0:c3a652eff606 | 31 | |
bonchenko | 0:c3a652eff606 | 32 | if(result == FR_OK) |
bonchenko | 0:c3a652eff606 | 33 | { |
bonchenko | 0:c3a652eff606 | 34 | USART_SendString("FR OK\r\n"); |
bonchenko | 0:c3a652eff606 | 35 | TCHAR filename[13] = "firmware.bin"; |
bonchenko | 0:c3a652eff606 | 36 | |
bonchenko | 0:c3a652eff606 | 37 | USART_SendString("Opening file...\r\n"); |
bonchenko | 0:c3a652eff606 | 38 | result = f_open(&file, (TCHAR*)filename, FA_READ); |
bonchenko | 0:c3a652eff606 | 39 | USART_SendString("Opening file finished\r\n"); |
bonchenko | 0:c3a652eff606 | 40 | |
bonchenko | 0:c3a652eff606 | 41 | if(result == FR_OK) |
bonchenko | 0:c3a652eff606 | 42 | { |
bonchenko | 0:c3a652eff606 | 43 | USART_SendString("FR Opened\r\n"); |
bonchenko | 0:c3a652eff606 | 44 | FLASH_Unlock(); |
bonchenko | 0:c3a652eff606 | 45 | FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR | FLASH_FLAG_BANK1_PGERR | FLASH_FLAG_BANK1_BSY | FLASH_FLAG_BANK1_EOP | FLASH_FLAG_BANK1_WRPRTERR); |
bonchenko | 0:c3a652eff606 | 46 | |
bonchenko | 0:c3a652eff606 | 47 | FLASH_Status FLASHStatus = FLASH_COMPLETE; |
bonchenko | 0:c3a652eff606 | 48 | uint32_t eraseCounter = 0; |
bonchenko | 0:c3a652eff606 | 49 | uint32_t writeAddress = ApplicationAddress; |
bonchenko | 0:c3a652eff606 | 50 | uint32_t flashValue = 0; |
bonchenko | 0:c3a652eff606 | 51 | |
bonchenko | 0:c3a652eff606 | 52 | // Calculate how many flash pages to erase |
bonchenko | 0:c3a652eff606 | 53 | uint32_t pages = FLASH_PagesMask(file.fsize) + 1; |
bonchenko | 0:c3a652eff606 | 54 | |
bonchenko | 0:c3a652eff606 | 55 | USART_SendString("Erasing flash...\r\n"); |
bonchenko | 0:c3a652eff606 | 56 | // Erase the flash pages |
bonchenko | 0:c3a652eff606 | 57 | for (eraseCounter = 0; (eraseCounter < pages) && (FLASHStatus == FLASH_COMPLETE); eraseCounter++) |
bonchenko | 0:c3a652eff606 | 58 | { |
bonchenko | 0:c3a652eff606 | 59 | FLASHStatus = FLASH_ErasePage(ApplicationAddress + (PAGE_SIZE * eraseCounter)); |
bonchenko | 0:c3a652eff606 | 60 | } |
bonchenko | 0:c3a652eff606 | 61 | |
bonchenko | 0:c3a652eff606 | 62 | USART_SendString("Writing flash...\r\n"); |
bonchenko | 0:c3a652eff606 | 63 | do |
bonchenko | 0:c3a652eff606 | 64 | { |
bonchenko | 0:c3a652eff606 | 65 | //Read the data from the file |
bonchenko | 0:c3a652eff606 | 66 | result = f_read(&file, &buffer, btr, &br); |
bonchenko | 0:c3a652eff606 | 67 | |
bonchenko | 0:c3a652eff606 | 68 | if(result == FR_OK) |
bonchenko | 0:c3a652eff606 | 69 | { |
bonchenko | 0:c3a652eff606 | 70 | // Led1On(); |
bonchenko | 0:c3a652eff606 | 71 | |
bonchenko | 0:c3a652eff606 | 72 | for(index = 0; index < br; index = index + 4) |
bonchenko | 0:c3a652eff606 | 73 | { |
bonchenko | 0:c3a652eff606 | 74 | //Flash Data |
bonchenko | 0:c3a652eff606 | 75 | flashValue = buffer[index + 3] << 24; |
bonchenko | 0:c3a652eff606 | 76 | flashValue += buffer[index + 2] << 16; |
bonchenko | 0:c3a652eff606 | 77 | flashValue += buffer[index + 1] << 8; |
bonchenko | 0:c3a652eff606 | 78 | flashValue += buffer[index]; |
bonchenko | 0:c3a652eff606 | 79 | |
bonchenko | 0:c3a652eff606 | 80 | FLASHStatus = FLASH_ProgramWord(writeAddress, flashValue); |
bonchenko | 0:c3a652eff606 | 81 | |
bonchenko | 0:c3a652eff606 | 82 | if (*(uint32_t*)writeAddress != flashValue) |
bonchenko | 0:c3a652eff606 | 83 | { |
bonchenko | 0:c3a652eff606 | 84 | return FLASH_MEMORY_MISMATCH; |
bonchenko | 0:c3a652eff606 | 85 | } |
bonchenko | 0:c3a652eff606 | 86 | |
bonchenko | 0:c3a652eff606 | 87 | writeAddress += 4; |
bonchenko | 0:c3a652eff606 | 88 | } |
bonchenko | 0:c3a652eff606 | 89 | } |
bonchenko | 0:c3a652eff606 | 90 | else |
bonchenko | 0:c3a652eff606 | 91 | { |
bonchenko | 0:c3a652eff606 | 92 | return FLASH_DISK_ERR; |
bonchenko | 0:c3a652eff606 | 93 | } |
bonchenko | 0:c3a652eff606 | 94 | } |
bonchenko | 0:c3a652eff606 | 95 | while(br == btr); |
bonchenko | 0:c3a652eff606 | 96 | |
bonchenko | 0:c3a652eff606 | 97 | USART_SendString("Closing file\r\n"); |
bonchenko | 0:c3a652eff606 | 98 | // Close the file |
bonchenko | 0:c3a652eff606 | 99 | result = f_close(&file); |
bonchenko | 0:c3a652eff606 | 100 | |
bonchenko | 0:c3a652eff606 | 101 | USART_SendString("Deleting file\r\n"); |
bonchenko | 0:c3a652eff606 | 102 | // Delete the file |
bonchenko | 0:c3a652eff606 | 103 | result = f_unlink((TCHAR*)filename); |
bonchenko | 0:c3a652eff606 | 104 | |
bonchenko | 0:c3a652eff606 | 105 | // Led1Flash(3, 2000); |
bonchenko | 0:c3a652eff606 | 106 | } |
bonchenko | 0:c3a652eff606 | 107 | else |
bonchenko | 0:c3a652eff606 | 108 | { |
bonchenko | 0:c3a652eff606 | 109 | USART_SendString("No File...\r\n"); |
bonchenko | 0:c3a652eff606 | 110 | return FLASH_NO_FILE; |
bonchenko | 0:c3a652eff606 | 111 | } |
bonchenko | 0:c3a652eff606 | 112 | } |
bonchenko | 0:c3a652eff606 | 113 | else |
bonchenko | 0:c3a652eff606 | 114 | { |
bonchenko | 0:c3a652eff606 | 115 | return FLASH_NO_SD_CARD; |
bonchenko | 0:c3a652eff606 | 116 | } |
bonchenko | 0:c3a652eff606 | 117 | |
bonchenko | 0:c3a652eff606 | 118 | return FLASH_OK; |
bonchenko | 0:c3a652eff606 | 119 | } |
bonchenko | 0:c3a652eff606 | 120 | |
bonchenko | 0:c3a652eff606 | 121 | uint32_t CheckFirmware(FIL *file) |
bonchenko | 0:c3a652eff606 | 122 | { |
bonchenko | 0:c3a652eff606 | 123 | |
bonchenko | 0:c3a652eff606 | 124 | return 1; |
bonchenko | 0:c3a652eff606 | 125 | } |
bonchenko | 0:c3a652eff606 | 126 | |
bonchenko | 0:c3a652eff606 | 127 | uint32_t FLASH_PagesMask(__IO uint32_t Size) |
bonchenko | 0:c3a652eff606 | 128 | { |
bonchenko | 0:c3a652eff606 | 129 | uint32_t pagenumber = 0x0; |
bonchenko | 0:c3a652eff606 | 130 | uint32_t size = Size; |
bonchenko | 0:c3a652eff606 | 131 | |
bonchenko | 0:c3a652eff606 | 132 | if ((size % PAGE_SIZE) != 0) |
bonchenko | 0:c3a652eff606 | 133 | { |
bonchenko | 0:c3a652eff606 | 134 | pagenumber = (size / PAGE_SIZE) + 1; |
bonchenko | 0:c3a652eff606 | 135 | } |
bonchenko | 0:c3a652eff606 | 136 | else |
bonchenko | 0:c3a652eff606 | 137 | { |
bonchenko | 0:c3a652eff606 | 138 | pagenumber = size / PAGE_SIZE; |
bonchenko | 0:c3a652eff606 | 139 | } |
bonchenko | 0:c3a652eff606 | 140 | |
bonchenko | 0:c3a652eff606 | 141 | return pagenumber; |
bonchenko | 0:c3a652eff606 | 142 | } |
bonchenko | 0:c3a652eff606 | 143 | |
bonchenko | 0:c3a652eff606 | 144 | void FLASH_DisableWriteProtectionPages(void) |
bonchenko | 0:c3a652eff606 | 145 | { |
bonchenko | 0:c3a652eff606 | 146 | uint32_t useroptionbyte = 0, WRPR = 0; |
bonchenko | 0:c3a652eff606 | 147 | uint16_t var1 = OB_IWDG_SW, var2 = OB_STOP_NoRST, var3 = OB_STDBY_NoRST; |
bonchenko | 0:c3a652eff606 | 148 | FLASH_Status status = FLASH_BUSY; |
bonchenko | 0:c3a652eff606 | 149 | |
bonchenko | 0:c3a652eff606 | 150 | WRPR = FLASH_GetWriteProtectionOptionByte(); |
bonchenko | 0:c3a652eff606 | 151 | |
bonchenko | 0:c3a652eff606 | 152 | /* Test if user memory is write protected */ |
bonchenko | 0:c3a652eff606 | 153 | if ((WRPR & UserMemoryMask) != UserMemoryMask) |
bonchenko | 0:c3a652eff606 | 154 | { |
bonchenko | 0:c3a652eff606 | 155 | useroptionbyte = FLASH_GetUserOptionByte(); |
bonchenko | 0:c3a652eff606 | 156 | |
bonchenko | 0:c3a652eff606 | 157 | UserMemoryMask |= WRPR; |
bonchenko | 0:c3a652eff606 | 158 | |
bonchenko | 0:c3a652eff606 | 159 | status = FLASH_EraseOptionBytes(); |
bonchenko | 0:c3a652eff606 | 160 | |
bonchenko | 0:c3a652eff606 | 161 | if (UserMemoryMask != 0xFFFFFFFF) |
bonchenko | 0:c3a652eff606 | 162 | { |
bonchenko | 0:c3a652eff606 | 163 | status = FLASH_EnableWriteProtection((uint32_t)~UserMemoryMask); |
bonchenko | 0:c3a652eff606 | 164 | } |
bonchenko | 0:c3a652eff606 | 165 | |
bonchenko | 0:c3a652eff606 | 166 | /* Test if user Option Bytes are programmed */ |
bonchenko | 0:c3a652eff606 | 167 | if ((useroptionbyte & 0x07) != 0x07) |
bonchenko | 0:c3a652eff606 | 168 | { |
bonchenko | 0:c3a652eff606 | 169 | /* Restore user Option Bytes */ |
bonchenko | 0:c3a652eff606 | 170 | if ((useroptionbyte & 0x01) == 0x0) |
bonchenko | 0:c3a652eff606 | 171 | { |
bonchenko | 0:c3a652eff606 | 172 | var1 = OB_IWDG_HW; |
bonchenko | 0:c3a652eff606 | 173 | } |
bonchenko | 0:c3a652eff606 | 174 | if ((useroptionbyte & 0x02) == 0x0) |
bonchenko | 0:c3a652eff606 | 175 | { |
bonchenko | 0:c3a652eff606 | 176 | var2 = OB_STOP_RST; |
bonchenko | 0:c3a652eff606 | 177 | } |
bonchenko | 0:c3a652eff606 | 178 | if ((useroptionbyte & 0x04) == 0x0) |
bonchenko | 0:c3a652eff606 | 179 | { |
bonchenko | 0:c3a652eff606 | 180 | var3 = OB_STDBY_RST; |
bonchenko | 0:c3a652eff606 | 181 | } |
bonchenko | 0:c3a652eff606 | 182 | |
bonchenko | 0:c3a652eff606 | 183 | FLASH_UserOptionByteConfig(var1, var2, var3); |
bonchenko | 0:c3a652eff606 | 184 | } |
bonchenko | 0:c3a652eff606 | 185 | |
bonchenko | 0:c3a652eff606 | 186 | if (status == FLASH_COMPLETE) |
bonchenko | 0:c3a652eff606 | 187 | { |
bonchenko | 0:c3a652eff606 | 188 | /* Generate System Reset to load the new option byte values */ |
bonchenko | 0:c3a652eff606 | 189 | NVIC_SystemReset(); |
bonchenko | 0:c3a652eff606 | 190 | } |
bonchenko | 0:c3a652eff606 | 191 | } |
bonchenko | 0:c3a652eff606 | 192 | } |