diff --git a/drivers/flash/flash_stm32g0x.c b/drivers/flash/flash_stm32g0x.c index 2a0cabfc330..d1ef8d2474a 100644 --- a/drivers/flash/flash_stm32g0x.c +++ b/drivers/flash/flash_stm32g0x.c @@ -21,7 +21,19 @@ LOG_MODULE_REGISTER(LOG_DOMAIN); #include "flash_stm32.h" +/* FLASH_DBANK_SUPPORT is defined in the HAL for all G0Bx and G0C1 SoCs, + * while only those with 256KiB and 512KiB Flash have two banks. + */ +#if defined(FLASH_DBANK_SUPPORT) && (CONFIG_FLASH_SIZE > (128)) +#define STM32G0_DBANK_SUPPORT +#endif + +#if defined(STM32G0_DBANK_SUPPORT) +#define STM32G0_BANK_COUNT 2 +#define STM32G0_BANK2_START_PAGE_NR 256 +#else #define STM32G0_BANK_COUNT 1 +#endif #define STM32G0_FLASH_SIZE (FLASH_SIZE) #define STM32G0_FLASH_PAGE_SIZE (FLASH_PAGE_SIZE) @@ -31,6 +43,8 @@ LOG_MODULE_REGISTER(LOG_DOMAIN); /* * offset and len must be aligned on 8 for write, * positive and not beyond end of flash + * On dual-bank SoCs memory accesses starting on the first bank and continuing + * beyond the first bank into the second bank are allowed. */ bool flash_stm32_valid_range(const struct device *dev, off_t offset, uint32_t len, @@ -125,6 +139,21 @@ static int erase_page(const struct device *dev, unsigned int offset) tmp = regs->CR; page = offset / STM32G0_FLASH_PAGE_SIZE; +#if defined(STM32G0_DBANK_SUPPORT) + bool swap_enabled = (regs->OPTR & FLASH_OPTR_nSWAP_BANK) == 0; + + /* big page-nr w/o swap or small page-nr w/ swap indicate bank2 */ + if ((page >= STM32G0_PAGES_PER_BANK) != swap_enabled) { + page = (page % STM32G0_PAGES_PER_BANK) + STM32G0_BANK2_START_PAGE_NR; + tmp |= FLASH_CR_BKER; + LOG_DBG("Erase page %d on bank 2", page); + } else { + page = page % STM32G0_PAGES_PER_BANK; + tmp &= ~FLASH_CR_BKER; + LOG_DBG("Erase page %d on bank 1", page); + } +#endif + /* Set the PER bit and select the page you wish to erase */ tmp |= FLASH_CR_PER; tmp &= ~FLASH_CR_PNB_Msk; @@ -174,6 +203,16 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset, return rc; } +/* + * The address space is always continuous, even though a subset of G0 SoCs has + * two flash banks. + * Only the "physical" flash page-NRs are not continuous on those SoCs. + * As a result the page numbers used in the zephyr flash api differs + * from the "physical" flash page number. + * The first is equal to the address offset divided by the page size, while + * "physical" pages are numbered starting with 0 on bank1 and 256 on bank2. + * As a result only a single homogeneous flash page layout needs to be defined. + */ void flash_stm32_page_layout(const struct device *dev, const struct flash_pages_layout **layout, size_t *layout_size) @@ -194,3 +233,16 @@ void flash_stm32_page_layout(const struct device *dev, *layout = &stm32g0_flash_layout; *layout_size = 1; } + +/* Override weak function */ +int flash_stm32_check_configuration(void) +{ +#if defined(STM32G0_DBANK_SUPPORT) && (CONFIG_FLASH_SIZE == 256) + /* Single bank mode not supported on dual bank SoCs with 256kiB flash */ + if ((regs->OPTR & FLASH_OPTR_DUAL_BANK) == 0) { + LOG_ERR("Single bank configuration not supported by the driver"); + return -ENOTSUP; + } +#endif + return 0; +}