From 4c9e42925ea781c3171cc1c0638561029c8c7c6b Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Tue, 25 Jul 2023 22:47:16 +0200 Subject: [PATCH] drivers: flash: stm32l5: use write-block-size when writing STM32L5 have a write block size of 8, but STM32U5 and STM32H5 have a write block size of 16. Convert write_dword() and flash_stm32_write_range() to write write-block-size data at a time. Fixes #60724 Signed-off-by: Florian Vaussard --- drivers/flash/flash_stm32l5x.c | 36 +++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/flash/flash_stm32l5x.c b/drivers/flash/flash_stm32l5x.c index b4381289ad1..8ece9b22492 100644 --- a/drivers/flash/flash_stm32l5x.c +++ b/drivers/flash/flash_stm32l5x.c @@ -155,13 +155,15 @@ bool flash_stm32_valid_range(const struct device *dev, off_t offset, return flash_stm32_range_exists(dev, offset, len); } -static int write_dword(const struct device *dev, off_t offset, uint64_t val) +static int write_nwords(const struct device *dev, off_t offset, const uint32_t *buff, size_t n) { FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); volatile uint32_t *flash = (uint32_t *)(offset + CONFIG_FLASH_BASE_ADDRESS); + bool full_zero = true; uint32_t tmp; int rc; + int i; /* if the non-secure control register is locked,do not fail silently */ if (regs->NSCR & FLASH_STM32_NSLOCK) { @@ -175,16 +177,26 @@ static int write_dword(const struct device *dev, off_t offset, uint64_t val) return rc; } - /* Check if this double word is erased and value isn't 0. + /* Check if this double/quad word is erased and value isn't 0. * - * It is allowed to write only zeros over an already written dword + * It is allowed to write only zeros over an already written dword / qword * See 6.3.7 in STM32L5 reference manual. * See 7.3.7 in STM32U5 reference manual. + * See 7.3.5 in STM32H5 reference manual. */ - if ((flash[0] != 0xFFFFFFFFUL || - flash[1] != 0xFFFFFFFFUL) && val != 0UL) { - LOG_ERR("Word at offs %ld not erased", (long)offset); - return -EIO; + for (i = 0; i < n; i++) { + if (buff[i] != 0) { + full_zero = false; + break; + } + } + if (!full_zero) { + for (i = 0; i < n; i++) { + if (flash[i] != 0xFFFFFFFFUL) { + LOG_ERR("Word at offs %ld not erased", (long)(offset + i)); + return -EIO; + } + } } /* Set the NSPG bit */ @@ -194,8 +206,9 @@ static int write_dword(const struct device *dev, off_t offset, uint64_t val) tmp = regs->NSCR; /* Perform the data write operation at the desired memory address */ - flash[0] = (uint32_t)val; - flash[1] = (uint32_t)(val >> 32); + for (i = 0; i < n; i++) { + flash[i] = buff[i]; + } /* Wait until the NSBSY bit is cleared */ rc = flash_stm32_wait_flash_idle(dev); @@ -343,8 +356,9 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset, } } - for (i = 0; i < len; i += 8, offset += 8) { - rc = write_dword(dev, offset, ((const uint64_t *) data)[i>>3]); + for (i = 0; i < len; i += FLASH_STM32_WRITE_BLOCK_SIZE) { + rc = write_nwords(dev, offset + i, ((const uint32_t *) data + (i>>2)), + FLASH_STM32_WRITE_BLOCK_SIZE / 4); if (rc < 0) { break; }