STM32L476 flash 页擦除没有效果
Posted
技术标签:
【中文标题】STM32L476 flash 页擦除没有效果【英文标题】:STM32L476 flash Page erase has no effect 【发布时间】:2021-10-20 05:40:34 【问题描述】:我有一个问题,我尝试将值写入 STM32L476 中的闪存页(第 256 页@0x08080000)。但是,我在闪存状态寄存器中设置了 PROGERR 错误。这意味着尝试将非零值写入未擦除到 0xFFFFFFFF 的闪存位置。
我确实像这样擦除闪存:
uint32_t page = 256;
HAL_FLASH_Unlock();
FLASH_PageErase(page, FLASH_BANK_BOTH);
FLASH_WaitForLastOperation((uint32_t) FLASH_TIMEOUT_VALUE);
CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB));
HAL_FLASH_Lock();
但是,当我在擦除后检查闪存内容时,它并没有改变旧的、未擦除的值。
我试着改成
uint32_t page = 256;
HAL_FLASH_Unlock();
SET_BIT(FLASH->SR, (FLASH_FLAG_ALL_ERRORS));
FLASH_WaitForLastOperation((uint32_t) FLASH_TIMEOUT_VALUE);
FLASH_PageErase(page, FLASH_BANK_BOTH);
FLASH_WaitForLastOperation((uint32_t) FLASH_TIMEOUT_VALUE);
CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB));
HAL_FLASH_Lock();
但无济于事。
我是否遗漏了一些明显的东西?
【问题讨论】:
注意,页码从 0 开始,但银行编号从 1 开始 【参考方案1】:每个银行有 256 页,编号为 0-255。因此,第 256 页无效。地址 0x08080000
的闪存是 bank 2 的第 0 页。无效的页码将导致 FLASH_PageErase
断言失败或使用不同的值。
值FLASH_BANK_BOTH
对FLASH_PageErase
无效,因此也会导致断言失败或使用不同的银行值。您一次只能擦除一个银行。否则,从 flash 运行会导致崩溃,因为您不能同时读取和写入单个 bank。
要擦除0x08080000
处的页面,您需要执行FLASH_PageErase(page, FLASH_BANK_2 );
并将page
设置为0
。
【讨论】:
刚刚自己发现了这个问题。这在技术上是不正确的:FLASH_PageErase
只是用0xFF
掩盖页码并检查是否Banks & FLASH_BANK_1 != 0
。所以用FLASH_BANK_BOTH
和256
擦除实际上是擦除bank 1 page 0。FLASH_PageErase()
不会失败。它确实删除了错误的页面。
它会屏蔽并检查第 1 页,但这是在完成 assert_param(IS_FLASH_PAGE(Page));
和 assert_param(IS_FLASH_BANK_EXCLUSIVE(Banks));
之后,它们会检查有效的页面并且只设置一个银行。
虽然我实际上对它不够熟悉,无法知道这些检查是否在非调试版本中被排除(似乎取决于USE_FULL_ASSERT
)。无论哪种方式,都很好地自己解决问题并提供有用的答案。
啊,是的,USE_FULL_ASSERT
独立于 STM32CubeIDE 中的构建配置,目前在项目中没有设置。【参考方案2】:
发现问题。它与 STM32L476 上的双组闪存有关。擦除第 256 页会改为擦除 bank 1 中的第 0 页。
正确检查并删除正确的页面如下所示:
uint32_t page = 256;
HAL_FLASH_Unlock();
FLASH_PageErase(page & 0xFF, (page & 0x100) == 0 ? FLASH_BANK_1 : FLASH_BANK_2);
FLASH_WaitForLastOperation((uint32_t) FLASH_TIMEOUT_VALUE);
CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB));
HAL_FLASH_Lock();
【讨论】:
以上是关于STM32L476 flash 页擦除没有效果的主要内容,如果未能解决你的问题,请参考以下文章
最终启动序列中的错误 - STM32L476 的 Eclipse 系统工作台调试