stm32L476-擦除闪光灯



L4系列使用页面(如果进行完全擦除,则为存储体(擦除闪存。但我在做页面擦除后,在写作方面遇到了一些问题,我不知道为什么。

为了概括目标,我存储了从0x08080000开始的6个值(第256页(那么我将存储更多的值,从0x08080800((第257页(到0x08085800(第267页(

我使用一个函数来擦除/写入第256页的值:

void write_bias_flash(int16_t biases[]) {
uint16_t *flash_biases = (uint16_t*) (ADDR_FLASH_PAGE_256);
static FLASH_EraseInitTypeDef EraseInitStruct;
Address = ADDR_FLASH_PAGE_256;
/* Fill EraseInit structure*/
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.Page = 0;
EraseInitStruct.Banks = FLASH_BANK_2;
EraseInitStruct.NbPages = 1;
HAL_FLASH_Unlock();
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
serprintf("Error erasing biases at address: 0x%x", Address);
}
for (int8_t bias = 0; bias < 6; bias++) {
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,
Address + bias * sizeof(uint64_t), (uint64_t) biases[bias])
!= HAL_OK)
serprintf("Error writing biases to flash.");
}
HAL_FLASH_Lock();
serprintf("Biases stored in flash.");
}

这工作很棒。没有问题。

我有两个功能用于擦除/写入从0x08080800开始的数据((第257页(:

void Erase_TM_Flash() {
uint8_t *flash = (uint8_t*) (FLASH_USER_START_ADDR);
uint8_t *b = (uint16_t*) (ADDR_FLASH_PAGE_256);
static FLASH_EraseInitTypeDef EraseInitStruct;
Address = FLASH_USER_START_ADDR;
/* Fill EraseInit structure*/
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.Page = 1;
EraseInitStruct.NbPages = 255;
EraseInitStruct.Banks = FLASH_BANK_2;
HAL_FLASH_Unlock();
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
serprintf("Error erasing biases at address: 0x%x", Address);
}
HAL_FLASH_Lock();
for (uint16_t i = 0; i< (FLASH_ROW_SIZE * sizeof(uint64_t))*255; i++)
{
if ((uint16_t) *(flash+i) != 255) {
serprintf("0x%x is not erased (%i)", flash+i, (uint16_t) *(flash+i));
}
}
}
void Save_to_Flash(uint32_t *data) {
uint32_t src_addr = (uint32_t) data;
Erase_TM_Flash();
serprintf("Saving to flash...");
HAL_StatusTypeDef HAL_STATUS;
HAL_FLASH_Unlock();
Address = FLASH_USER_START_ADDR;
while (Address < (FLASH_USER_END_ADDR - (FLASH_ROW_SIZE * sizeof(uint64_t)))) {
HAL_STATUS = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FAST, Address, (uint64_t) src_addr);
if (HAL_STATUS == HAL_OK) {
Address = Addres+ (FLASH_ROW_SIZE * sizeof(uint64_t));
src_addr = src_addr + (FLASH_ROW_SIZE * sizeof(uint64_t));
} else {
serprintf("Error writing flash at address 0x%x. (%i)", Address, HAL_STATUS);
Address = Address + (FLASH_ROW_SIZE * sizeof(uint64_t));
src_addr = src_addr + (FLASH_ROW_SIZE * sizeof(uint64_t));
}
}
HAL_FLASH_Lock();
serprintf("Done");
}

擦除效果很好。我在调试器中验证这些值(在代码中检查未擦除的页面(。但当节省发生时:

Error writing flash at address 0x8080800. (1)
Error writing flash at address 0x8080900. (1)
Error writing flash at address 0x8080a00. (1)
Error writing flash at address 0x8080b00. (1)

在剩下的所有页面中依此类推。

但是,如果我擦除整个闪存:

void Erase_Flash() {
serprintf("Erasing flash...");
HAL_FLASH_Unlock();
/* Clear OPTVERR bit set on virgin samples */
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
/* Fill EraseInit structure*/
EraseInitStruct.TypeErase = FLASH_TYPEERASE_MASSERASE;
EraseInitStruct.Banks = FLASH_BANK_2;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
serprintf("Error erasing flash.");
}
HAL_FLASH_Lock();
serprintf("Done.");
}

然后写作就像一种魅力。HAL_STATUS=1,根据我发现的代码,它是HAL_ERROR=0x01U,这并没有完全的帮助。

我不确定有什么不同,但我希望通过另一种方式来观察我的删除可能会发现这个问题。

谢谢!

此问题似乎与闪存快速编程有关,并非所有STM32型号都有此功能。

根据参考手册(RM0351(,在使用快速编程之前,必须对闪存进行大规模擦除。否则,将出现编程序列错误,并设置FLASH_SR寄存器中的PGSERR位。请参阅快速编程/编程错误3.7.5位7 PGSERR下的3.3.7闪存主存储器编程序列

RM0351修订版9,3.3.7闪存主存储器编程序列,见第106页:

Fast programming
(...)
1. Perform a mass erase of the bank to program. If not, PGSERR is set.
2. (...)

RM0351修订版9,3.3.7闪存主存储器编程序列,见第107页:

Programming errors
(...)
PGSERR: Programming Sequence Error
PGSERR is set if one of the following conditions occurs:
– (...)
– In the fast programming sequence: the Mass erase is not performed before setting 
FSTPG bit.
– (...)

因此,观察到的行为与预期一致因此,您可以更换Erase_TM_Flash()功能,并使用Erase_Flash()首先大规模擦除整个闪存组。或者,完全避免使用闪存快速编程,而是使用FLASH_Program_DoubleWord()FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, ...)

相关源文件:stm32l4xx_hal_flash.h、stm32l4xxx_hal_flach.c

相关帖子:STM32-写入和读取闪存

最新更新