LV013-单片机的通用架构
前面几篇讲的都是"计算机的通用原理"和"系统的组成",这一篇开始向芯片内部聚焦。先给出一个重要论断:所有单片机的内部架构都是同一个骨架——内核挂在总线上,总线上挂着存储器和各种外设。厂商不同、型号不同,变的只是各部件的规格和数量,骨架从 8 位机的 51 到 32 位机的 STM32 从未变过。
看懂这张通用的框图,你拿到任何一颗新 MCU 的数据手册都能迅速对号入座——只需要问三个问题:什么内核?多少存储?有哪些外设?
一、 总览:一张通用框图
从下到上看这张图,分五个层次:
- 内核(CPU 子系统):CPU 核心 + 内核外设(NVIC、SysTick),是芯片的大脑;
- 高速总线 AHB:内核与存储器、支撑系统之间的骨干通道;
- 存储器与支撑系统:FLASH、SRAM、时钟/复位挂在 AHB 上(电源管理等低速支撑电路挂在 APB 一侧);
- 外设总线 APB:经总线桥从 AHB 分出,挂载低速外设;
- 片上外设:GPIO、定时器、串口等,面向控制对象的功能模块。
芯片边界之外还有两样东西:外部晶振(给时钟系统提供节拍)和传感器/执行器(经引脚与片上外设相连)。下面自上而下逐层拆解。
二、 内核:单片机的大脑
内核(Core)就是 LV001 里讲的 CPU 在单片机里的具体形态,包含三块。
1. 处理器核心与指令集
处理器核心包括寄存器组、ALU 和控制逻辑。定义"这个 CPU 认识哪些指令"的是指令集架构 ISA(Instruction Set Architecture)——目前 MCU 世界的主流是两大阵营:
(1)ARM Cortex-M:32 位 RISC 架构,ARM 公司设计内核、授权给芯片厂商(ST/NXP/GD/兆易等几十家)生产芯片。Cortex-M 家族又分档次:M0/M0+ 主打超低功耗低成本,M3 是性价比最平衡的一代(STM32F1 用它),M4 加了 DSP 指令和浮点单元,M7 主打高性能。内核统一是 Cortex-M 最大的生态优势:换厂商不用换知识;
(2)RISC-V:2010 年诞生的开源指令集,免授权费,模块化设计,是国产芯片(GD32V、CH32V、ESP32-C3)的新选择。
两大阵营的指令不兼容,但编程模型高度相似——寄存器、中断、异常、总线,学通一个另一个几天就能上手。
2. 寄存器组
内核里有一组速度极快的存储单元——寄存器(比任何存储器都快一个数量级),Cortex-M3 的寄存器组包括:
- 通用寄存器 R0~R12:放运算的操作数和结果;
- 堆栈指针 SP(R13):指向当前栈顶,函数调用、中断现场保存全靠它;
- 链接寄存器 LR(R14):保存函数返回地址;
- 程序计数器 PC(R15):指向下一条指令——就是 LV001 里那个驱动程序自动推进的 PC;
- 程序状态寄存器 xPSR:记录标志位(零标志、进位、负数、溢出)和当前中断号。
程序运行的本质就是"在寄存器之间搬运和加工数据"。Cortex-M 寄存器组的逐个详解见 01-概述/LV030-CortexM3简介。
3. 内核外设:与大脑长在一起的部分
有些部件物理上和内核做在同一块区域、深度耦合,称为内核外设(区别于后面挂在总线上的片上外设):
(1)NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器):管理所有中断的使能、优先级、嵌套与响应,是 Cortex-M 不可分割的一部分,详见 01-概述/LV040-CortexM3异常 与 LV045-CortexM3的NVIC中断控制;
(2)SysTick:内核自带的 24 位向下计数定时器,为操作系统提供统一的"心跳"节拍(FreeRTOS 的 tick 就常用它)。
把它们做进内核的好处:所有用 Cortex-M 的芯片,中断行为和系统节拍的行为都完全一致,程序可移植性强。
三、 总线与体系结构
1. 三类信号线
总线(Bus)是连接各部件的一组公共信号线。LV001 讲过"数据线"和"控制线",完整的总线其实有三类:
- 地址总线(AB,Address Bus):单向,由内核发出,指明要访问哪个部件的哪个单元。位数决定寻址空间——32 位地址线可寻址
= 4 GB; - 数据总线(DB,Data Bus):双向,承载实际搬运的指令和数据,宽度常见 8/16/32 位;
- 控制总线(CB,Control Bus):混合方向,传递读写命令、时钟、中断请求、DMA 请求等协调信号。
所有部件都挂在同一组总线上,靠地址区分"这次访问是谁"——这就是后面"存储器映射"存在的前提。
2. 分层总线:主干道与小马路
如果所有外设都挂在一条高速总线上,慢速外设(如 100 kHz 的 I2C)会拖累高速部件(如内核取指)。所以单片机的总线分成层级:
- AHB(Advanced High-performance Bus):高速骨干,内核、FLASH、SRAM、DMA、总线桥挂在上面,跑系统级高速率;
- APB(Advanced Peripheral Bus):低速分支,经总线桥(Bridge)从 AHB 分出,GPIO、UART、定时器等低速外设挂在上面。
像城市交通:先走主干道(AHB),到站后拐进小马路(APB)。慢速外设的访问不会阻塞主干道——既省成本(APB 逻辑简单),又不拖累关键路径。STM32F1 的具体总线结构(ICode/DCode/System 三条总线、BusMatrix 总线矩阵、APB1/APB2 两条分支)在 10-STM32基础/LV040-STM32系统架构 里详细拆解。
3. 冯·诺依曼还是哈佛:单片机的选择
LV001 在介绍冯·诺依曼结构时,已经引出了它的"对手"哈佛结构(指令/数据分开存储、独立总线、并行访问),并给出了两种结构的总线级对比框图——建议先回看那一节。这里把差异收拢成一张速查表:
| 维度 | 冯·诺依曼结构 | 哈佛结构 |
|---|---|---|
| 程序与数据 | 同一存储器、同一组总线 | 分开存储、各有独立总线 |
| 取指与取数据 | 共用一条通道,只能轮流 | 两条通道,可以并行 |
| 存储分配 | 灵活,程序数据比例运行时可变 | 固定,程序区数据区出厂确定 |
| 结构与成本 | 简单、成本低 | 复杂、成本高 |
| 典型应用 | 早期计算机、PC 的统一内存 | 单片机(Cortex-M)、DSP |
结构选择的本质是一道取舍题:程序和数据要不要共用存储与访问通道。到这里,本篇已经讲完了单片机的存储介质(FLASH/SRAM 天然分工)和总线分层(AHB/APB),回答这道题所需的材料齐了——下一节正式展开。
4. 单片机与 PC 各用什么架构
4.1 单片机:普遍采用哈佛结构
主流单片机(包括 STM32 的 Cortex-M 内核)都采用哈佛结构,准确说是改进型哈佛结构。为什么单片机做了这个选择?四个原因,按分量排序:
(1)物理介质天然分开——这是"必然"而非"选择"。单片机的程序要求掉电不丢,只能放 FLASH;数据要求高速随机读写,只能放 SRAM。两种存储介质特性完全不同,物理上本来就是两块芯片区域——硬件形态天然就是哈佛结构,"程序进 FLASH、数据进 SRAM"只是顺应物理;
(2)性能:取指与取数并行。哈佛结构下 CPU 执行指令的同时可以预取下一条指令。Cortex-M 专门分出 I-Code(取指)和 D-Code(取数据)两条总线接入总线矩阵,再配合 FLASH 接口的预取缓冲,掩盖高主频下 FLASH 等待周期的影响(STM32F103 在 72 MHz 下就有 2 个等待周期),让程序尽量跑出标称性能;
(3)可靠性:程序区天然只读。控制类设备往往常年无人值守运行,"程序被误改"等于灾难。哈佛结构下指令存储器可以加硬件写保护,一个跑飞的野指针最多踩坏数据,改不动程序本身——配合看门狗复位就能恢复运行。这对 LV010 讲的"最坏情况也可预期"的可靠性哲学是重要一环;
(4)用不上统一内存的灵活性。PC 统一内存的核心红利是"按需装载"——但单片机的程序直接在 FLASH 里原地执行(XIP),上电即运行,根本没有"把程序从磁盘搬进内存"这一步;程序编译完就固化了,不存在运行中动态增减。灵活性的好处用不上,缺点的代价却要实付,自然不选冯·诺依曼。
再说改进型哈佛(Modified Harvard)的含义:纯粹的哈佛结构里,程序空间和数据空间连地址都不相通——早期 AVR 单片机就是这样,C 语言要用 progmem 关键字和两套指针分别访问 Flash 与 RAM 中的数据,非常别扭。Cortex-M 的改进是"总线分开、地址统一":物理上取指总线和数据总线独立(保住并行的性能),逻辑上共享同一个 4 GB 统一地址空间(保住统一编址的编程便利——C 程序里一个指针可以按地址访问任何存储区,不用区分两套空间)。可以说 Cortex-M 同时拿到了两种结构的优点。
4.2 PC:冯·诺依曼式的统一内存
PC 的主存是统一编址的 DRAM:操作系统内核、各个应用程序、它们的数据,全混放在同一个内存里,靠 MMU 划分区域互相隔离。整体上这是一台冯·诺依曼机器。为什么 PC 反着选?同样是需求决定的:
(1)灵活性是第一需求。PC 上程序是 GB 级的、数量不定——用户开多少个程序、每个程序处理多大的数据,事先全然不知。统一内存可以动态分配:程序大就多占,程序多就挤一挤。若用哈佛结构,程序区和数据区的大小出厂焊死,任何比例都会在某种负载下严重浪费;
(2)有磁盘和 MMU 支撑"按需装载"。程序平时躺在 SSD 里,运行时操作系统把它装进内存的任意空闲区域,MMU 的虚拟地址重定位让每个程序都"以为"自己独占内存(详见 LV010 关于 MMU 的展开)。这套机制以统一内存为前提——程序可以被装到任何地址,恰恰因为内存不分"谁的区";
(3)多任务共享内存。几十个进程共用一套 DRAM、按需增减、靠 MMU 隔离,这是现代操作系统的地基。两套物理分开的存储器会让进程管理、内存回收的复杂度爆炸;
(4)成本。一套大容量通用 DRAM 比两套各占一半的专用存储便宜得多,产业生态也统一;
(5)性能短板用缓存补。冯·诺依曼瓶颈的解法不是改主存结构,而是在 CPU 近旁加多级 Cache:频繁访问的指令和数据被缓存到离内核最近的地方。有意思的是,现代 x86 CPU 的 L1 缓存恰恰是指令、数据分开的(L1i 与 L1d)——离内核最近的存储层偷偷"哈佛化"了,主存层保持冯·诺依曼。
【注意】
两种结构的边界比教科书印象更模糊:单片机在物理哈佛之上做了统一编址(吸收冯·诺依曼的编程便利),PC 在统一内存之上做了分缓存(吸收哈佛的并行性能)。工程世界里没有结构教条,只有"为设计目标取舍"——单片机"程序固化、数据量小、求稳求快",所以哈佛;PC"程序海量、动态装载、求灵活",所以冯·诺依曼。
四、 存储器:FLASH 与 SRAM
1. 分工
LV007 说过单片机把主存拆成两块,这里给出完整对比:
| 维度 | FLASH(闪存) | SRAM(静态随机存储器) |
|---|---|---|
| 存什么 | 编译好的程序、常量、中断向量表 | 变量、堆栈、动态数据 |
| 掉电后 | 数据保留(非易失) | 数据丢失(易失) |
| 读写特点 | 随机读快;写之前必须按扇区擦除,寿命有限(万次级) | 随机读写极快,无限次 |
| 成本与密度 | 便宜、密度高 | 贵、密度低 |
| STM32F103C8T6 | 64 KB | 20 KB |
为什么不给 SRAM 也做成掉电不丢?成本和工艺不允许;为什么不用 FLASH 跑变量?擦写太慢且寿命有限。两者分工是物理特性决定的必然。
2. XIP:代码原地执行
CPU 直接从 FLASH 取指执行,不需要先把程序搬到 RAM——这叫 XIP(eXecute In Place,片内执行/原地执行)。它依赖 FLASH 的字节级随机读能力:CPU 给一个地址,FLASH 立刻返回该地址的数据,满足取指时序要求。这也是单片机选 NOR FLASH 存程序的原因(NAND 只能按块读,CPU 没法直接取指)——详见 01-概述/LV010-常见存储器 与 LV012-EEPROM与Flash。
一个例外值得知道:当需要"运行中自我更新程序"(IAP/Bootloader)时,MCU 不能一边从 FLASH 取指一边擦写同一片 FLASH——这时要把一小段代码搬进 SRAM 执行,见 20-STM32的启动/LV010-在内部SRAM调试。
3. 统一地址空间与存储器映射
FLASH、SRAM、每个外设,全部被编进同一个 4 GB 地址空间——一张"地址 → 部件"的对照表管理整颗芯片,这张表就是存储器映射(Memory Map)。访问 0x2000 0000 就是访问 SRAM,访问 0x4001 0800 就是访问 GPIOA 的寄存器。"地址即部件"是理解单片机编程的关键一跃,完整机制留到 LV016-寄存器与硬件控制 展开,Cortex-M 的空间划分见 01-概述/LV022-CortexM0存储器映射 与 01-概述/LV035-CortexM3存储器系统。
五、 片上外设:单片机的手脚
外设(Peripheral)是集成在芯片内、面向控制对象的功能模块。按功能分四类:
- 数字 I/O 类:GPIO——最基本的外设,每个引脚可配成输入或输出,读按键、点灯、模拟时序全靠它,是"单片机的手";
- 通信类:UART(串口,最经典的调试通道)、I2C/SPI(连接传感器和存储芯片)、CAN(汽车与工业现场)、USB——是"单片机的嘴和耳朵";
- 模拟类:ADC(模数转换,把电压变成数字)、DAC(数模转换)——连接模拟世界的桥梁;
- 定时控制类:定时器 TIM(定时、计数、PWM 输出、输入捕获)、看门狗 IWDG/WWDG(程序跑飞时复位自救)、RTC(实时时钟);
- 数据搬运类:DMA(不经 CPU 在存储器与外设之间搬运数据,给内核减负)。
外设不直接连在内核上,而是挂在总线上,每个外设有自己的寄存器组;内核通过读写这些寄存器来指挥外设——这正是 LV016 的主题。本站《基本外设篇》将逐个深入。
六、 支撑系统:让芯片活着
框图外围还有三组不起眼但缺一不可的电路,它们不参与计算,却决定芯片能否工作:
(1)时钟系统:单片机每个动作都按节拍进行。外部晶振(HSE)或内部振荡器(HSI)经 PLL 倍频产生主时钟 SYSCLK,再经 AHB/APB 分频分给 CPU 和各外设——这棵"时钟树"决定每个部件跑多快,也决定了功耗大小(给不用的外设关时钟是省电的基本功)。详见 40-STM32时钟/LV001-STM32F1时钟系统;
(2)复位与电源:上电复位、手动复位、看门狗复位、欠压复位;电源管理提供睡眠/停止/待机等低功耗模式,是电池类产品的命根子;
(3)调试接口:SWD/JTAG,PC 通过它烧写程序、单步调试、观察变量——没有它就没有嵌入式开发效率。
七、 拿 STM32F103 对号入座
把通用骨架套到 STM32F103 上逐项验证:
| 通用骨架的部件 | STM32F103(以 C8T6 为例) |
|---|---|
| 内核 | Cortex-M3,72 MHz,512 KB 以下 FLASH 型号的主流选择 |
| 指令集 | ARMv7-M(Thumb-2) |
| FLASH / SRAM | 64 KB / 20 KB |
| 高速总线 | AHB + BusMatrix(ICode/DCode/System 三条接口) |
| 外设总线 | APB1(36 MHz)/ APB2(72 MHz)两条 |
| 片上外设 | 2×SPI、2×I2C、3×USART、1×USB、1×CAN、2×ADC、4×定时器、37 个 GPIO |
| 支撑系统 | HSE 8 MHz 晶振 + PLL ×9 = 72 MHz,SWD 调试 |
展开版的详细框图见 10-STM32基础/LV040-STM32系统架构。
记住这张骨架图的价值:以后看任何一颗新 MCU——不管厂商吹得多天花乱坠——都是"内核 + 总线 + 存储 + 外设"的排列组合。对着数据手册问三个问题(什么内核?多少存储?有哪些外设?),芯片的定位和选型方向就基本清楚了。骨架之外还有两个藏在内核里的问题:CPU 认识哪些指令(指令集)?它靠什么把指令执行得又快又稳(流水线)?这就是下一篇 LV014-指令集与流水线 的内容。
本文档由 markdowncli 技能辅助生成