From b6ab9e420b0a874eb2f8f6b7597430ed9e526bf7 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 1 Nov 2023 19:12:09 +1100 Subject: [PATCH] stm32/flash: Change flash_erase to only erase a single sector at a time. An erase sector sits in a given flash bank and some MCUs have two flash banks. If trying to erase a range of sectors and that range crosses from one flash bank into the next, the original implementation of `flash_erase()` would not handle this case and would do the wrong thing. This commit changes `flash_erase()` to only erase a single sector, which sidesteps the need to handle flash-bank-crossing. Most callers of this function only need to erase a single sector anyway. Signed-off-by: Damien George --- ports/stm32/flash.c | 21 ++++++++++----------- ports/stm32/flash.h | 2 +- ports/stm32/flashbdev.c | 2 +- ports/stm32/mboot/main.c | 2 +- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/ports/stm32/flash.c b/ports/stm32/flash.c index d9f7af8a24..fb1e6059c1 100644 --- a/ports/stm32/flash.c +++ b/ports/stm32/flash.c @@ -272,11 +272,10 @@ int32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *siz return -1; } -int flash_erase(uint32_t flash_dest, uint32_t num_word32) { - // check there is something to write - if (num_word32 == 0) { - return 0; - } +// Erase a single flash page which starts at the given address. +// The address will be converted to a bank and sector number. +int flash_erase(uint32_t flash_dest) { + const unsigned int num_sectors = 1; #if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION // Acquire lock on the flash peripheral. @@ -306,23 +305,23 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) { __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR); EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.PageAddress = flash_dest; - EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; + EraseInitStruct.NbPages = num_sectors; #elif defined(STM32G0) || defined(STM32G4) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.Page = get_page(flash_dest); EraseInitStruct.Banks = get_bank(flash_dest); - EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; + EraseInitStruct.NbPages = num_sectors; #elif defined(STM32L0) || defined(STM32L1) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR); EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.PageAddress = flash_dest; - EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; + EraseInitStruct.NbPages = num_sectors; #elif (defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32WB) || defined(STM32WL) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.Page = get_page(flash_dest); - EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; + EraseInitStruct.NbPages = num_sectors; #elif defined(STM32L4) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); // The sector returned by flash_get_sector_info can not be used @@ -330,7 +329,7 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) { 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; + EraseInitStruct.NbPages = num_sectors; #else #if defined(STM32H5) @@ -354,7 +353,7 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) { EraseInitStruct.Banks = get_bank(flash_dest); #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; + EraseInitStruct.NbSectors = num_sectors; #if defined(STM32H5) EraseInitStruct.Sector &= 0x7f; // second bank should start counting at 0 #endif diff --git a/ports/stm32/flash.h b/ports/stm32/flash.h index ecda923db7..e5ba35cf7d 100644 --- a/ports/stm32/flash.h +++ b/ports/stm32/flash.h @@ -28,7 +28,7 @@ bool flash_is_valid_addr(uint32_t addr); int32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *size); -int flash_erase(uint32_t flash_dest, uint32_t num_word32); +int flash_erase(uint32_t flash_dest); 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/flashbdev.c b/ports/stm32/flashbdev.c index 19edde2108..e96c54e791 100644 --- a/ports/stm32/flashbdev.c +++ b/ports/stm32/flashbdev.c @@ -161,7 +161,7 @@ static void flash_bdev_irq_handler(void) { // This code erases the flash directly, waiting for it to finish if (!(flash_flags & FLASH_FLAG_ERASED)) { - flash_erase(flash_cache_sector_start, flash_cache_sector_size / 4); + flash_erase(flash_cache_sector_start); flash_flags |= FLASH_FLAG_ERASED; return; } diff --git a/ports/stm32/mboot/main.c b/ports/stm32/mboot/main.c index 1175530871..2424b37da3 100644 --- a/ports/stm32/mboot/main.c +++ b/ports/stm32/mboot/main.c @@ -465,7 +465,7 @@ static int mboot_flash_page_erase(uint32_t addr, uint32_t *next_addr) { } // Erase the flash page. - ret = flash_erase(sector_start, sector_size / sizeof(uint32_t)); + ret = flash_erase(sector_start); if (ret != 0) { return ret; }