当前位置: 首页 > java >正文

N32G43x Bootloader 中 ENV 区的管理与实现

1. 背景

在 Bootloader 设计中,经常需要保存一些 掉电不丢失的关键参数,比如:

  • 当前正在运行的 APP 选择(APP1 / APP2)

  • 固件升级标志

  • 设备的配置参数(校准值、序列号等)

这些数据如果仅存在 SRAM 中(比如放在 .noinit 段的 reset_flag),在 断电后就会丢失,因此需要放到 Flash 的固定区域
我们把这块区域称为 ENV 区


2. ENV 与 Flash 的关系

在硬件上,ENV 区其实就是 Flash 的一段固定地址空间
例如在我的项目中:

  • Bootloader 占用:0x08000000 ~ 0x08005FFF

  • APP1 占用:0x08006000 ~ 0x08011FFF

  • APP2 占用:0x08012000 ~ 0x0801DFFF

  • ENV 区: 0x0801E000 ~ 0x0801FFFF (大小 8KB)

可以看到,ENV 区和 APP 一样,本质上就是 Flash 的一部分,只不过我们约定它专门用来存放配置数据。


3. Flash 基础操作

在此之前,我已经封装好了 Flash 的基本操作函数(见上篇博客):

  • remo_flash_erase_sector(addr) 擦除一个扇区(页)

  • remo_flash_write_words(addr, length, buf) 按字写数据

  • remo_flash_read_bytes(addr, length, buf) 读取数据

这些 API 面向硬件驱动,能保证我可以对任意地址的 Flash 进行擦写和读取。


4. 为什么还需要 ENV 封装

如果直接用上面的 Flash API 来操作 ENV,每次都要写一堆逻辑:

  • 先读出数据结构

  • 校验 Magic 字和 CRC

  • 如果无效,就写默认值

  • 修改参数后,要重新计算 CRC

  • 擦除扇区,再写回

这样做既繁琐,又容易遗漏步骤。

于是我在此基础上,增加了一层 ENV 管理模块(env.c / env.h),专门负责 ENV 区的参数读写。


5. ENV 管理模块设计

ENV 数据结构

typedef struct {uint32_t magic;        // 魔术字,区分有效/无效uint32_t version;      // 数据版本号uint32_t app_select;   // 上次选择的 APPuint32_t upgrade_flag; // 升级标志uint32_t reserved[8];  // 预留参数uint32_t crc32;        // 数据校验
} env_data_t;
  • magic 用来判断是否是有效 ENV(比如 0xA55AA55A)

  • crc32 用来保证数据完整性

提供的 API

  • env_load() 从 Flash 读取 ENV,并校验

  • env_save() 保存数据到 ENV 区,自动更新 CRC

  • env_init_default() 初始化默认 ENV

  • env_get() 获取内存副本指针

这样,Bootloader 或 APP 就可以很轻松地操作 ENV:

// 加载 ENV
if (env_load(NULL) != 0) {env_init_default(); // 自动写入默认值
}
env_data_t *env = env_get();// 修改参数
env->app_select = 1; // 下次启动 APP2
env_save(env);

6. 对比总结

  • 直接用 Flash API(硬件层)

    • 优点:灵活,可以对任意地址操作

    • 缺点:每次操作 ENV 都要写一堆重复代码,容易出错

  • 用 ENV 管理模块(逻辑层)

    • 优点:

      • 封装了 CRC 校验和 Magic 检查

      • 自动管理擦写流程

      • 接口简洁,调用更安全

    • 缺点:只能操作约定的 ENV 区,不够通用(但对 Bootloader 足够了)


7. 总结

ENV 区其实就是 Flash 中的一块区域,只是我们在软件层面给它定义了一个结构体,并且通过 ENV 模块来集中管理。

这种 两层封装 的好处是:

  • 下层(remo_flash_plat.c):只负责硬件的通用擦写

  • 上层(env.c):负责具体的数据结构和业务逻辑

这样不仅逻辑清晰,还能避免代码重复,提高可靠性。

http://www.xdnf.cn/news/19587.html

相关文章:

  • 前缀和(优化算法)
  • ClickHouse常见问题——ClickHouseKeeper配置listen_host后不生效
  • 面试 TOP101 动态规划专题题解汇总Java版(BM62 —— BM82)
  • 二、SVN基础命令速查表
  • leetcode 1792. 最大平均通过率 中等
  • 通过 select into outfile / load data infile 进行数据导入导出学习笔记
  • 开源项目_金融分析工具TradingAgents
  • 01数据结构-红黑树
  • python 数据类型【python进阶一】
  • java设计模式一、单例模式
  • 【K8s】整体认识K8s之Configmap、Secret/ResourceQuota资源配额/访问控制
  • Linux应用开发-windows,linux环境下相关工具
  • Adobe Illustrator 2025最新破解教程下载安装教程,Illustrator2025最新版下载
  • AI 安全与伦理:当大模型拥有 “决策能力”,我们该如何建立技术边界与监管框架?
  • 新手向:前端开发中的常见问题
  • NLP大语言模型数据准备
  • 基于 DNA 的原核生物与微小真核生物分类学:分子革命下的范式重构​
  • Shell编程(二):正则表达式
  • FastK v1.1 安装与使用-生信工具59
  • Gradle vs. Maven,Java 构建工具该用哪个?
  • 喜讯!华清远见参与制定的《电子产品印制电路板可制造性设计(DFM)和可靠性设计规范》正式发布
  • 【无标题】训练、推理适用的数据类型
  • 专题:2025全球新能源汽车供应链核心领域研究报告|附300+份报告PDF、数据仪表盘汇总下载
  • 关闭页面强制清除所有循环定时器
  • ES6手录02-字符串与函数的扩展
  • Kotlin 协程异步任务工具类:高效处理异步操作与超时控制
  • UE5 为啥原生的NotifyState写逻辑会有问题
  • 开源低代码平台(NocoBase)
  • 20250828的学习笔记
  • 9.1日IO作业