ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

单片机基础核心知识点汇总(三十)

单片机基础核心知识点汇总(三十) 目录前言一、Flash 基础核心特性二、Flash 分区规划IAP 必备三、Flash 基础读写代码四、参数掉电存储工程方案五、IAP 固件升级 Flash 操作逻辑六、Flash 开发高频坑点七、Flash 寿命优化策略小结前言本篇我们攻克嵌入式量产开发核心存储能力 —— 片内 Flash 操作。几乎所有量产设备都离不开 Flash 应用设备参数掉电保存、校准数据存储、日志记录、OTA 固件升级、开机配置固化。很多新手对 Flash 认知只有简单读写实际项目中频繁遇到各种疑难问题 直接写 Flash 不擦除导致写入失败频繁擦写损耗 Flash 寿命跨扇区存储数据异常IAP 分区规划不合理引发固件覆盖程序运行时擦 Flash 造成卡死。Flash 有一条铁则只能将 bit1 改成 bit0不能直接把 bit0 改成 bit1想要恢复 bit1必须执行扇区擦除。一、Flash 基础核心特性存储单元最小操作按半字 / 字 / 双字写入按扇区擦除擦除后扇区所有数据为 0xFF擦写次数有上限STM32 片内 Flash 一般万次级别程序运行时可读写同芯片 Flash但擦写期间禁止访问被操作扇区代码掉电瞬间操作 Flash极易造成存储数据损坏二、Flash 分区规划IAP 必备以 512KB Flash 芯片举例0x08000000 ~ 0x08002FFFBootloader 分区IAP 升级引导程序0x08003000 ~ 0x0800BFFFApp 分区设备业务主程序0x0800C000 ~ 0x0800CFFF参数存储分区保存配置、校准参数业务代码和参数分区物理隔离升级固件不会覆盖设备配置三、Flash 基础读写代码#include stm32f10x.h //Flash擦除单个扇区 uint32_t Flash_EraseSector(uint32_t addr) { FLASH_Unlock(); FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); uint32_t ret FLASH_ErasePage(addr); FLASH_Lock(); return ret; } //写入半字2字节 uint32_t Flash_WriteHalfWord(uint32_t addr, uint16_t data) { FLASH_Unlock(); FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); uint32_t ret FLASH_ProgramHalfWord(addr, data); FLASH_Lock(); return ret; } //批量写入多字节数据 uint32_t Flash_WriteBuf(uint32_t start_addr, uint8_t *buf, uint16_t len) { uint16_t i 0; uint32_t res; if(len % 2 ! 0) return 1; while(i len) { uint16_t temp (buf[i1] 8) | buf[i]; res Flash_WriteHalfWord(start_addr i, temp); if(res ! FLASH_COMPLETE) return res; i 2; } return FLASH_COMPLETE; } //读取Flash数据直接指针访问 uint8_t Flash_ReadByte(uint32_t addr) { return *(volatile uint8_t*)addr; }四、参数掉电存储工程方案不要每次修改参数就擦写 Flash频繁擦写快速损耗寿命。方案内存缓存参数定时保存 / 修改确认后再写入 Flash。#define PARAM_ADDR 0x0800C000 typedef struct { uint16_t para1; uint16_t para2; uint32_t crc; }param_t; param_t g_param_cache; //保存参数到Flash void Param_Save(void) { Flash_EraseSector(PARAM_ADDR); g_param_cache.crc crc16_calc((uint8_t*)g_param_cache, sizeof(param_t)-4); Flash_WriteBuf(PARAM_ADDR, (uint8_t*)g_param_cache, sizeof(param_t)); } //开机加载参数 void Param_Load(void) { param_t *p (param_t *)PARAM_ADDR; uint16_t crc_check crc16_calc((uint8_t*)p, sizeof(param_t)-4); if(crc_check p-crc) { memcpy(g_param_cache, p, sizeof(param_t)); } else { //校验失败加载默认参数 g_param_cache.para1 100; g_param_cache.para2 200; } }增加 CRC 校验防止掉电半写导致参数损坏。五、IAP 固件升级 Flash 操作逻辑Bootloader 运行检测是否存在新固件将收到的固件包写入 App 备份 Flash 分区固件全部接收完成校验整个固件 CRC校验通过擦除原 App 分区将备份固件拷贝到 App 区域跳转 App 程序校验失败保留旧程序不执行覆盖六、Flash 开发高频坑点忘记解锁 Flash直接擦写操作全部失败不做 CRC 校验掉电中断写入参数变成乱码循环频繁擦写同一扇区Flash 提前磨损失效擦写 Flash 时代码在当前扇区运行程序直接 HardFault地址没有对齐写入半字 / 字时报错分区规划重叠升级时误擦除 Bootloader设备变砖七、Flash 寿命优化策略减少擦除次数参数改动批量一次性写入循环轮换多个备份扇区分散擦写压力重要参数做双备份A 扇区主存B 扇区备用禁止在循环内反复执行 Flash 擦写小结片内 Flash 操作核心就三点遵守硬件读写规则、合理分区、增加校验与备份机制。单纯读写只是基础量产项目重点在于保护数据安全、控制擦写损耗避免设备变砖与参数丢失。
返回列表