uint32_t PAGEError = 0;
FLASH_EraseInitTypeDef EraseInitStruct;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS ;
EraseInitStruct.Sector = FLASH_SECTOR_0;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08000000, counter)
HAL_FLASH_Lock();
counter2 = *(__IO uint32_t *)0x08000000;
counter3 = *(__IO uint32_t *)0x08000001;
counter4 = *(__IO uint32_t *)0x08000002;
sprintf(buf, "%d", counter2); //gets send to the OLED with I2C
sprintf(buf2, "%d", counter3);
sprintf(buf3, "%d", counter4);
我想将变量计数器写入闪存,然后将其读作counter2
。
第一个闪存扇区从0x08000000
开始。
counter2
,3
和4
通过OLED屏幕显示。
显示counter2
有效并向我显示counter-1
的值,但它只能运行一次。如果我再次写入闪光灯,似乎没有任何事情发生。
counter3
和counter4
根本不起作用。
在擦除闪存但未写入任何内容后counter=0x00000008
时OLED上的输出:
counter2: 536873624
counter3: -652214262
counter4: 31006720
写作和重新设定后:
counter2: 8
counter3: -654311424
counter4: 30998528
这里发生了什么?有人能告诉我为什么所有变量都会改变吗 我是否必须配置链接器?
答案 0 :(得分:5)
我现在会把你当作乞讨者,但如果不是,我会说对不起。
STM32设备在0x08000000
上有闪存,并且通过擦除此扇区,您在启动时失败了,因为您删除了CPU加载指令的实际部分。
当您尝试删除扇区时,您没有指定要删除的扇区数。
读取计数器是错误的。由于你有uint32_t
变量,你必须在读数之间做4个字节,如:
counter2 = *(__IO uint32_t *)0x08000000;
counter3 = *(__IO uint32_t *)0x08000004;
counter4 = *(__IO uint32_t *)0x08000008;
正确的删除如下所示。
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
EraseInitStruct.Sector = FLASH_SECTOR_0; //Specify sector number
EraseInitStruct.NbSectors = 1; //This is also important!
if(HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
//Erase error!
}
因此,了解您的计划需要多长时间,并在您的计划之后在行业中开展业务。
您可以在STM32CubeF4包中找到 EraseProgram 的示例。
STM32Cube_FW_F4_V1.16.0\Projects\STM324x9I_EVAL\Examples\FLASH\FLASH_EraseProgram\Src\main.c
概念也适用于您的核心,只需确保为闪存擦除设置正确的地址。
答案 1 :(得分:0)
感谢@phoenix!
在Stm32CubF3中,擦除Flash的工作方式如下:
要提及的是内存页地址的外观:
/* Base address of the Flash sectors */
#define ADDR_FLASH_PAGE_0 ((uint32_t)0x08000000) /* Base @ of Page 0, 2 Kbytes */
#define ADDR_FLASH_PAGE_1 ((uint32_t)0x08000800) /* Base @ of Page 1, 2 Kbytes */
#define ADDR_FLASH_PAGE_2 ((uint32_t)0x08001000) /* Base @ of Page 2, 2 Kbytes */
#define ADDR_FLASH_PAGE_3 ((uint32_t)0x08001800) /* Base @ of Page 3, 2 Kbytes */
#define ADDR_FLASH_PAGE_4 ((uint32_t)0x08002000) /* Base @ of Page 4, 2 Kbytes */
#define ADDR_FLASH_PAGE_5 ((uint32_t)0x08002800) /* Base @ of Page 5, 2 Kbytes */
#define ADDR_FLASH_PAGE_6 ((uint32_t)0x08003000) /* Base @ of Page 6, 2 Kbytes */
因此,您的最小代码如下:
我要删除我的应用程序@ 0x08003000-> FLASH_PAGE_6。明智的擦除操作是2kB:
/* EEPROM start address in Flash */
#define EEPROM_START_ADDRESS ((uint32_t)ADDR_FLASH_PAGE_32) /* EEPROM emulation start address */
/* Pages 0 and 1 base and end addresses */
#define PAGE0_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x0000))
#define PAGE0_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1)))
//#define PAGE0_ID ADDR_FLASH_PAGE_32
/* Clear flash flags */
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP |
FLASH_FLAG_WRPERR |
FLASH_FLAG_PGERR);
uint32_t *flash_ptr = 0x8003000;
uint32_t page_error = 0;
HAL_StatusTypeDef flashstatus;
FLASH_EraseInitTypeDef s_eraseinit;
/* Fill EraseInit structure*/
s_eraseinit.TypeErase = FLASH_TYPEERASE_PAGES;
s_eraseinit.NbPages = 1; // seems to be 1 !!!!
/* I want to delete 54kB in my flash --> 52kB / 2kB (per erase) = 26 iterations
After erasing one page, increment page by 0x800 = 2048 byte = 2kB = pagesize */
for(int pageCount = 0; pageCount < 26; pageCount++){
s_eraseinit.PageAddress = ADDR_FLASH_PAGE_6 + pageCount * 0x800;
flashstatus = HAL_FLASHEx_Erase(&s_eraseinit, &page_error);
}
答案 2 :(得分:-1)
最好的方法是在linkescriptr中创建新的flash段并将数据放在那里。这是最安全的。
如果不知道链接描述文件创建一个段大小的表,并使用编译器指令将其放在flash的末尾。
如果您不知道两者,我建议使用Cube中的现成STM eeprom仿真示例