From afd47d58ac25b292bb7ff5ba3b1c53dbf3750d81 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 18 Jun 2020 13:35:53 +1000 Subject: [PATCH] stm32/flash: Make flash C-API reusable, and funcs return an error code. This commit makes the low-level flash C functions usable by code other than flashbdev.c (eg by mboot). Changes in this commit are: - flash_erase() and flash_write() now return an errno error code, a negative value on error. - flash_erase() now automatically locks the flash, as well as unlocking it. - flash_write() now automatically unlocks the flash, as well as locking it. - flashbdev.c is modified for the above changes. Signed-off-by: Damien George --- ports/stm32/flash.c | 68 +++++++++++++++++++++-------------------- ports/stm32/flash.h | 4 +-- ports/stm32/mphalport.h | 4 +++ 3 files changed, 41 insertions(+), 35 deletions(-) diff --git a/ports/stm32/flash.c b/ports/stm32/flash.c index 99c95f7d9..7c7d2f7b6 100644 --- a/ports/stm32/flash.c +++ b/ports/stm32/flash.c @@ -26,6 +26,7 @@ #include "py/mpconfig.h" #include "py/misc.h" +#include "py/mphal.h" #include "flash.h" typedef struct { @@ -162,17 +163,18 @@ uint32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *si return 0; } -void flash_erase(uint32_t flash_dest, uint32_t num_word32) { +int flash_erase(uint32_t flash_dest, uint32_t num_word32) { // check there is something to write if (num_word32 == 0) { - return; + return 0; } - // unlock + // Unlock the flash for erase. HAL_FLASH_Unlock(); - FLASH_EraseInitTypeDef EraseInitStruct; + // Clear pending flags (if any) and set up EraseInitStruct. + FLASH_EraseInitTypeDef EraseInitStruct; #if defined(STM32F0) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR); EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; @@ -190,17 +192,14 @@ void flash_erase(uint32_t flash_dest, uint32_t num_word32) { EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; #elif defined(STM32L4) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); - - // erase the sector(s) // The sector returned by flash_get_sector_info can not be used // as the flash has on each bank 0/1 pages 0..255 EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.Banks = get_bank(flash_dest); EraseInitStruct.Page = get_page(flash_dest); EraseInitStruct.NbPages = get_page(flash_dest + 4 * num_word32 - 1) - EraseInitStruct.Page + 1; - ; #else - // Clear pending flags (if any) + #if defined(STM32H7) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS_BANK1 | FLASH_FLAG_ALL_ERRORS_BANK2); #else @@ -208,7 +207,6 @@ void flash_erase(uint32_t flash_dest, uint32_t num_word32) { FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); #endif - // erase the sector(s) EraseInitStruct.TypeErase = TYPEERASE_SECTORS; EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V #if defined(STM32H7) @@ -216,14 +214,17 @@ void flash_erase(uint32_t flash_dest, uint32_t num_word32) { #endif EraseInitStruct.Sector = flash_get_sector_info(flash_dest, NULL, NULL); EraseInitStruct.NbSectors = flash_get_sector_info(flash_dest + 4 * num_word32 - 1, NULL, NULL) - EraseInitStruct.Sector + 1; + #endif + // Erase the sectors. uint32_t SectorError = 0; - if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) { - // error occurred during sector erase - HAL_FLASH_Lock(); // lock the flash - return; - } + HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError); + + // Lock the flash after erase. + HAL_FLASH_Lock(); + + return mp_hal_status_to_neg_errno(status); } /* @@ -255,16 +256,21 @@ void flash_erase_it(uint32_t flash_dest, uint32_t num_word32) { } */ -void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) { +int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) { + // Unlock the flash for write. + HAL_FLASH_Unlock(); + + HAL_StatusTypeDef status = HAL_OK; + #if defined(STM32L4) || defined(STM32WB) // program the flash uint64 by uint64 for (int i = 0; i < num_word32 / 2; i++) { uint64_t val = *(uint64_t *)src; - if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flash_dest, val) != HAL_OK) { - // error occurred during flash write - HAL_FLASH_Lock(); // lock the flash - return; + status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flash_dest, val); + if (status != HAL_OK) { + num_word32 = 0; // don't write any odd word after this loop + break; } flash_dest += 8; src += 2; @@ -272,21 +278,16 @@ void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) if ((num_word32 & 0x01) == 1) { uint64_t val = *(uint64_t *)flash_dest; val = (val & 0xffffffff00000000uL) | (*src); - if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flash_dest, val) != HAL_OK) { - // error occurred during flash write - HAL_FLASH_Lock(); // lock the flash - return; - } + status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flash_dest, val); } #elif defined(STM32H7) // program the flash 256 bits at a time for (int i = 0; i < num_word32 / 8; i++) { - if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, flash_dest, (uint64_t)(uint32_t)src) != HAL_OK) { - // error occurred during flash write - HAL_FLASH_Lock(); // lock the flash - return; + status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, flash_dest, (uint64_t)(uint32_t)src); + if (status != HAL_OK) { + break; } flash_dest += 32; src += 8; @@ -296,10 +297,9 @@ void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) // program the flash word by word for (int i = 0; i < num_word32; i++) { - if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, flash_dest, *src) != HAL_OK) { - // error occurred during flash write - HAL_FLASH_Lock(); // lock the flash - return; + status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, flash_dest, *src); + if (status != HAL_OK) { + break; } flash_dest += 4; src += 1; @@ -307,8 +307,10 @@ void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) #endif - // lock the flash + // Lock the flash after write. HAL_FLASH_Lock(); + + return mp_hal_status_to_neg_errno(status); } /* diff --git a/ports/stm32/flash.h b/ports/stm32/flash.h index b9edf6106..048914e50 100644 --- a/ports/stm32/flash.h +++ b/ports/stm32/flash.h @@ -27,7 +27,7 @@ #define MICROPY_INCLUDED_STM32_FLASH_H uint32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *size); -void flash_erase(uint32_t flash_dest, uint32_t num_word32); -void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32); +int flash_erase(uint32_t flash_dest, uint32_t num_word32); +int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32); #endif // MICROPY_INCLUDED_STM32_FLASH_H diff --git a/ports/stm32/mphalport.h b/ports/stm32/mphalport.h index fe9378a1c..a76945db5 100644 --- a/ports/stm32/mphalport.h +++ b/ports/stm32/mphalport.h @@ -4,6 +4,10 @@ extern const unsigned char mp_hal_status_to_errno_table[4]; +static inline int mp_hal_status_to_neg_errno(HAL_StatusTypeDef status) { + return -mp_hal_status_to_errno_table[status]; +} + NORETURN void mp_hal_raise(HAL_StatusTypeDef status); void mp_hal_set_interrupt_char(int c); // -1 to disable