diff --git a/radio/src/boards/helloradio-h750/board.h b/radio/src/boards/helloradio-h750/board.h index 5c3f986318c..3105ae6bac0 100644 --- a/radio/src/boards/helloradio-h750/board.h +++ b/radio/src/boards/helloradio-h750/board.h @@ -61,7 +61,7 @@ void getCPUUniqueID(char * s); #define FLASH_PAGESIZE 256 void unlockFlash(); void lockFlash(); -void flashWrite(uint32_t * address, const uint32_t * buffer); +bool flashWrite(uint32_t * address, const uint32_t * buffer); uint32_t isFirmwareStart(const uint8_t * buffer); uint32_t isBootloaderStart(const uint8_t * buffer); diff --git a/radio/src/boards/jumper-h750/board.h b/radio/src/boards/jumper-h750/board.h index 354d4bbd9b6..556dcda7f35 100644 --- a/radio/src/boards/jumper-h750/board.h +++ b/radio/src/boards/jumper-h750/board.h @@ -60,7 +60,7 @@ void getCPUUniqueID(char * s); #define FLASH_PAGESIZE 256 void unlockFlash(); void lockFlash(); -void flashWrite(uint32_t * address, const uint32_t * buffer); +bool flashWrite(uint32_t * address, const uint32_t * buffer); uint32_t isFirmwareStart(const uint8_t * buffer); uint32_t isBootloaderStart(const uint8_t * buffer); diff --git a/radio/src/boards/rm-h750/board.h b/radio/src/boards/rm-h750/board.h index a987c59600c..86e49d82aff 100644 --- a/radio/src/boards/rm-h750/board.h +++ b/radio/src/boards/rm-h750/board.h @@ -60,7 +60,7 @@ void getCPUUniqueID(char * s); #define FLASH_PAGESIZE 256 void unlockFlash(); void lockFlash(); -void flashWrite(uint32_t * address, const uint32_t * buffer); +bool flashWrite(uint32_t * address, const uint32_t * buffer); uint32_t isFirmwareStart(const uint8_t * buffer); uint32_t isBootloaderStart(const uint8_t * buffer); diff --git a/radio/src/boards/senduwing-h750/board.h b/radio/src/boards/senduwing-h750/board.h index 17a76725e25..137b63bdc5b 100644 --- a/radio/src/boards/senduwing-h750/board.h +++ b/radio/src/boards/senduwing-h750/board.h @@ -60,7 +60,7 @@ void getCPUUniqueID(char * s); #define FLASH_PAGESIZE 256 void unlockFlash(); void lockFlash(); -void flashWrite(uint32_t * address, const uint32_t * buffer); +bool flashWrite(uint32_t * address, const uint32_t * buffer); uint32_t isFirmwareStart(const uint8_t * buffer); uint32_t isBootloaderStart(const uint8_t * buffer); diff --git a/radio/src/bootloader/bin_fw_files.cpp b/radio/src/bootloader/bin_fw_files.cpp index 7580bcab741..35a07416b6a 100644 --- a/radio/src/bootloader/bin_fw_files.cpp +++ b/radio/src/bootloader/bin_fw_files.cpp @@ -53,13 +53,14 @@ static FWFileInfo fwFiles[MAX_FW_FILES]; static uint8_t Block_buffer[BLOCK_LEN]; static UINT BlockCount; -static void flashWriteBlock() +static bool flashWriteBlock() { // TODO: use some board provided driver instead uint32_t blockOffset = 0; #if !defined(SIMU) while (BlockCount) { - flashWrite((uint32_t *)firmwareAddress, (uint32_t *)&Block_buffer[blockOffset]); + if (!flashWrite((uint32_t *)firmwareAddress, (uint32_t *)&Block_buffer[blockOffset])) + return false; blockOffset += FLASH_PAGESIZE; firmwareAddress += FLASH_PAGESIZE; if (BlockCount > FLASH_PAGESIZE) { @@ -70,6 +71,7 @@ static void flashWriteBlock() } } #endif // SIMU + return true; } void sdInit(void) @@ -267,17 +269,24 @@ void firmwareInitWrite(uint32_t index) firmwareWritten = 0; } -bool firmwareWriteBlock(uint32_t* progress) +FlashWriteRes firmwareWriteBlock(uint32_t* progress) { - flashWriteBlock(); + if (!flashWriteBlock()) return FW_ERROR; + firmwareWritten += sizeof(Block_buffer); *progress = (100 * firmwareWritten) / firmwareSize; - readFirmwareFile(); + // a read error or a short file must not be reported as success + if (readFirmwareFile() != FR_OK) { + return FW_ERROR; + } + if (BlockCount == 0 && firmwareWritten < firmwareSize) { + return FW_ERROR; + } if (BlockCount == 0 || firmwareWritten >= FLASHSIZE - BOOTLOADER_SIZE) { - return true; + return FW_DONE; } - return false; + return FW_IN_PROGRESS; } diff --git a/radio/src/bootloader/boot.h b/radio/src/bootloader/boot.h index 5c740a5a8ab..8918956c251 100644 --- a/radio/src/bootloader/boot.h +++ b/radio/src/bootloader/boot.h @@ -53,6 +53,7 @@ enum BootloaderState { ST_FLASH_CHECK, ST_FLASHING, ST_FLASH_DONE, + ST_FLASH_ERROR, ST_RESTORE_MENU, ST_USB, #if defined(SPI_FLASH) diff --git a/radio/src/bootloader/boot_menu.cpp b/radio/src/bootloader/boot_menu.cpp index 74896b5a4e9..ecdb2ce361d 100644 --- a/radio/src/bootloader/boot_menu.cpp +++ b/radio/src/bootloader/boot_menu.cpp @@ -96,6 +96,7 @@ void bootloaderMenu() uint8_t index = 0; FRESULT fr; uint32_t nameCount = 0; + uint32_t progress = 0; sdInit(); @@ -107,7 +108,8 @@ void bootloaderMenu() next_frame += FRAME_INTERVAL_MS; if (state != ST_USB && state != ST_FLASHING - && state != ST_FLASH_DONE && state != ST_RADIO_MENU) { + && state != ST_FLASH_DONE && state != ST_FLASH_ERROR + && state != ST_RADIO_MENU) { if (usbPlugged()) { state = ST_USB; #if !defined(SIMU) @@ -244,14 +246,16 @@ void bootloaderMenu() } else if (result == 1) { // confirmed firmwareInitWrite(vpos); + progress = 0; state = ST_FLASHING; } } else if (state == ST_FLASHING) { - uint32_t progress = 0; - bool done = firmwareWriteBlock(&progress); + FlashWriteRes res = firmwareWriteBlock(&progress); bootloaderDrawScreen(state, progress); - if(done) { + if (res == FW_DONE) { state = ST_FLASH_DONE; + } else if (res == FW_ERROR) { + state = ST_FLASH_ERROR; } #if defined(SPI_FLASH) } else if (state == ST_CLEAR_FLASH_CHECK) { @@ -282,13 +286,15 @@ void bootloaderMenu() } } - if (state == ST_FLASH_DONE) { + if (state == ST_FLASH_DONE || state == ST_FLASH_ERROR) { + BootloaderState drawn = state; + if (event == EVT_KEY_BREAK(KEY_EXIT) || event == EVT_KEY_BREAK(KEY_ENTER)) { state = ST_START; vpos = 0; } - bootloaderDrawScreen(state, 100); + bootloaderDrawScreen(drawn, drawn == ST_FLASH_DONE ? 100 : progress); } if (event == EVT_KEY_LONG(KEY_EXIT)) { diff --git a/radio/src/bootloader/firmware_files.h b/radio/src/bootloader/firmware_files.h index 4475b13d3d4..560e5135b11 100644 --- a/radio/src/bootloader/firmware_files.h +++ b/radio/src/bootloader/firmware_files.h @@ -69,7 +69,15 @@ enum FlashCheckRes { }; FlashCheckRes checkFirmwareFile(unsigned int index, FlashCheckRes res); +enum FlashWriteRes { + FW_IN_PROGRESS=0, + FW_DONE, + FW_ERROR +}; + void firmwareInitWrite(uint32_t index); bool firmwareEraseBlock(uint32_t* progress); -bool firmwareWriteBlock(uint32_t* progress); + +// Write the block currently in the buffer, then fetch the next one +FlashWriteRes firmwareWriteBlock(uint32_t* progress); diff --git a/radio/src/gui/colorlcd/boot_menu.cpp b/radio/src/gui/colorlcd/boot_menu.cpp index ff174d41ed1..2ae8e722ce0 100644 --- a/radio/src/gui/colorlcd/boot_menu.cpp +++ b/radio/src/gui/colorlcd/boot_menu.cpp @@ -341,16 +341,20 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str) lcd.drawText(USB_TXT_X, y + USB_PLG_TXT_YO, TR_BL_USB_CONNECTED, USB_TXT_ALIGN | BL_FOREGROUND); } else if (st == ST_FILE_LIST || st == ST_DIR_CHECK || st == ST_FLASH_CHECK || - st == ST_FLASHING || st == ST_FLASH_DONE) { + st == ST_FLASHING || st == ST_FLASH_DONE || st == ST_FLASH_ERROR) { bootloaderDrawTitle(LV_SYMBOL_SD_CARD " /FIRMWARE"); - if (st == ST_FLASHING || st == ST_FLASH_DONE) { + if (st == ST_FLASHING || st == ST_FLASH_DONE || st == ST_FLASH_ERROR) { LcdFlags color = BL_RED; if (st == ST_FLASH_DONE) { color = BL_GREEN; opt = 100; // Completed > 100% + } else if (st == ST_FLASH_ERROR) { + // the bar stays where the write gave up + lcd.drawText(LCD_W / 2, (LCD_H - PROGRESS_H) / 2 - EdgeTxStyles::STD_FONT_HEIGHT, + LV_SYMBOL_CLOSE " " TR_BL_WRITING_FAILED, CENTERED | BL_FOREGROUND); } lcd.drawRect(PROGRESS_X, (LCD_H - PROGRESS_H) / 2, PROGRESS_W, PROGRESS_H, LINE_H, SOLID, BL_SELECTED); @@ -405,6 +409,9 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str) else if (st == ST_FLASH_DONE) { pos = lcd.drawText(FOOTER_X1, LCD_H - FOOTER_Y1, LV_SYMBOL_CHARGE " " TR_BL_WRITING_COMPL, FOOTER_ALIGN1 | BL_FOREGROUND); } + else if (st == ST_FLASH_ERROR) { + pos = lcd.drawText(FOOTER_X1, LCD_H - FOOTER_Y1, LV_SYMBOL_CHARGE " " TR_BL_RETRY_OR_DFU, FOOTER_ALIGN1 | BL_FOREGROUND); + } } #if LANDSCAPE pos = 0; diff --git a/radio/src/gui/common/stdlcd/boot_menu.cpp b/radio/src/gui/common/stdlcd/boot_menu.cpp index dedd6093862..853c1357a9b 100644 --- a/radio/src/gui/common/stdlcd/boot_menu.cpp +++ b/radio/src/gui/common/stdlcd/boot_menu.cpp @@ -130,6 +130,10 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char *str) else if (st == ST_FLASH_DONE) { lcdDrawCenteredText(4 * FH, TR_BL_WRITING_COMPL); } + else if (st == ST_FLASH_ERROR) { + lcdDrawCenteredText(4 * FH, TR_BL_WRITING_FAILED); + lcdDrawCenteredText(6 * FH, TR_BL_RETRY_OR_DFU); + } } uint32_t bootloaderGetMenuItemCount(int baseCount) diff --git a/radio/src/io/bootloader_flash.cpp b/radio/src/io/bootloader_flash.cpp index 18340e00dbc..1064d6edc0d 100644 --- a/radio/src/io/bootloader_flash.cpp +++ b/radio/src/io/bootloader_flash.cpp @@ -64,6 +64,7 @@ void BootloaderFirmwareUpdate::flashFirmware(const char * filename, ProgressHand FIL file; uint8_t buffer[1024]; UINT count; + bool success = true; pulsesStop(); @@ -81,22 +82,29 @@ void BootloaderFirmwareUpdate::flashFirmware(const char * filename, ProgressHand if (f_read(&file, buffer, sizeof(buffer), &count) != FR_OK) { POPUP_WARNING(STR_SDCARD_ERROR); + success = false; break; } if (count != sizeof(buffer) && !f_eof(&file)) { POPUP_WARNING(STR_SDCARD_ERROR); + success = false; break; } if (i == 0 && !isBootloaderStart(buffer)) { POPUP_WARNING(STR_INCOMPATIBLE); + success = false; break; } - for (UINT j = 0; j < count; j += FLASH_PAGESIZE) { + for (UINT j = 0; j < count && success; j += FLASH_PAGESIZE) { WDG_ENABLE(3000); - flashWrite(CONVERT_UINT_PTR(BOOTLOADER_ADDRESS + i + j), CONVERT_UINT_PTR(buffer + j)); + success = flashWrite(CONVERT_UINT_PTR(BOOTLOADER_ADDRESS + i + j), CONVERT_UINT_PTR(buffer + j)); WDG_ENABLE(WDG_DURATION); } + if (!success) { + POPUP_WARNING(STR_FIRMWARE_UPDATE_ERROR); + break; + } progressHandler("Bootloader", STR_WRITING, i, flash_size); // Reached end-of-file @@ -107,7 +115,7 @@ void BootloaderFirmwareUpdate::flashFirmware(const char * filename, ProgressHand #endif } - POPUP_INFORMATION(STR_FIRMWARE_UPDATE_SUCCESS); + if (success) POPUP_INFORMATION(STR_FIRMWARE_UPDATE_SUCCESS); watchdogSuspend(0); WDG_RESET(); diff --git a/radio/src/targets/c14/board.h b/radio/src/targets/c14/board.h index f9193a0dcaf..133a52277fc 100644 --- a/radio/src/targets/c14/board.h +++ b/radio/src/targets/c14/board.h @@ -60,7 +60,7 @@ void getCPUUniqueID(char * s); #define FLASH_PAGESIZE 256 void unlockFlash(); void lockFlash(); -void flashWrite(uint32_t * address, const uint32_t * buffer); +bool flashWrite(uint32_t * address, const uint32_t * buffer); uint32_t isFirmwareStart(const uint8_t * buffer); uint32_t isBootloaderStart(const uint8_t * buffer); diff --git a/radio/src/targets/common/arm/stm32/flash_driver.cpp b/radio/src/targets/common/arm/stm32/flash_driver.cpp index cc41ad11ed9..776ff2e86f6 100644 --- a/radio/src/targets/common/arm/stm32/flash_driver.cpp +++ b/radio/src/targets/common/arm/stm32/flash_driver.cpp @@ -85,6 +85,82 @@ static uint32_t stm32_flash_get_sector_size(uint32_t sector) return 128 * 1024; } +// twice the datasheet maximum for a 128 KB sector erase at x32 parallelism +// (2 s, DS9405 Table 48); the driver never issues a bank or mass erase +#define FLASH_TIMEOUT_MS 4000 + +#if defined(FLASH_FLAG_RDERR) + #define _FLASH_FLAG_RDERR FLASH_FLAG_RDERR +#else + #define _FLASH_FLAG_RDERR 0U +#endif + +// Error flags are sticky until written with 1, so one left over by an earlier +// access since reset (e.g. a stray write to flash, which sets PGSERR) would +// abort the very next erase/program. Clear them before starting an operation. +static void flash_drv_clear_errors() +{ + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | + FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | + FLASH_FLAG_PGSERR | _FLASH_FLAG_RDERR); +} + +static bool flash_drv_wait_last_op() +{ + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + + uint32_t start = DWT->CYCCNT; + uint32_t timeout_cycles = + (uint32_t)(FLASH_TIMEOUT_MS * (SystemCoreClock / 1000UL)); + + while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + if ((DWT->CYCCNT - start) > timeout_cycles) { + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | + FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | + FLASH_FLAG_PGSERR); + return false; + } + } + + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); + + if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | + FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR)) { + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | + FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR | + FLASH_FLAG_EOP); + return false; + } + + return true; +} + +// ES0206 2.2.15: on dual bank devices the data cache may be corrupted by a +// read-while-write, so it must be disabled while flash is erased/programmed +// and reset before being enabled again. +static bool flash_drv_disable_dcache() +{ + bool enabled = (FLASH->ACR & FLASH_ACR_DCEN) != 0; + if (enabled) FLASH->ACR &= ~FLASH_ACR_DCEN; + return enabled; +} + +static void flash_drv_flush_caches(bool dcache_enabled) +{ + if (FLASH->ACR & FLASH_ACR_ICEN) { + FLASH->ACR &= ~FLASH_ACR_ICEN; + FLASH->ACR |= FLASH_ACR_ICRST; + FLASH->ACR &= ~FLASH_ACR_ICRST; + FLASH->ACR |= FLASH_ACR_ICEN; + } + if (dcache_enabled) { + FLASH->ACR |= FLASH_ACR_DCRST; + FLASH->ACR &= ~FLASH_ACR_DCRST; + FLASH->ACR |= FLASH_ACR_DCEN; + } +} + #elif defined(STM32H7) || defined(STM32H7RS) static uint32_t stm32_flash_get_sector(uint32_t address) @@ -129,6 +205,43 @@ static inline void stm32_flash_lock() { HAL_FLASH_Lock(); } static int stm32_flash_erase_sector(uint32_t address) { + int ret = 0; + +#if defined(STM32F2) || defined(STM32F4) + + uint32_t sector = stm32_flash_get_sector(address); + + __disable_irq(); + __DSB(); + + stm32_flash_unlock(); + flash_drv_clear_errors(); + + bool dcache = flash_drv_disable_dcache(); + + if (sector > 11) sector += 4; + + CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE); + FLASH->CR |= FLASH_PSIZE_WORD; + CLEAR_BIT(FLASH->CR, FLASH_CR_SNB); + FLASH->CR |= FLASH_CR_SER | (sector << FLASH_CR_SNB_Pos); + FLASH->CR |= FLASH_CR_STRT; + + if (!flash_drv_wait_last_op()) { + ret = -1; + } + + CLEAR_BIT(FLASH->CR, FLASH_CR_SER | FLASH_CR_SNB); + + __DSB(); + __enable_irq(); + + flash_drv_flush_caches(dcache); + + stm32_flash_lock(); + +#else + FLASH_EraseInitTypeDef eraseInit; eraseInit.TypeErase = FLASH_TYPEERASE_SECTORS; eraseInit.Sector = stm32_flash_get_sector(address); @@ -142,15 +255,20 @@ static int stm32_flash_erase_sector(uint32_t address) eraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3; #endif - int ret = 0; uint32_t sector_errors = 0; + // Interrupts must stay enabled here: the HAL timeout counts HAL_GetTick(), + // which only advances in the ms timer interrupt. Nothing needs masking, as + // code and vectors run from TCM/SDRAM, never from the bank being erased. stm32_flash_unlock(); if (HAL_FLASHEx_Erase(&eraseInit, §or_errors) != HAL_OK) { ret = -1; } stm32_flash_lock(); + +#endif + return ret; } @@ -162,18 +280,57 @@ static int stm32_flash_erase_sector(uint32_t address) #define FLASH_PROG_WORDS 4UL #define _FLASH_PROGRAM(address, p_data) \ HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, address, (uintptr_t)p_data) -#else - #define FLASH_PROG_WORDS 1UL - #define _FLASH_PROGRAM(address, p_data) \ - HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, *p_data) #endif static int stm32_flash_program(uint32_t address, void* data, uint32_t len) { + int ret = 0; + +#if defined(STM32F2) || defined(STM32F4) + uint32_t* p_data = (uint32_t*)data; uint32_t end_addr = address + len; - int ret = 0; + __disable_irq(); + __DSB(); + stm32_flash_unlock(); + flash_drv_clear_errors(); + + bool dcache = flash_drv_disable_dcache(); + + while (address < end_addr) { + CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE); + FLASH->CR |= FLASH_PSIZE_WORD; + FLASH->CR |= FLASH_CR_PG; + + *(__IO uint32_t*)address = *p_data; + + // PG must be cleared even on failure, or the next erase sees PG+SER + bool ok = flash_drv_wait_last_op(); + CLEAR_BIT(FLASH->CR, FLASH_CR_PG); + + if (!ok) { + ret = -1; + break; + } + + address += sizeof(uint32_t); + p_data++; + } + + __DSB(); + __enable_irq(); + + flash_drv_flush_caches(dcache); + + stm32_flash_lock(); + +#else + + uint32_t* p_data = (uint32_t*)data; + uint32_t end_addr = address + len; + + // interrupts stay enabled, see stm32_flash_erase_sector() stm32_flash_unlock(); while (address < end_addr) { if (_FLASH_PROGRAM(address, p_data) != HAL_OK) { @@ -186,6 +343,9 @@ static int stm32_flash_program(uint32_t address, void* data, uint32_t len) } stm32_flash_lock(); + +#endif + return ret; } @@ -211,17 +371,29 @@ const etx_flash_driver_t stm32_flash_driver = { void unlockFlash() { stm32_flash_unlock(); } void lockFlash() { stm32_flash_lock(); } -void flashWrite(uint32_t* address, const uint32_t* buffer) +bool flashWrite(uint32_t* address, const uint32_t* buffer) { // check first if the address is on a sector boundary uint32_t sector = stm32_flash_get_sector((uintptr_t)address); uint32_t bank = stm32_flash_get_bank((uintptr_t)address); if ((uintptr_t)address == _flash_sector_address(sector, bank)) { - if (stm32_flash_erase_sector((uintptr_t)address) < 0) return; + if (stm32_flash_erase_sector((uintptr_t)address) < 0) return false; } - stm32_flash_program((uintptr_t)address, (uint8_t*)buffer, FLASH_PAGESIZE); + if (stm32_flash_program((uintptr_t)address, (uint8_t*)buffer, + FLASH_PAGESIZE) < 0) + return false; + +#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + // drop any lines cached before the erase/program so the read back + // below comes from flash + SCB_InvalidateDCache_by_Addr(address, FLASH_PAGESIZE); +#endif + + // verify the page was actually written, independently of what the + // flash controller reported + return memcmp(address, buffer, FLASH_PAGESIZE) == 0; } // TODO: move this somewhere else, as it depends on firmware layout diff --git a/radio/src/targets/common/arm/stm32/flash_driver.h b/radio/src/targets/common/arm/stm32/flash_driver.h index 86dc0b40107..3f107cf9fc3 100644 --- a/radio/src/targets/common/arm/stm32/flash_driver.h +++ b/radio/src/targets/common/arm/stm32/flash_driver.h @@ -44,5 +44,5 @@ extern const void* stm32_flash_dfu_media; uint32_t isFirmwareStart(const uint8_t * buffer); uint32_t isBootloaderStart(const uint8_t * buffer); -void flashWrite(uint32_t* address, const uint32_t* buffer); +bool flashWrite(uint32_t* address, const uint32_t* buffer); diff --git a/radio/src/targets/pa01/board.h b/radio/src/targets/pa01/board.h index 42a2b5bc765..4ced440aa65 100644 --- a/radio/src/targets/pa01/board.h +++ b/radio/src/targets/pa01/board.h @@ -61,7 +61,7 @@ void getCPUUniqueID(char * s); #define FLASH_PAGESIZE 256 void unlockFlash(); void lockFlash(); -void flashWrite(uint32_t * address, const uint32_t * buffer); +bool flashWrite(uint32_t * address, const uint32_t * buffer); uint32_t isFirmwareStart(const uint8_t * buffer); uint32_t isBootloaderStart(const uint8_t * buffer); diff --git a/radio/src/targets/simu/simulib.cpp b/radio/src/targets/simu/simulib.cpp index d9ced7ff7b9..315b7887d93 100644 --- a/radio/src/targets/simu/simulib.cpp +++ b/radio/src/targets/simu/simulib.cpp @@ -391,9 +391,10 @@ void setSelectedUsbMode(int mode) {} void delay_ms(uint32_t ms) { } void delay_us(uint16_t us) { } -void flashWrite(uint32_t *address, const uint32_t *buffer) +bool flashWrite(uint32_t *address, const uint32_t *buffer) { sleep_ms(10); + return true; } uint32_t isBootloaderStart(const uint8_t * block) diff --git a/radio/src/targets/st16/board.h b/radio/src/targets/st16/board.h index cc95deef494..1055bda249c 100644 --- a/radio/src/targets/st16/board.h +++ b/radio/src/targets/st16/board.h @@ -60,7 +60,7 @@ void getCPUUniqueID(char * s); #define FLASH_PAGESIZE 256 void unlockFlash(); void lockFlash(); -void flashWrite(uint32_t * address, const uint32_t * buffer); +bool flashWrite(uint32_t * address, const uint32_t * buffer); uint32_t isFirmwareStart(const uint8_t * buffer); uint32_t isBootloaderStart(const uint8_t * buffer); diff --git a/radio/src/translations/bl_translations.h b/radio/src/translations/bl_translations.h index f919807a4df..3402ff9121e 100644 --- a/radio/src/translations/bl_translations.h +++ b/radio/src/translations/bl_translations.h @@ -64,6 +64,8 @@ #define TR_BL_DIR_EMPTY "Adresar je prazdny" #define TR_BL_WRITING_FW "Nahravani firmware ..." #define TR_BL_WRITING_COMPL "Nahravani dokonceno" + #define TR_BL_WRITING_FAILED TR("Zapis selhal!", "Zapis se nezdaril!") + #define TR_BL_RETRY_OR_DFU TR("Zkuste znovu / DFU", "Zkuste znovu, nebo pouzijte USB (DFU)") #define TR_BL_ENABLE "Povoleno" #define TR_BL_DISABLE "Zakazano" @@ -111,6 +113,8 @@ #define TR_BL_DIR_EMPTY "Katalog er tomt" #define TR_BL_WRITING_FW "Installerer..." #define TR_BL_WRITING_COMPL "Installation slut" + #define TR_BL_WRITING_FAILED TR("Skrivning fejlede!", "Skrivning mislykkedes!") + #define TR_BL_RETRY_OR_DFU TR("Prov igen / DFU", "Prov igen, eller brug USB (DFU)") #define TR_BL_ENABLE "Aktiver" #define TR_BL_DISABLE "Deaktiver" @@ -158,6 +162,8 @@ #define TR_BL_DIR_EMPTY "Verzeichnis leer" #define TR_BL_WRITING_FW "Schreibe..." #define TR_BL_WRITING_COMPL TR("Schreiben fertig","Schreiben abgeschlossen") + #define TR_BL_WRITING_FAILED TR("Schreiben Fehler!", "Schreiben fehlgeschlagen!") + #define TR_BL_RETRY_OR_DFU TR("Neu vers. / DFU", "Erneut versuchen, oder USB (DFU)") #define TR_BL_ENABLE "Aktivieren" #define TR_BL_DISABLE "Deaktivieren" @@ -206,6 +212,8 @@ #define TR_BL_DIR_EMPTY "Repertoire vide" #define TR_BL_WRITING_FW "Ecriture Firmware ..." #define TR_BL_WRITING_COMPL "Ecriture terminée" + #define TR_BL_WRITING_FAILED TR("Echec ecriture!", "Echec de l'ecriture!") + #define TR_BL_RETRY_OR_DFU TR("Reessayer / DFU", "Reessayez, ou utilisez USB (DFU)") #define TR_BL_ENABLE "Activer" #define TR_BL_DISABLE "Désactiver" @@ -253,6 +261,8 @@ #define TR_BL_DIR_EMPTY "Cartella vuota" #define TR_BL_WRITING_FW "Scrittura..." #define TR_BL_WRITING_COMPL "Scrittura completata" + #define TR_BL_WRITING_FAILED TR("Scrittura fallita!", "Scrittura fallita!") + #define TR_BL_RETRY_OR_DFU TR("Riprova / DFU", "Riprova, oppure usa USB (DFU)") #define TR_BL_ENABLE "Abilita" #define TR_BL_DISABLE "Disabilita" @@ -300,6 +310,8 @@ #define TR_BL_DIR_EMPTY "Katalog jest pusty" #define TR_BL_WRITING_FW "Zapis firmware ..." #define TR_BL_WRITING_COMPL "Zapis ukonczony" + #define TR_BL_WRITING_FAILED TR("Zapis nieudany!", "Zapis nie powiodl sie!") + #define TR_BL_RETRY_OR_DFU TR("Powtorz / DFU", "Powtorz, lub uzyj USB (DFU)") #define TR_BL_ENABLE "Enable" #define TR_BL_DISABLE "Disable" @@ -347,6 +359,8 @@ #define TR_BL_DIR_EMPTY "Katalogen aer tom" #define TR_BL_WRITING_FW "Skriver..." #define TR_BL_WRITING_COMPL "Skrivning klar" + #define TR_BL_WRITING_FAILED TR("Skrivning fel!", "Skrivningen misslyckades!") + #define TR_BL_RETRY_OR_DFU TR("Forsok igen / DFU", "Forsok igen, eller anvand USB (DFU)") #define TR_BL_ENABLE "Aktivera" #define TR_BL_DISABLE "Inaktivera" @@ -394,6 +408,8 @@ #define TR_BL_DIR_EMPTY "Directory is empty" #define TR_BL_WRITING_FW "Writing..." #define TR_BL_WRITING_COMPL "Writing complete" + #define TR_BL_WRITING_FAILED TR("Writing failed!", "Writing failed!") + #define TR_BL_RETRY_OR_DFU TR("Retry or use DFU", "Retry, or flash over USB (DFU)") #define TR_BL_ENABLE "Enable" #define TR_BL_DISABLE "Disable"