arch/stm32h5: Fix FLASH bank logic during erase operations.

Properly select physical bank for block erase based on block number.

Previously, it would configure flash erase bank select based on the logical bank. If banks were swapped, and user application
tried to erase the first block of logical bank 2 (expecting to erase starting at 0x08100000), it would actually erase starting
at 0x0800000. This is fixed in this commit.

Signed-off-by: Tyler Bennett <tbennett@2g-eng.com>
This commit is contained in:
Tyler Bennett 2025-05-21 15:17:49 -05:00 committed by Xiang Xiao
parent 49ad027c60
commit 3cf0abbfee
2 changed files with 28 additions and 14 deletions

View file

@ -237,7 +237,7 @@ void __start(void)
nx_start();
/* Shoulnd't get here */
/* Shouldn't get here */
for (; ; );
}

View file

@ -578,7 +578,8 @@ size_t up_progmem_erasesize(size_t block)
ssize_t up_progmem_eraseblock(size_t block)
{
struct stm32h5_flash_priv_s *priv;
bool bank_swap;
bool phy_bank1;
int ret;
size_t block_address = STM32_FLASH_BASE + (block * FLASH_BLOCK_SIZE);
@ -587,7 +588,28 @@ ssize_t up_progmem_eraseblock(size_t block)
return -EFAULT;
}
priv = flash_bank(block_address);
/* If SWAP_BANK == 0: Logical bank 2 corresponds to physical bank 2
* If SWAP_BANK == 1: Logical bank 2 corresponds to physical bank 1
*/
bank_swap = (bool)(getreg32(STM32_FLASH_OPTSR_CUR) &
FLASH_OPTSR_CUR_SWAP_BANK);
if ((!bank_swap && block >= H5_FLASH_BANK_NBLOCKS) ||
(bank_swap && block < H5_FLASH_BANK_NBLOCKS))
{
phy_bank1 = false;
}
else
{
phy_bank1 = true;
}
/* Convert logical block number into physical erase sector number for
* placing in NSCR_SNB
*/
block = block % H5_FLASH_BANK_NBLOCKS;
ret = nxmutex_lock(&g_lock);
if (ret < 0)
@ -605,7 +627,7 @@ ssize_t up_progmem_eraseblock(size_t block)
flash_unlock_nscr();
if (priv->base == STM32_FLASH_BANK1)
if (phy_bank1)
{
modifyreg32(STM32_FLASH_NSCR, FLASH_NSCR_BKSEL, FLASH_NSCR_SER);
}
@ -614,8 +636,7 @@ ssize_t up_progmem_eraseblock(size_t block)
modifyreg32(STM32_FLASH_NSCR, 0, FLASH_NSCR_BKSEL | FLASH_NSCR_SER);
}
modifyreg32(STM32_FLASH_NSCR, FLASH_NSCR_SNB_MASK,
FLASH_NSCR_SNB(block - priv->stblock));
modifyreg32(STM32_FLASH_NSCR, FLASH_NSCR_SNB_MASK, FLASH_NSCR_SNB(block));
modifyreg32(STM32_FLASH_NSCR, 0, FLASH_NSCR_STRT);
@ -703,14 +724,7 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
flash_unlock_nscr();
if (priv->base == STM32_FLASH_BANK1)
{
modifyreg32(STM32_FLASH_NSCR, FLASH_NSCR_BKSEL, FLASH_NSCR_PG);
}
else
{
modifyreg32(STM32_FLASH_NSCR, 0, FLASH_NSCR_BKSEL | FLASH_NSCR_PG);
}
modifyreg32(STM32_FLASH_NSCR, 0, FLASH_NSCR_PG);
/* Write */