初级会员

- 积分
- 70
- 金钱
- 70
- 注册时间
- 2022-3-9
- 在线时间
- 26 小时
|
本帖最后由 ZJHZXK 于 2022-4-2 15:57 编辑
第一次写帖子,有不妥之处,请联系更改在操作片内flash过程中需要注意两点
1、对地址的正确操作(地址搞错容易进入MCU休眠状态,无法再重新烧录程序)。要想操作好地址,首先去查阅芯片手册关于flash的地址内容,我使用的是STM32G030C8T6芯片,手册对应的flash地址如下,有一点需要注意,该款芯片page31后面的页数进行操作的时候,可以写入一次但是无法再次进行擦除写入,有没有大佬解答下疑惑?
2、闪存的编程和擦除
通过手册中的描述,在芯片复位以后,Flash编程操作是被保护的,不能写入。通过写入特定的序列KEY、KEY2到FLASH_KEYR寄存器才可解除写保护,只有在写保护被解除后,我们才能操作相关的寄存器。这个操作有官方库中的HAL_FLASH_Unlock(),HAL_FLASH_Unlock()函数来实现,操作完成以后,FLASH_CR便被解锁了,如果写入错误,那么FLASH_CR将被锁定,知道下次复位才可以再次解锁。需要注意的就是在往Flash写入数据以前需要检查该区域是否已经擦除,因为在对Flash进行编程的时候,必须要求其写入地址的Flash是被擦出的(也就是说其值必须是0xFFFFFFFF),否则无法写入
3、标准的编程步骤如下:
解锁。
确保要写入地址的Flash已经擦除完全。
检查 FLASH_SR 中的 BSY 位,确保当前未执行任何 FLASH 操作。
将 FLASH_CR 寄存器中的 PG 位置 1,激活 FLASH 编程.
针对所需存储器地址(主存储器块或 OTP 区域内)执行数据写入操作.
等待 BSY 位清零,完成一次编程.
上锁
4、代码如下
#define STM32_Flash_BASE_31 (0x0800F800) //page31(我操作的页)
4.1、擦除
void erase_flash(uint32_t page)
{
HAL_FLASH_Unlock(); //解锁
uint32_t PageError = 0;
FLASH_EraseInitTypeDef FlashSet;
FlashSet.Banks = FLASH_BANK_1; //主储存
FlashSet.TypeErase=FLASH_TYPEERASE_PAGES; //擦除类型,页擦除
FlashSet.Page=page; //从哪页开始擦除
FlashSet.NbPages=1; //一次擦除一页
__disable_irq(); //关全局中断
HAL_FLASHEx_Erase(&FlashSet, &PageError); //擦除
__enable_irq();
HAL_FLASH_Lock(); //锁定
}
4.1、写入
void write_flash(uint32_t Flash_Address,uint64_t *Data,uint16_t Length,uint32_t page)
{
HAL_FLASH_Unlock(); //解锁
FLASH_EraseInitTypeDef FlashSet;
FlashSet.Banks = FLASH_BANK_1; //主储存
FlashSet.TypeErase=FLASH_TYPEERASE_PAGES; //擦除类型,页擦除
FlashSet.Page=page; //从哪页开始擦除
FlashSet.NbPages=1;
uint32_t PageError = 0;
__disable_irq();
HAL_FLASHEx_Erase(&FlashSet, &PageError); //擦除
__enable_irq();
for(int i = 0;i<Length;i++)
{
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, Flash_Address+i*8, *Data); //写入
Data++;
}
HAL_FLASH_Lock(); //锁定
}
4.3读取
void read_flash(uint32_t Flash_Address,uint64_t *Data,uint16_t Length)
{
uint32_t Address_r = Flash_Address;
for(int i = 0;i<Length;i++)
{
*Data = *(__IO uint64_t*)(Address_r+i*8);
Data++;
}
}
|
-
-
|