![](/media/cache/profiles/9cplksk_GJzRNOO.gif.50x50_q85.png)
A demonstration of a simple bootloader with SD card. Binary folder already contains precompiled SimpleBootloader for Nucleo-F767ZI under MbedOS 6.15.1. Firmware example for bootloader is here - https://os.mbed.com/users/JohnnyK/code/FirmwareForSimpleBootloader/
Binary folder already contains precompiled SimpleBootloader for Nucleo-F767ZI
main.cpp
- Committer:
- JohnnyK
- Date:
- 2021-12-08
- Revision:
- 1:84522765c238
- Parent:
- 0:58ebce14a984
File content as of revision 1:84522765c238:
/* * Tested with Nudleo-F767Zi and Nudleo-F429ZI * Builded with Mbed Studio 1.4.3 */ #include "mbed.h" //MbedOS 6.15.1 #include "SDBlockDevice.h" #include "FATFileSystem.h" #include "KVStore.h" #include "kvstore_global_api.h" #include <string> #define SD_MOUNT_PATH "sd" #define FIRMWARE_PATH "/" SD_MOUNT_PATH "/" #if !defined(POST_APPLICATION_ADDR) #error "target.restrict_size must be set for your target in mbed_app.json" #endif //Pin order: MOSI, MISO, SCK, CS SDBlockDevice sd(PC_12, PC_11, PC_10, PC_9); //with a problem of init a sd card can be required add "sd.INIT_FREQUENCY": 100000 to Mbed_app.json FATFileSystem fs(SD_MOUNT_PATH); FlashIAP flash; void apply_update(FILE *file, uint32_t address); int main() { printf("Bootloader starts!\n"); printf("About to start the application at 0x%x\r\n", POST_APPLICATION_ADDR); ThisThread::sleep_for(500ms); printf("Bootloader's SD card operations start!\n"); // Init if (0 != sd.init()) { printf("SD card is not present or init failed!\n"); }else{ // Set the frequency if ( 0 != sd.frequency(5000000)) { printf("Error setting frequency \n"); } //Mounting the filesystem... fflush(stdout); if (0 != fs.mount(&sd)){ printf("Mount failed!\n"); }else{ // Display the root directory printf("Opening the root directory... "); fflush(stdout); DIR *d = opendir(SD_MOUNT_PATH); printf("%s\n", (!d ? "Fail :(" : "OK")); if(d){ printf("Firmware files on the SD cards:\n"); while (true) { struct dirent *e = readdir(d); if(!e) break; if(e->d_type == 0x5) printf("%s\n", e->d_name); } printf("Closing the root directory... "); fflush(stdout); printf("%s\n", (closedir(d) < 0 ? "Fail :(" : "OK")); char str[10]; string strr; FILE *firmware; char kv_key[] = {"/kv/key"}; char kv_value[10]; kv_info_t info; while(true){ printf("Please, select one of available files!\n"); scanf("%10s",str); printf("Your request is %s!\n", str); kv_get_info(kv_key, &info); kv_get(kv_key, kv_value, info.size, 0); bool check = true; for(int i=0;str[i]!='\0';i++){ if(str[i]!=kv_value[i]) check = false; } if(check){ printf("This firmware is already loaded!\n"); break; }else{ printf("Finding..."); strr = FIRMWARE_PATH + string(str, 10); firmware = fopen(strr.c_str(), "r"); printf(" %s\n", (!firmware ? "Fail :(" : "OK")); if(firmware){ apply_update(firmware, POST_APPLICATION_ADDR); kv_set(kv_key, str, strlen(str), 0); printf("Closing the firmware file..."); fflush(stdout); printf("%s\n", (fclose(firmware) < 0 ? "Fail :(" : "OK")); break; }else{ printf("The %s not exist on the SD card.\nTry it again!\n", str); } } } }else{ printf("A DIR fail!\n"); } fs.unmount(); } sd.deinit(); } printf("SD card operations end!\nStarting application...\n"); ThisThread::sleep_for(800ms); mbed_start_application(POST_APPLICATION_ADDR); } void apply_update(FILE *file, uint32_t address) { fseek(file, 0, SEEK_END); long len = ftell(file); printf("Firmware size is %ld bytes\r\n", len); fseek(file, 0, SEEK_SET); flash.init(); const uint32_t page_size = flash.get_page_size(); char *page_buffer = new char[page_size]; uint32_t addr = address; uint32_t next_sector = addr + flash.get_sector_size(addr); bool sector_erased = false; size_t pages_flashed = 0; uint32_t percent_done = 0; while (true) { // Read data for this page memset(page_buffer, 0, sizeof(char) * page_size); int size_read = fread(page_buffer, 1, page_size, file); if (size_read <= 0) { break; } // Erase this page if it hasn't been erased if (!sector_erased) { flash.erase(addr, flash.get_sector_size(addr)); sector_erased = true; } // Program page flash.program(page_buffer, addr, page_size); addr += page_size; if (addr >= next_sector) { next_sector = addr + flash.get_sector_size(addr); sector_erased = false; } if (++pages_flashed % 3 == 0) { uint32_t percent_done_new = ftell(file) * 100 / len; if (percent_done != percent_done_new) { percent_done = percent_done_new; printf("Flashed %3ld%%\r", percent_done); } } } printf("Flashed 100%%\r\n"); delete[] page_buffer; flash.deinit(); }