第1章:知己知彼——MCU内存架构深度剖析(Flash、SRAM、寄存器)

各位同学,咱们开始上课。

做血压计嵌入式开发,说白了就是跟内存打交道。你写的每一行代码,最终都要落到Flash、SRAM或者寄存器里。我见过太多工程师,代码写得飞起,一跑起来就崩,查半天发现是内存踩踏了。嗯,这其实是对MCU的内存架构不够了解。

今天这一章,咱们就把MCU的“家底”翻个底朝天。你搞懂了Flash、SRAM和寄存器这三兄弟,后面做内存优化才能有的放矢。

1.1 Flash:你的代码住在这里

Flash是什么?简单说,它就是MCU的“硬盘”。掉电不丢数据,专门用来存你的程序代码、常量数据,还有那些初始化配置。

我个人习惯把Flash想象成一本写满指令的“书”。MCU上电后,就从这本书的第一页开始读,一条一条执行。书页翻完了,程序也就跑完了。

但Flash有个“脾气”——它读得快,写得慢。读一个字节可能只要几个时钟周期,但写一个字节,那得几十毫秒。你想想看,要是程序在Flash里跑,频繁地往Flash里写数据,那性能得多糟糕?

所以,我建议你把Flash当成“只读”的。程序代码、查表数据、字符串常量,这些放Flash里。运行时需要频繁修改的变量,千万别放Flash里,否则你会后悔的。

Flash的关键特性:

  • 非易失性:掉电不丢数据
  • 读取速度快(通常几十ns)
  • 写入速度慢(ms级别)
  • 擦除次数有限(通常10万次左右)
  • 按扇区擦除,不能按字节擦除

我在项目中遇到过一件事:有个同事把血压计的校准参数存在Flash里,每次测量完都更新一次。结果用了半年,Flash就坏了。为什么?因为校准参数所在的扇区被擦写了超过10万次。后来我改成只在参数变化时才写Flash,问题就解决了。

避坑指南:我曾经因为没注意Flash的擦写寿命,导致产品批量返修。从那以后,我定了个规矩:所有需要频繁更新的数据,一律放SRAM;只有那些几乎不变的数据,才放Flash。

1.2 SRAM:你的数据在这里跳舞

SRAM是MCU的“内存条”。掉电就丢,但读写速度极快。你的全局变量、局部变量、堆栈,全都在SRAM里。

做血压计开发,SRAM是最宝贵的资源。为什么?因为MCU的SRAM通常很小,几KB到几十KB。你想想看,一个血压计要处理传感器数据、做滤波算法、驱动LCD显示、还要跑蓝牙协议栈……这点SRAM够用吗?

不够。所以你必须精打细算。

我一般把SRAM分成三块来管理:

区域 用途 典型大小
全局/静态变量区 存放全局变量、static变量 1-4 KB
堆区 动态内存分配(malloc) 0.5-2 KB
栈区 函数调用、局部变量 0.5-2 KB

你看,总共才几KB,分来分去就没了。所以,我建议你在血压计项目里尽量少用动态内存分配。malloc和free用多了,容易产生内存碎片。你想想看,一个血压计跑几个月,内存碎片越来越多,最后malloc失败,系统就挂了。

我的小技巧:在血压计里,我通常把所有的缓冲区都定义为全局数组,大小在编译时就确定好。这样虽然浪费了点空间,但胜在稳定可靠。医疗设备嘛,稳定第一。

1.3 寄存器:你的CPU在跟硬件“聊天”

寄存器是什么?它是CPU内部的小型存储单元,速度比SRAM还快。CPU直接操作寄存器,来控制外设、读取状态、传输数据。

说白了,寄存器就是CPU和硬件之间的“翻译官”。你要让ADC开始采样,就往ADC控制寄存器里写个1;你要知道ADC采样完了没,就读ADC状态寄存器。

在血压计里,寄存器操作无处不在:

  • GPIO寄存器:控制传感器供电、驱动气泵、电磁阀
  • ADC寄存器:读取压力传感器数据
  • 定时器寄存器:产生PWM波驱动气泵、计时
  • UART/SPI/I2C寄存器:与蓝牙模块、LCD通信

我刚开始做血压计时,总觉得寄存器操作很麻烦。后来发现,其实寄存器操作就是“读-改-写”三步走。你只要记住:不要随意修改保留位,不要同时操作多个位域,一般不会出问题。

寄存器操作的核心原则:

  1. 读寄存器值到变量
  2. 修改变量中对应的位
  3. 将变量写回寄存器

千万别直接往寄存器里写一个魔数,那样很容易把其他位搞乱。

举个例子,你要让PA0引脚输出高电平:

// 错误做法:直接写值,可能影响其他引脚
GPIOA->ODR = 0x0001;

// 正确做法:读-改-写
uint32_t temp = GPIOA->ODR;
temp |= (1 << 0);
GPIOA->ODR = temp;

你看,多写两行代码,就能避免很多坑。我见过有人直接写寄存器,结果把其他引脚的状态也改了,导致气泵误动作。嗯,这种bug最难查。

1.4 三者的关系:一个形象的比喻

为了帮你更好地理解,我打个比方:

  • Flash 就像你的“书架”。书(代码)放在上面,需要的时候拿下来读。但你不能一边读一边往书里写新内容,那太慢了。
  • SRAM 就像你的“办公桌”。你正在处理的数据、草稿纸(变量)都放在桌上。桌子就这么大,东西多了就放不下。
  • 寄存器 就像你的“手”。你要拿笔(控制外设)、翻书(读状态)、写字(传数据),都得用手直接操作。

你想想看,一个高效的工程师,一定是书架放得整齐、桌面收拾干净、手速又快又准。做内存优化,也是这个道理。

1.5 本章小结

这一章,咱们把MCU的内存架构拆开看了个遍:

  • Flash存代码和常量,掉电不丢,但写入慢、有寿命限制
  • SRAM存变量,速度快,但容量小、掉电丢
  • 寄存器是CPU和外设的接口,操作要小心

下一章,咱们就进入实战环节——教你如何用工具把内存使用情况看得一清二楚。到时候,你会发现自己写的代码到底吃了多少内存。

好了,今天就到这里。有问题随时问我。