CH582M Flash 存储与 SNV 详解¶
芯片型号:CH582M / CH583 / CH592 等 CH58x 系列
主题:片上 Flash 分区地图、BLE SNV 配对绑定机制、外接存储扩展方案
学习状态:🚧 原理已整理,待代码验证
更新日期:2026年7月18日
⚠️ 这是踩坑重灾区,也是 CH58x 系列最核心的"非直观"设计之一。建议通读本节后再动手写 Flash 相关代码。
1. 整片 Flash 地址映射总览¶
CH582M / CH583M 的 Flash 总容量为 512 KB(0x00000000 ~ 0x0007FFFF),物理上就是同一块 Flash,沁恒通过地址划分人为定义了 4 个功能区域:
| 地址范围 | 区域名称 | 容量 | 用途 | 用户可读写? |
|---|---|---|---|---|
0x00000000 ~ 0x0006FFFF | CodeFlash | 448 KB | 用户程序 + 蓝牙 LIB | ✅ 程序读写(带加解密) |
0x00070000 ~ 0x00077FFF | DataFlash | 32 KB | 用户非易失数据 | ✅ 直接读写(无加密) |
0x00078000 ~ 0x0007DFFF | BootLoader | 24 KB | 系统引导程序(ISP/IAP) | ❌ 用户不可写 |
0x0007E000 ~ 0x0007FFFF | InfoFlash | 8 KB | 系统配置信息(校准参数、MAC 等) | ❌ 用户不可写 |
📌 关键认知:CodeFlash 和 DataFlash 只是同一物理 Flash 的不同地址段,不是两块独立的芯片。它们的差异是沁恒在 SDK 里做了不同的接口封装(CodeFlash 带内核加解密,DataFlash 不加)。
2. CodeFlash 内部分区(BLE 例程视角)¶
在官方 BLE 例程中,CodeFlash 的 448 KB 并非全给用户程序,实际被划分如下:
| 子区域 | 容量 | 地址范围(相对) | 用途 |
|---|---|---|---|
| 启动区 | 4 KB | 0x0000 ~ 0x0FFF | 中断向量表、启动代码 |
| imageA (APP) | 152 KB | 0x1000 ~ 0x26FFF | 用户主程序 |
| imageA (OTA) | 152 KB | 0x27000 ~ 0x4DFFF | OTA 升级固件备份区 |
| imageA (IAP) | 4 KB | 0x4E000 ~ 0x4EFFF | IAP 跳转程序 |
| BLE LIB | 136 KB | 0x4F000 ~ 0x6FFFF | 蓝牙协议栈库(只读) |
| 合计 | 448 KB | — | — |
💡 这意味着:如果你不需要 OTA 功能,理论上可以把
imageA (OTA)这 152 KB 腾出来给主程序或数据存储。但注意——这涉及到修改链接脚本和启动文件,不是开箱即用。
3. DataFlash 内部细分手册(避坑用)¶
DataFlash 只有 32 KB(0x70000 ~ 0x77FFF),但 BLE 协议栈会自动占用尾部区域,用户可用的其实更少:
| DataFlash 偏移 | 占用长度 | 对应宏定义 | 用途 |
|---|---|---|---|
0x0000 | 12 KB | CONFIG_MESH_NVS_ADDR_DEF 等 | MESH 网络信息存储 |
0x3000 | — | — | 用户可用空间 |
0x7000 | 4 字节 | OTA_DATAFLASH_ADD | OTA 升级标志位 |
0x7E00 | 512 B | BLE_SNV_ADDR 等 | BLE 配对绑定信息 |
0x7FFF | — | — | DataFlash 边界 |
⚠️ 血泪教训:如果你往
0x7E00之后写自己的数据,会导致 BLE 配对信息丢失,下次连接手机需要重新配对!
4. CodeFlash vs DataFlash 操作差异¶
| 特性 | CodeFlash | DataFlash |
|---|---|---|
| 基地址 | 0x00000000 | 0x00070000 |
| 最小擦除单位 | 4 KB(块擦) | 256 B(页擦)或 4 KB(块擦) |
| 读写接口 | 带内核加解密 | 无加解密,直接操作 |
| 擦除后读前 4 字节 | 显示为"乱码"(正常,因加密) | 正常显示 |
| ISP 工具读取 | 可读出完整固件 | 可单独读出 DataFlash |
| RAM 缓冲区对齐 | 必须 4 字节对齐 | 必须 4 字节对齐 |
| 写前操作 | 必须先擦除 | 必须先擦除 |
5. Flash 擦写寿命与时间开销¶
| 参数 | 数值 |
|---|---|
| 擦写寿命(常温 5~45°C) | 10 万次(典型值) |
| 擦写寿命(全温 -40~85°C) | 5 万次(典型值) |
| 数据保持 | 20 年 |
| 单块(4KB)擦除时间 | 6 ~ 30 ms(典型 16 ms) |
| 单字编程时间 | 1 ~ 4 ms(典型 2 ms) |
实测:擦 1 字节和擦 4 KB 耗时几乎一样(都是 ~17 ms),因为最小擦除单位是 4 KB。写 1 字节也要 ~2 ms。所以 Flash 操作要尽量批量、减少擦写次数。
6. BLE SNV — 配对绑定信息存储(避坑重点)¶
SNV(Secure Non-Volatile) 是 BLE 协议栈用来保存配对绑定(Pairing & Bonding)信息的关键区域。这块区域躲藏在 DataFlash 尾部,新手很容易误写进去导致连接异常。
6.1 什么是配对绑定?¶
| 概念 | 含义 | 类比 |
|---|---|---|
| 配对(Pairing) | 首次连接时交换密钥、建立安全链路 | 初次见面,交换名片 |
| 绑定(Bonding) | 把配对得到的密钥保存下来,下次自动重连 | 把名片存通讯录,下次直接打电话 |
CH582M 的 BLE 协议栈在首次配对成功后,会把密钥信息(LTK、IRK、设备地址等)写入 SNV 区域。如果 SNV 被擦除或覆盖,下次手机连接时会拒绝重连(错误码 0x13:主机拒绝配对),必须删除手机端的配对记录重新配对。
6.2 SNV 在 DataFlash 中的位置¶
根据官方 EVT 包中的 CONFIG.h 定义:
#define BLE_SNV_ADDR 0x00077000 // 实质 Flash 地址
#define BLE_SNV_SIZE 0x00001000 // 分配大小 4 KB(注意:实际有效约 512 B ~ 1 KB)
但这里有个坑——0x77000 是实质地址,DataFlash 的接口函数使用的是偏移地址(减去 0x70000),所以偏移地址是 0x7000。
更常见的 EVT 版本实际使用:
| 参数 | 数值(典型版本) | 说明 |
|---|---|---|
| 实质 Flash 地址 | 0x00077E00 | 在 DataFlash 范围内 |
| DataFlash 偏移 | 0x7E00 | 使用 EEPROM_WRITE 时传这个偏移 |
| 占用长度 | 约 512 B(实际 ~224 B/次配对) | 一次配对密钥约 224 B,按 256 B 对齐 |
| 配对次数上限 | 约 2 ~ 4 次(取决于具体实现) | 超出需覆盖旧记录或扩 SNV 区 |
⚠️ 血泪教训:不同版本的 EVT 包、不同芯片型号(CH582/CH583/CH592),SNV 地址可能不同。务必以你当前工程
CONFIG.h或app_mesh_config.h中的宏定义为准!
6.3 一次配对实际占用多少字节?¶
实测(从 DataFlash 写入记录推算):
- 单次配对成功后的密钥数据约 224 B
- BLE 协议栈按 256 B 块 对齐存储
- 所以
BLE_SNV_SIZE = 0x1000 (4 KB)看似很多,实际可能支持 8~16 次配对记录,或用于不同用途分区
如果你需要连接多台主机并回连(比如一个蓝牙键盘要连 3 台电脑),可以动态切换 SNV 地址实现——每次切换广播 MAC 地址时,同时切换对应的 SNV 存储区,每台主机的配对信息互不干扰。
6.4 SNV 相关操作禁忌¶
| 操作 | 后果 |
|---|---|
往 0x7E00 偏移之后写用户数据 | BLE 配对信息丢失,需重新配对 |
| 擦除 DataFlash 时未保护 SNV 区 | 所有绑定设备失效 |
| 更换 BLE 例程版本未核对 SNV 宏 | 可能新例程的 SNV 地址和旧版不同,导致数据冲突 |
| 关闭 BLE 配对功能却保留 SNV 宏 | 浪费 4 KB DataFlash,其实可释放 |
6.5 释放 SNV 空间的方法¶
如果你不需要 BLE 配对功能(比如广播传感器数据,任何手机都能连,不做安全认证):
- 在
CONFIG.h中查找配对使能宏,如BLE_BONDING_ENABLE或SNV_ENABLE - 关闭后,SNV 区域变为普通 DataFlash 可用空间
- 但注意:关闭配对后,BLE 连接将没有加密,在敏感场景(如键鼠)不建议
💡 一句话:SNV 是 BLE 的"通讯录",别乱动。要动之前先确认你的配对策略,再决定要不要释放这块空间。
6.6 SNV 绑定设备数量上限 — 128 个的真相¶
来自论坛官方技术支持(WCH TECH_Lpc)的确认:
CH592 的
BLE_SNV_NUM最大值为 32 × 4 = 128 个,改宏与BLE_SNV_ADDR配合使用,每 256 字节可以多存放一个设备。
算术验证¶
| 参数 | 计算 | 结果 |
|---|---|---|
| 单个设备占用 | 256 B(协议栈按块对齐) | 256 B |
| 128 个设备总需求 | 128 × 256 B | 32,768 B = 32 KB |
| CH582/CH592 DataFlash 总容量 | — | 32 KB |
结论:128 个绑定的理论上限是 32 KB DataFlash 全部给 SNV 用时实现的。
但"理论上"不等于"实际工程可用"¶
| 场景 | 占用 DataFlash | 剩余用户空间 | 可行性 |
|---|---|---|---|
| 默认 1 个绑定 | 256 B | ~31.7 KB | ✅ 正常 |
| 6 个绑定 | 1,536 B | ~30.5 KB | ✅ 正常 |
| 128 个绑定(理论极限) | 32 KB | 0 KB | ⚠️ 前提:不开 MESH、不用 OTA 标志、不存任何用户数据 |
| 128 绑定 + MESH(12 KB) | 44 KB | -12 KB | ❌ 溢出,编译报错 / 运行崩溃 |
实际工程建议¶
| 你的需求 | 建议 SNV 数量 | 配置要点 |
|---|---|---|
| 普通 BLE 从机(连 1~2 台手机) | 1 ~ 4 | 默认即可,改 BLE_SNV_NUM 宏 |
| 蓝牙键盘(连 3 台电脑切换) | 3 ~ 6 | 改 BLE_SNV_NUM=6,确保 BLE_SNV_ADDR 后有足够空间 |
| 需要配对很多设备(如门禁系统) | 10 ~ 32 | 需要关闭 MESH,释放前 12 KB |
| 超过 32 个绑定 | 不推荐用 CH582M | 考虑改用 Nordic nRF 系列(NVS 存储更灵活)或外接 SPI Flash 存配对信息 |
📌 核心认知:Deepseek 说的"理论上最多 128 个"数字本身是对的,但隐含的"全占 DataFlash"条件必须明确。实际工程中,128 个绑定 = 放弃 MESH、放弃 OTA DataFlash 标志、放弃所有用户数据存储——绝大多数场景下做不到。按需调整
BLE_SNV_NUM,不要盲从理论上限。
7. 能扩展 Flash 容量吗?¶
| 问题 | 答案 | 说明 |
|---|---|---|
| CodeFlash 能扩展吗? | ❌ 不能 | 物理上限 448 KB,改不了 |
| DataFlash 能扩展吗? | ❌ 不能 | 物理上限 32 KB,改不了 |
| 总 Flash 能扩展吗? | ❌ 不能 | 512 KB 是芯片物理容量 |
| 但可以通过重新分区释放空间吗? | ✅ 可以 | 不需要 OTA 时,可释放 152 KB OTA 区 |
| 外接存储扩展可行吗? | ✅ 推荐 | 通过 SPI 外接 Flash/EEPROM/SD 卡 |
实用策略:
- CodeFlash 不够:如果程序超过 152 KB(APP 区),要么换 CH585(128 KB SRAM,但 CodeFlash 也是 448 KB),要么优化代码、关闭不需要的 BLE 功能,或者外接 SPI Flash 存储大资源(如字库、图片)。
- DataFlash 不够:32 KB 对于配置参数、历史数据很快会满。推荐做法:
- 频繁变化的数据 → 外接 SPI Flash(如 W25Q128,16 MB)
- 小量配置参数 → 用 DataFlash 的
0x3000~0x6FFF区域(约 16 KB 可用) - 极简配置 → 直接复用 OTA 标志位附近的空闲区(谨慎)
- RAM 不够:32 KB SRAM 跑 BLE 协议栈后只剩约 10~15 KB 给用户。如果不够,直接升级 CH585(128 KB SRAM)或 CH592(26 KB SRAM,反而更小)。
8. 外接存储扩展方案¶
既然片上 Flash 和 DataFlash 都受限于物理容量,外接存储芯片就成了扩展的核心手段。CH582M 有 1 组 SPI 和 4 组 UART,可以通过 SPI 接口挂载各种存储器。
8.1 三种主流外接存储方案对比¶
| 特性 | EEPROM(AT24C 系列) | SPI Flash(W25Q 系列) | FRAM(FM25L 系列) |
|---|---|---|---|
| 接口 | I2C(CH582M 无原生 I2C,需软模拟或外挂) | SPI(硬件支持) | SPI(硬件支持) |
| 典型容量 | 1 KB ~ 1 MB | 512 KB ~ 256 MB | 4 KB ~ 1 MB |
| 擦写单位 | 字节级(可单字节改写) | 4 KB 扇区(必须整块擦) | 字节级(直接覆盖,无需擦除) |
| 写入速度 | 慢(~5 ms / 字节) | 中等(~100 µs / 页,但擦除 ~16 ms) | 极快(~150 ns / 字节) |
| 擦写寿命 | 10 万 ~ 100 万次 | 10 万次 | 10 亿次(10¹⁴) |
| 数据保持 | 10 年 @ 85°C | 20 年 @ 85°C | 45 年以上 |
| 功耗(写) | ~3 mA | ~15 mA | ~150 µA |
| 典型单价 | ¥0.5 ~ 2(小容量) | ¥1 ~ 5(常用 8 MB) | ¥10 ~ 50(较贵) |
| 最佳场景 | 配置参数、密码、校准值 | 固件、字库、图片、日志、大数据 | 高频事件记录、医疗数据、实时日志 |
📌 核心差异:EEPROM 和 FRAM 都是字节可改写,不用先擦除;Flash 必须先擦 4 KB 再写。FRAM 的寿命和速度碾压前两者,但价格也贵。
8.2 选型决策树¶
需要存什么?
├── 配置参数(几十 ~ 几百字节)
│ ├── 更新频率低(一天几次) → DataFlash 或 AT24C02
│ └── 更新频率高(一秒几次) → FRAM(FM25L256)
├── 日志/历史数据(KB ~ MB 级)
│ ├── 只追加、不频繁擦写 → SPI Flash(W25Q64)
│ └── 频繁覆盖、循环记录 → SPI Flash + 磨损均衡算法
├── 字库/图片/音频资源(MB 级)
│ └── 只读、偶尔更新 → SPI Flash(W25Q128)
└── 固件备份/OTA 包
└── 大容量、一次性写入 → SPI Flash(W25Q64 / W25Q128)
8.3 与 CH582M 的接口对接建议¶
| 外接芯片 | 接口方式 | CH582M 连接 | 注意点 |
|---|---|---|---|
| W25Q64(8 MB SPI Flash) | SPI 硬件 | MOSI→PA12, MISO→PA13, SCK→PA14, CS→任意 GPIO | SPI 速率可达半主频(40 MHz @ 80 MHz),读写极快 |
| AT24C02(256 B I2C EEPROM) | GPIO 模拟 I2C | 任意 GPIO 软模拟 | 速率低(~100 kHz),但省引脚 |
| FM25W256(32 KB FRAM) | SPI 硬件 | 同 W25Q64 | 写操作无需等待,可像 RAM 一样随机写 |
| SD 卡(microSD) | SPI 模式 | 同 SPI Flash | FAT 文件系统可用 FatFs,适合大容量日志 |
8.4 实用策略:分级存储架构¶
最成熟的方案是把存储按访问频率和重要性分层:
| 层级 | 存储介质 | 存放内容 | 访问策略 |
|---|---|---|---|
| L1 片上 | DataFlash | BLE 配对信息、设备 ID、校准参数 | 开机加载,运行时只读 |
| L2 外接小容量 | EEPROM / FRAM | 用户设置、运行配置、实时计数器 | 按需读写,频繁更新 |
| L3 外接大容量 | SPI Flash / SD 卡 | 日志、字库、图片、音频、OTA 包 | 批量读写,顺序/追加为主 |
💡 示例:一个 BLE 温湿度传感器 - DataFlash:存设备名称、广播间隔、配对密钥 - 外接 W25Q64:存 30 天的温湿度历史数据(每 10 分钟一条) - 如果需要 1 秒级高频记录 → 换 FRAM,或做 RAM 缓冲 + 定期批量写入 Flash
8.5 关于"扩展"的最终总结¶
| 问题 | 答案 |
|---|---|
| 片上 Flash 能物理扩展吗? | ❌ 不能,448 KB CodeFlash + 32 KB DataFlash 是硬上限 |
| 程序代码超过 152 KB 怎么办? | ① 关闭 OTA 释放 152 KB;② 精简代码;③ 换 CH585(也是 448 KB,但 RAM 大) |
| 用户数据超过 32 KB 怎么办? | 外接 SPI Flash(W25Q64/W25Q128),性价比高,最常用 |
| 频繁写入的参数怎么存? | 外接 EEPROM(AT24C) 或 FRAM(FM25L),按擦写频率和预算选 |
| 日志类大数据怎么存? | 外接 SPI Flash + 环形缓冲区/日志文件系统,做好磨损均衡 |
🔑 核心心法:CH582M 的片上存储是"精打细算型",用 DataFlash 存关键的、掉电必须保的少量配置;用外接存储兜底大容量和频繁写入。不要试图把所有东西塞进 32 KB DataFlash 里——那是给自己找不痛快。
参考文献¶
本文内容基于以下资料整理与验证:
| 来源 | 标题/说明 | 关键信息 |
|---|---|---|
| WCH 产品页 | 沁恒 CH583/CH582 产品页 | 核心规格、外设参数 |
| WCH 下载中心 | CH583DS1.PDF 数据手册 | Flash 分区、地址映射、擦写参数 |
| WCH 社区论坛 | 【SNV】BLE_SNV 相关问题 | 官方确认:CH592 的 BLE_SNV_NUM 最大值为 128 个,每 256 字节多存一个设备 |
| WCH 社区论坛 | ch571 Peripheral dataflash 问题 | DataFlash 中蓝牙库保存了数据,需避开系统区域 |
| WCH 社区论坛 | ch582 dataflash 讨论 | 蓝牙绑定占用 DataFlash 最后 256 字节,操作接口说明 |
| WCH 社区论坛 | CH582 BLE MESH DataFlash 问题 | MESH 默认使用 DataFlash 前 12 KB,修改扇区配置 |
| CSDN 博客 | 沁恒 RISC-V 蓝牙芯片 Flash 分区优化 | Flash 地图、SNV 位置、分区数据 |
| CSDN 博客 | 【沁恒蓝牙 mesh】CH58x flash 分区与数据存储管理 | DataFlash 偏移地址、MESH 存储区域、SNV 地址 |
| 博客园 | CH573/571/CH583/582/CH592/591 内部 flash 和 eeprom 的读写 | CodeFlash / DataFlash 地址范围、读写接口说明 |
| 立创商城 | CH582M 商品参数 | 工作电压、ADC 位数、GPIO 数量等 |