第三章 TC3xx内存布局详解

做嵌入式开发,特别是搞OTA升级,内存布局是绕不开的坎。我常说一句话:搞不清内存布局,就像开车不看仪表盘——迟早要出事。

TC3xx的内存体系其实挺有意思的。它不像有些MCU那样简单粗暴地划几个区就完事,而是把Flash、RAM、OTP这些资源安排得明明白白。今天我就带大家把这块硬骨头啃下来。

3.1 Flash分区:你的代码住哪儿

TC3xx的Flash,说白了就是程序存储的大本营。它分为几个关键区域,每个区域都有自己的脾气。

区域名称 起始地址 大小 用途
PFlash0 0x80000000 2MB 主程序代码存储
PFlash1 0x80200000 2MB 备用程序或Bootloader
DFlash0 0xAF000000 64KB 数据存储,比如校准参数
DFlash1 0xAF010000 64KB EEPROM模拟区

这里有个坑,我必须要说。PFlash0和PFlash1虽然大小一样,但它们的擦写寿命和访问速度其实有细微差别。我在做OTA方案时,曾经因为没注意这个差异,导致升级过程中出现奇怪的超时问题。

关键点:PFlash的擦除单位是16KB,而DFlash是4KB。这意味着如果你要频繁更新小数据,用DFlash更划算。

3.2 RAM区域:你的数据在哪儿跑

RAM这块,TC3xx做得挺讲究。它把RAM分成了好几个独立的小区,每个小区都有专门的用途。

  • DSPR(Data Scratch Pad RAM):每个核独享的,速度最快。我习惯把关键变量和堆栈放这里。
  • PSPR(Program Scratch Pad RAM):也是每个核独享,但专门给程序用的。放一些时间敏感的函数,比如中断服务程序。
  • LMU(Local Memory Unit):所有核共享的,容量最大。适合放全局变量和缓冲区。
  • DLMU(Data Local Memory Unit):也是共享的,但访问路径更短,速度比LMU快一点。

你想想看,如果OTA升级时把下载的固件包放在DSPR里,那肯定不行——空间不够,而且会影响其他任务的运行。我一般把下载缓冲区放在LMU,解压和校验时再用DSPR加速。

我的习惯:OTA升级的临时缓冲区放在LMU,大小建议至少256KB。这样即使网络波动导致数据重传,也不会把RAM撑爆。

3.3 OTP区域:一次写入,终身受用

OTP,全称是One-Time Programmable。说白了就是只能写一次,写错了就废了。TC3xx的OTP区域不大,但作用很关键。

它主要用来存这些东西:

  1. 芯片唯一ID:每颗芯片出厂时就烧录好了,不能改。
  2. 安全密钥:用于固件签名验证的根密钥。我建议把公钥哈希放这里。
  3. 配置字:比如启动模式、Flash保护位等。

我曾经见过一个项目,工程师把调试接口的解锁密码写到了OTP里,结果密码设错了,芯片直接变砖。嗯,那场面,真是欲哭无泪。

警告:OTP区域一旦写入,无法擦除。在量产前一定要反复确认配置值。建议先在开发板上验证无误后,再写入正式产品。

3.4 内存映射与访问权限

TC3xx的内存映射不是简单的线性排列。它用了多层映射和权限控制,目的是保证安全。

举个例子,PFlash在CPU看来是0x80000000开始的地址,但在DMA控制器看来,可能是另一个地址。这种设计是为了隔离不同主设备的访问路径。

权限控制这块,TC3xx引入了MPU(内存保护单元)。你可以给每个任务分配不同的内存访问权限。比如OTA升级任务只能写DFlash,不能碰PFlash0里的主程序。

// 配置MPU保护PFlash0区域
// 只允许读,不允许写
IfxMpu_setRegion(0,               // 区域编号
                 0x80000000,      // 起始地址
                 0x200000,        // 大小2MB
                 IfxMpu_Access_readOnly);  // 只读权限

这个机制在OTA升级时特别有用。你可以把正在运行的程序区域设为只读,防止意外篡改。等升级完成、系统重启后,再切换保护策略。

3.5 实战中的内存布局规划

好了,理论说完了,咱们来点实际的。我一般做OTA方案时,内存布局是这样规划的:

区域 内容 大小 说明
PFlash0 Bootloader 128KB 负责启动和升级引导
PFlash0剩余 App主程序 ~1.8MB 正常运行时执行
PFlash1 升级备份区 2MB 存放新固件
DFlash0 升级状态标志 4KB 记录升级进度
DFlash1 用户参数 64KB 校准数据、配置等

为什么要这么分?原因很简单:

  • Bootloader放在PFlash0开头,上电就能执行。
  • 升级备份区放在PFlash1,这样升级时不会覆盖正在运行的程序。
  • 升级状态标志用DFlash,因为擦写次数多,而且数据量小。

我记得有一次,客户要求升级过程中断电后能恢复。我就在DFlash0里存了一个升级状态机,每次擦写前先更新状态。这样即使断电,重启后也能从断点继续。

避坑指南:千万不要把升级状态标志和用户参数放在同一个DFlash扇区。否则每次升级都会擦除用户参数,客户会找你算账的。我曾经就吃过这个亏,后来学乖了,分开存放。

3.6 小结

TC3xx的内存布局,说白了就是一套精心设计的资源分配方案。Flash管存储,RAM管运行,OTP管安全。搞懂了这些,你就能像搭积木一样,把OTA升级方案安排得明明白白。

下一章,我会带大家深入Bootloader的设计,看看怎么在TC3xx上实现一个可靠的启动引导程序。到时候咱们再细聊。