在学习 RTOS(实时操作系统)或者单片机编程的时候,我们经常会遇到任务栈(Stack)、任务调度等概念,而这些都与 CPU 的架构密切相关。只有深入理解 ARM 处理器的架构,你才能真正掌握 RTOS 的核心。
今天,我们就从 ARM 硬件架构 和 基础汇编指令 这两个方面,来快速入门 ARM 架构。
如果你曾经自己组装过电脑,你会发现电脑的基本组成是:
这些组件是分开的,需要主板连接起来。
但是,在嵌入式系统(单片机)里,情况有所不同。单片机使用的是 SoC(System on Chip,系统级芯片),即把 CPU、内存、存储等都集成在一个芯片上,如下图所示:
------------------------
| ARM SoC |
| ------------------- |
| | CPU | |
| ------------------- |
| | 内存 (SRAM) | |
| ------------------- |
| | Flash (存储) | |
| ------------------- |
------------------------
这里:
在 ARM 处理器中,所有的计算都是在 CPU 内部进行的,内存(RAM)只是存储数据,它本身不具备计算能力。来看一个例子:
假设 C 语言代码:
a = a * b;
在 ARM 处理器中,CPU 无法直接在内存里进行乘法运算,它必须经过 4 个步骤:
a
b
a * b
这就是 精简指令集(RISC) 的特点——CPU 只提供基本的读写指令,所有计算都在 CPU 内部的 寄存器 里完成。
那么,CPU 内部 是怎么存储变量 a
和 b
的呢?来看 ARM CPU 的内部架构:
-------------------------
| 计算单元 (ALU) |
-------------------------
| R0 R1 R2 R3 R4 |
| R5 R6 R7 R8 R9 |
| R10 R11 R12 R13 R14 |
-------------------------
ARM 处理器有一组 寄存器(Register),用来存储运算过程中的临时数据。
重点:
a
可能存放在 R0
b
可能存放在 R1
a * b
的结果会存放在 R0
这就解释了为什么 ARM 处理器在执行 C 代码时,需要先把数据加载到寄存器。
在 ARM 处理器中,某些寄存器有特殊作用:
寄存器 | 名称 | 作用 |
---|---|---|
R13 | SP(Stack Pointer) | 栈指针,用于管理任务栈 |
R14 | LR(Link Register) | 链接寄存器,用于存放函数返回地址 |
R15 | PC(Program Counter) | 程序计数器,存放下一条要执行的指令 |
函数调用过程
void funcA() {
funcB(); // 调用 funcB
}
funcA()
调用 funcB()
时,funcA()
的返回地址会被存入 LR(R14)。funcB()
执行完后,会从 LR 取回地址,回到 funcA()
继续执行。这个机制对于 RTOS 的任务切换 至关重要,因为任务切换本质上就是修改 PC(R15)寄存器的值。
ARM 处理器不能直接在内存里计算数据,必须先把数据加载到寄存器。
LDR R0, [R1]
解释:
STR R0, [R1]
解释:
ADD R0, R1, R2
解释:
R1 + R2
,把结果存入 R0
SUB R0, R1, R2
解释:
R1 - R2
,把结果存入 R0
CMP R0, R1
解释:
R0
和 R1
,结果存入 状态寄存器(PSR)B
(跳转)指令的执行B label
解释:
label
位置BL func
解释:
func
,并保存返回地址LR(R14)
当 func
执行完后,我们可以用:
BX LR
返回到调用 func
的位置。
✅ ARM 处理器的 CPU、寄存器、内存 关系
✅ 任务栈(SP)、函数返回地址(LR)、程序计数器(PC) 的作用
✅ 基本的 ARM 汇编指令(LDR、STR、ADD、SUB、CMP、B、BL)
如果你想更进一步,建议你尝试:
ARM 处理器是嵌入式开发的基石,理解它的本质,你才能真正掌握 FreeRTOS 和更高级的嵌入式开发技术!
希望这篇文章对你有帮助,我们下节课见!