Skip to content

MCU 内部flash的读写操作

在一些时候,需要存储一些数据,但是又不想接外部的flash,那我们可以知道,其实还有内部的flash可以使用, 需要注意的是内部flash,读写次数有限,所以需要控制擦写次数

1. 硬件连接

因为有flash大小的区分,所以需要注意设备进行页擦除的最大地址
C6T6 32k 最大地址 0x08007FF0
C8T6 64k 最大地址 0x0800FFE0

小容量产品:主存储块1-32KB, 每页1KB。系统存储器2KB
中容量产品:主存储块64-128KB, 每页1KB。系统存储器2KB
大容量产品:主存储块256KB以上, 每页2KB。系统存储器2KB
互联型产品:主存储块256KB以上, 每页2KB。系统存储器18KB

下图是 闪存模块的组织(中容量产品)

alt text

需要注意的是,前面一般都是放置代码的,所以擦写的时候尽量只擦写最后一个快的区域,防止误擦除。

2. CubeMX生成代码

可以看到,配置了3个部分

  1. 外部时钟
  2. SWD 接口
  3. 串口输出
  4. GPIO

alt text

3. 编写代码

重定向串口

C
/* USER CODE BEGIN PV */
#include "stdio.h"
int fputc(int ch,FILE *f)
{
	HAL_UART_Transmit (&huart1 ,(uint8_t *)&ch,1,HAL_MAX_DELAY );
	return ch;
}
/* USER CODE END PV */

申明一些变量

C
/* USER CODE BEGIN 0 */

//debug 查看对应地址,是否正确,如果显示的是问号,则无此位置
//C6T6 32k  最大地址 0x08007FF0
//C8T6 64k  最大地址 0x0800FFE0
#define FLASH_SAVE_ADDR  0x08007000

static FLASH_EraseInitTypeDef EraseInitStruct = {
	.TypeErase = FLASH_TYPEERASE_PAGES,       //页擦除
	.PageAddress = FLASH_SAVE_ADDR,                //擦除地址
	.NbPages = 1                              //擦除页数
};
/* USER CODE END 0 */

下面代码执行擦写的操作

C
  while (1)
  {
        HAL_FLASH_Unlock();
        uint32_t PageError = 0;
        __disable_irq();                             //擦除前关闭中断
        if (HAL_FLASHEx_Erase(&EraseInitStruct,&PageError) == HAL_OK)
        {
            printf("擦除 成功\r\n");
        }
        __enable_irq();                             //擦除后打开中断
        uint32_t writeFlashData = 0x55555555;        //待写入的值
        uint32_t addr = FLASH_SAVE_ADDR;                  //写入的地址
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,addr, writeFlashData);
        printf("at address:0x%x, read value:0x%x\r\n", addr, *(__IO uint32_t*)addr);
        HAL_FLASH_Lock();
        while(1);//代码停住,限制擦写次数
        
  }

4. 后记

内部的flash有擦写的次数限制,所以尽量只存储少量和擦写次数少的内容。
写的时候需要注意程序占用的空间,不要将程序误擦除。