From a1499f95936a53bf756ca0cf956577fb19fb7139 Mon Sep 17 00:00:00 2001 From: Siddharth Purohit Date: Fri, 11 Jun 2021 14:29:02 +0530 Subject: [PATCH] AP_Bootloader: add support for erasing external flash --- Tools/AP_Bootloader/AP_Bootloader.cpp | 16 ++++++ Tools/AP_Bootloader/bl_protocol.cpp | 81 ++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/Tools/AP_Bootloader/AP_Bootloader.cpp b/Tools/AP_Bootloader/AP_Bootloader.cpp index e028f7c28b..8018f7e54a 100644 --- a/Tools/AP_Bootloader/AP_Bootloader.cpp +++ b/Tools/AP_Bootloader/AP_Bootloader.cpp @@ -32,6 +32,9 @@ #include "bl_protocol.h" #include "can.h" #include +#if EXTERNAL_PROG_FLASH_MB +#include +#endif extern "C" { int main(void); @@ -51,6 +54,10 @@ struct boardinfo board_info = { #define HAL_STAY_IN_BOOTLOADER_VALUE 0 #endif +#if EXTERNAL_PROG_FLASH_MB +AP_FlashIface_JEDEC ext_flash; +#endif + int main(void) { if (BOARD_FLASH_SIZE > 1024 && check_limit_flash_1M()) { @@ -142,6 +149,15 @@ int main(void) #endif flash_init(); + +#if EXTERNAL_PROG_FLASH_MB + while (!ext_flash.init()) { + // keep trying until we get it working + // there's no future without it + chThdSleep(1000); + } +#endif + #if defined(BOOTLOADER_DEV_LIST) while (true) { bootloader(timeout); diff --git a/Tools/AP_Bootloader/bl_protocol.cpp b/Tools/AP_Bootloader/bl_protocol.cpp index 2a3989d25e..c2cdeb3546 100644 --- a/Tools/AP_Bootloader/bl_protocol.cpp +++ b/Tools/AP_Bootloader/bl_protocol.cpp @@ -50,7 +50,9 @@ #include "support.h" #include "can.h" #include - +#if EXTERNAL_PROG_FLASH_MB +#include +#endif // #pragma GCC optimize("O0") @@ -106,6 +108,14 @@ #define PROTO_DEBUG 0x31 // emit debug information - format not defined #define PROTO_SET_BAUD 0x33 // baud rate on uart +// External Flash programming +#if EXTERNAL_PROG_FLASH_MB +#define PROTO_EXTF_ERASE 0x34 // Erase sectors from external flash +#define PROTO_EXTF_PROG_MULTI 0x35 // write bytes at external flash program address and increment +#define PROTO_EXTF_READ_MULTI 0x36 // read bytes at address and increment +#define PROTO_EXTF_GET_CRC 0x37 // compute & return a CRC of data in external flash +#endif + #define PROTO_PROG_MULTI_MAX 64 // maximum PROG_MULTI size #define PROTO_READ_MULTI_MAX 255 // size of the size field @@ -138,6 +148,11 @@ volatile unsigned timer[NTIMERS]; // access on STM32H7 #define RESERVE_LEAD_WORDS 8 + +#if EXTERNAL_PROG_FLASH_MB +extern AP_FlashIface_JEDEC ext_flash; +#endif + /* 1ms timer tick callback */ @@ -569,6 +584,70 @@ bootloader(unsigned timeout) led_set(LED_BLINK); break; + // program data from start of the flash + // + // command: EXTF_ERASE//EOC + // success reply: INSYNC/OK + // invalid reply: INSYNC/INVALID + // readback failure: INSYNC/FAILURE + // + case PROTO_EXTF_ERASE: +#if EXTERNAL_PROG_FLASH_MB + { + if (!done_sync || !CHECK_GET_DEVICE_FINISHED(done_get_device_flags)) { + // lower chance of random data on a uart triggering erase + goto cmd_bad; + } + uint32_t cmd_erase_bytes; + if (cin_word(&cmd_erase_bytes, 100)) { + goto cmd_bad; + } + + // expect EOC + if (!wait_for_eoc(2)) { + goto cmd_bad; + } + uint32_t erased_bytes = 0; + uint32_t sector_number = 0; + uint8_t pct_done = 0; + if (cmd_erase_bytes > (ext_flash.get_sector_size() * ext_flash.get_sector_count())) { + uprintf("Requested to erase more than we can\n"); + goto cmd_bad; + } + uprintf("Erase Command Received\n"); + sync_response(); + cout(&pct_done, sizeof(pct_done)); + // Flash all sectors that encompass the erase_bytes + while (erased_bytes < cmd_erase_bytes) { + uint32_t delay_ms = 0, timeout_ms = 0; + if (!ext_flash.start_sector_erase(sector_number, delay_ms, timeout_ms)) { + goto cmd_fail; + } + uint32_t next_check_ms = AP_HAL::millis() + delay_ms; + while (true) { + cout(&pct_done, sizeof(pct_done)); + if (AP_HAL::millis() > next_check_ms) { + if (!ext_flash.is_device_busy()) { + pct_done = erased_bytes*100/cmd_erase_bytes; + uprintf("PCT DONE: %d\n", pct_done); + break; + } + if ((AP_HAL::millis() + timeout_ms) > next_check_ms) { + // We are out of time, return error + goto cmd_fail; + } + next_check_ms = AP_HAL::millis()+delay_ms; + } + chThdSleep(chTimeMS2I(delay_ms)); + } + erased_bytes += ext_flash.get_sector_size(); + sector_number++; + } + } +#else + goto cmd_bad; +#endif // EXTERNAL_PROG_FLASH_MB + break; // program bytes at current address // // command: PROG_MULTI///EOC