使用 HAL 时如何擦除 STM32F405RG 中的内部闪存页面(不是扇区!)?
How can I erase an internal flash Page (not sector!) in my STM32F405RG while using HAL?
我在尝试管理 STM32F4 微控制器中的内部闪存时遇到了死胡同。有很多示例,但大多数使用 SPL API 或低级寄存器操作。我正在使用 HAL 库。而且我找不到只擦除一页的功能(在 stm32f4xx_hal_flash.c
和 stm32f4xx_hal_flash_ex.c
中)。
建议的函数,例如 HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *SectorError)
或 void FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)
不允许您仅擦除一页 (2048 kByte),而只能擦除整个扇区(或多个扇区)。
当我尝试使用类似的东西时:
void Internal_Flash_Erase(unsigned int pageAddress) {
while (FLASH->SR & FLASH_SR_BSY);
if (FLASH->SR & FLASH_SR_EOP) {
FLASH->SR = FLASH_SR_EOP;
}
FLASH->CR |= FLASH_CR_PER;
FLASH->AR = pageAddress;
FLASH->CR |= FLASH_CR_STRT;
while (!(FLASH->SR & FLASH_SR_EOP));
FLASH->SR = FLASH_SR_EOP;
FLASH->CR &= ~FLASH_CR_PER;
}
由于HAL中没有FLASH->AR
(地址寄存器),所以出现编译错误。
我发现阅读 RM0090 Reference manual 现在我需要使用 FLASH->CR
而不是 AR 并设置位 FLASH_CR_SNB [3:6]
来选择扇区号。
现在我不知道如何只擦除一页。有必要在内部闪存中创建大容量存储设备以实现以下功能:
usbd_storage_if.c
中的 int8_t STORAGE_Write_FS (uint8_t lun,
uint8_t *buf,
uint32_t blk_addr,
uint16_t blk_len)
将 USB 堆栈调用转换为内部闪存。
你不能。您可以擦除的最小部分是一个扇区。
我引用参考手册:
3.6.3 Erase
The Flash memory erase operation can be performed at sector level or on the
whole Flash> memory (Mass Erase). Mass Erase does not affect the OTP sector
or the configuration sector.
这就是扇区大小不同的原因。考虑到何时可能需要擦除闪存数据,设计您的软件以巧妙地使用这些扇区非常重要。
您可能需要在 RAM 中缓冲整个扇区,以便以类似文件系统的粒度实现闪存写入。
通常:
复制table中的一个flash扇区,修改table中的页,擦除扇区,将table复制到flash扇区
显然我发现了我的错误。我找到的示例适用于 STM32F103xx。而 STM32F103xx 闪存实际上被分成页面(1 或 2 KB)。可以擦除 "sector" 等于擦除 "page"。但是在STM32F4xx的情况下flash-memory被划分为扇区的情况有所不同。
我在尝试管理 STM32F4 微控制器中的内部闪存时遇到了死胡同。有很多示例,但大多数使用 SPL API 或低级寄存器操作。我正在使用 HAL 库。而且我找不到只擦除一页的功能(在 stm32f4xx_hal_flash.c
和 stm32f4xx_hal_flash_ex.c
中)。
建议的函数,例如 HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *SectorError)
或 void FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)
不允许您仅擦除一页 (2048 kByte),而只能擦除整个扇区(或多个扇区)。
当我尝试使用类似的东西时:
void Internal_Flash_Erase(unsigned int pageAddress) {
while (FLASH->SR & FLASH_SR_BSY);
if (FLASH->SR & FLASH_SR_EOP) {
FLASH->SR = FLASH_SR_EOP;
}
FLASH->CR |= FLASH_CR_PER;
FLASH->AR = pageAddress;
FLASH->CR |= FLASH_CR_STRT;
while (!(FLASH->SR & FLASH_SR_EOP));
FLASH->SR = FLASH_SR_EOP;
FLASH->CR &= ~FLASH_CR_PER;
}
由于HAL中没有FLASH->AR
(地址寄存器),所以出现编译错误。
我发现阅读 RM0090 Reference manual 现在我需要使用 FLASH->CR
而不是 AR 并设置位 FLASH_CR_SNB [3:6]
来选择扇区号。
现在我不知道如何只擦除一页。有必要在内部闪存中创建大容量存储设备以实现以下功能:
usbd_storage_if.c
中的 int8_t STORAGE_Write_FS (uint8_t lun,
uint8_t *buf,
uint32_t blk_addr,
uint16_t blk_len)
将 USB 堆栈调用转换为内部闪存。
你不能。您可以擦除的最小部分是一个扇区。
我引用参考手册:
3.6.3 Erase
The Flash memory erase operation can be performed at sector level or on the whole Flash> memory (Mass Erase). Mass Erase does not affect the OTP sector or the configuration sector.
这就是扇区大小不同的原因。考虑到何时可能需要擦除闪存数据,设计您的软件以巧妙地使用这些扇区非常重要。
您可能需要在 RAM 中缓冲整个扇区,以便以类似文件系统的粒度实现闪存写入。
通常: 复制table中的一个flash扇区,修改table中的页,擦除扇区,将table复制到flash扇区
显然我发现了我的错误。我找到的示例适用于 STM32F103xx。而 STM32F103xx 闪存实际上被分成页面(1 或 2 KB)。可以擦除 "sector" 等于擦除 "page"。但是在STM32F4xx的情况下flash-memory被划分为扇区的情况有所不同。