(嵌入式八股)No.3 STM32(1)
1.1 了解即可:MCU/MPU/SOC/FPGA/DSP/NPU
嵌入式处理芯片主要根据集成度和应用场景分为 MCU、MPU 和 SoC。
- MCU (微控制器) 就像‘全能单身公寓’,集成了 CPU、RAM、Flash 和外设,没有 MMU,主要运行裸机或 RTOS,用于低功耗实时控制(如 STM32)。
- MPU (微处理器) 就像‘高性能引擎’,计算能力强但需要外挂 DDR 和存储,拥有 MMU,可以运行 Linux 等大型系统(如早期 ARM9)。
- SoC (片上系统) 则是现代主流的‘摩天大楼综合体’,它在 MPU 的基础上进一步集成了 GPU、NPU、WiFi 等专用模块,适合高性能计算和多媒体应用(如 RK3588)。
此外,还有专攻数学运算的 DSP、硬件逻辑可编程的 FPGA 以及专攻 AI 加速的 NPU,它们常作为协处理器配合 SoC 使用。”
1.2 STM32启动流程(熟悉)
注:如果觉得八股还是不太了解,后续可以去结合 OTA 升级再巩固巩固
先了解一下什么是MSP和PSP
MSP(Main Stack Pointer)主堆栈指针
•用途:默认堆栈指针,用于处理模式(Handler Mode),即中断、异常处理等系统级操作。
•特点:
◦系统复位后自动启用;
◦所有异常处理(如中断服务程序)都必须使用MSP;
◦始终在特权模式下使用;
◦是全局共享的堆栈指针,系统内核使用它来处理紧急事务。
PSP(Process Stack Pointer)进程堆栈指针
◦用途:用于线程模式(Thread Mode)下的应用程序代码(如用户任务)。
◦特点:
▪需要显式配置,常用于多任务系统(如RTOS);不同任务切换的时候PSP指针就会指向不同的任务,这个在RTOS调试中也会用到!
▪每个任务可拥有独立的PSP,实现堆栈隔离;
▪可在特权或非特权模式下使用(取决于配置);
▪若某个任务发生堆栈溢出,不会影响其他任务或系统内核。
启动流程(熟悉)
1️⃣硬件复位序列(芯片自动完成)
上电/外部复位(POR/PDR 电路释放后就是重启之后,内核处于已知状态):
◦PC = 0x0000 0000
◦所有寄存器为默认值,Flash 等待周期按出厂设定。
取第一个字——主堆栈顶(MSP)
内核从 0x0000 0000 读出 32 位数值(也就是4个字节),装入 MSP。
(该值实际存放在 Flash 0x0800 0000,通过地址别名映射到 0x0000 0000。)
取第二个字——复位向量
从 0x0000 0004 读出 Reset_Handler 地址,跳转到该地址,开始执行用户代码。

2️⃣启动文件运行(startup_stm32xxxx.s)
4. 建立 C 运行环境
•把 Flash 中的 .data 常量拷贝到 RAM(已初始化全局变量)
•把 .bss 段全部清零(未初始化全局变量)
•可选:把 _estack 重新装入 MSP,确保栈顶对齐
系统级初始化
◦调用 SystemInit():使能 FPU、配置 RCC 时钟树、重映射中断向量表(写 SCB->VTOR)
◦调用 __libc_init_array():为 C++ 全局对象调用构造函数(纯 C 工程亦会执行)
进入用户世界
◦bl main(这个是BL是汇编指令,先记下返回地址(把下一条指令地址写入 LR 寄存器),再跳转到目标函数。)
从此开始执行用户 main(),启动流程结束。
3️⃣总结:
上电/复位
→ 硬件自动:取 MSP → 取 Reset_Handler → 跳转
→ 软件汇编:copy .data / zero .bss → SystemInit() → __libc_init_array()
→ main()
1.3 ARM架构(了解即可,寄存器务必掌握)
入门了解即可
Cortex‐M3 的一个简化视图

ARM 架构的

在嵌入式开发领域,ARM架构的处理器占了90%以上的市场份额, 大多数人学习嵌入式都是从ARM开始的。如果时间足够的话可以去学习一下简单的汇编指令。如果时间不够的话就深入了解ARM体系结构和工作流程。
ARM 即 Advanced RISC Machines 的缩写,在嵌入式开发领域,ARM 架构的处理器占了 90%以上的市场份额, 大多数人学习嵌入式都是从 ARM 开始的。如果时间足够的话可以去学习一下简单的汇编指令。如果时间不够的话就深入了解 ARM 体系结构和工作流程。
ARM 有三种不同系列的处理器,分为 A 、R 、M 三种系列,同时有多种架构,比如 ARMv6 、ARMv7 、ARMv8 。
- M 系列处理器主要是低性能芯片,应用于单片机领域,我们常说的 STM32F103、STM32F407、STM32H750 都是 M 内核的,分别对应 M3/M4/M7 内核。
- A 系列处理器主要是高性能芯片,跑 Linux 系统,比如 imx6ull、STM32MP15x 等。
- R 系列处理器实时性较强,芯片性能高于 M 系列,主要应用于工业领域
ARM 从 v6 版本开始转变设计理念,最终在 v7 版本中正式将内核架构划分为 A、R、M 三大系列,分别针对不同的应用场景。
架构演进:ARMv7 与 ARMv8
- 核心区别
- ARMv7:32 位架构,确立了 A/R/M 三大分系。
- ARMv8:引入了 64 位支持(AArch64),并在 M 系列中引入了硬件级安全特性。
- Cortex-M 系列的演进 (v7-M vs v8-M)
ARMv7-M (如 M3/M4/M7):
- 传统的扁平内存模型。
- 安全性依赖软件或 MPU 进行简单的区域保护。
ARMv8-M (如 M23/M33):
- TrustZone 技术:最大的升级点。将硬件资源物理隔离为 安全域 (Secure World) 和 非安全域 (Non-secure World)。
- 应用价值:在物联网设备中保护密钥和核心启动代码,防止通过非安全应用窃取核心数据。
Cortex-M3/M4 /M7 均基于 ARMv7-M 架构,具备以下核心硬件特性: 务必熟悉
流水线与总线架构
- 三级流水线:取指 (Fetch) \rightarrow\解码 (Decode) \rightarrow\执行 (Execute)。支持分支预测。
- 哈佛架构 (Harvard Architecture):指令总线 (I-Code) 和 数据总线 (D-Code) 分离,可同时进行指令读取和数据访问。
- 统一编址:尽管总线分离,但指令和数据共享同一个 4GB 线性地址空间 (0x00000000 ~ 0xFFFFFFFF)。
- AMBA 总线标准:基于 AHB-Lite (高速) 和 APB (外设) 总线协议,支持高吞吐量操作。
存储与位操作
- 位带操作 (Bit-banding):支持对两个特定存储器区域(SRAM 和 外设区)进行位寻址。通过访问“别名区”的一个字,实现对“位带区”某个位的原子操作(读-改-写)。
- MPU (存储器保护单元):可选组件。提供硬件级的内存访问权限控制(如设置某区域为只读、不可执行),增强系统健壮性。(M7 会带)
中断与系统控制
- NVIC (嵌套向量中断控制器):紧耦合于内核,低延迟(12 个周期)。支持 中断嵌套。支持 8~256 个 中断优先级。支持最多 240 个外部中断请求。
- 双堆栈机制 (Shadow Stack Pointer):MSP (主堆栈指针):用于 OS 内核和中断服务程序。PSP (进程堆栈指针):用于用户应用程序。作用:实现 OS 内核与用户任务的堆栈隔离,提高安全性。
- 低功耗支持:支持睡眠模式 (Sleep) 和深度睡眠 (Deep Sleep),配合 WFI/WFE 指令。
总结
ARM处理器的工作模式:(了解)
- 应用程序正常运行时,ARM 处理器工作在用户模式(User mode),当程序运行出错或有中断发生时,ARM 处理器就会切换到对应的特权工作模式。
- 用户模式属于普通模式,有些特权指令是运行不了的,需要切换到特权模式下才能运行。在 ARM 处理器中,除了用户模式是普通模式,剩下的几种工作模式都属于特权模式。
- 目的是为了实现代码隔离和安全保护。
- 在 CM3 中取消了 FIQ 的概念(v7 前的 ARM 都有这个 FIQ,快中断请求),这是因为有了更新更好的机制——中断优先级管理以及嵌套中断支持,它们被纳入 CM3 的中断管理逻辑中。


两种操作模式 (Operation Modes)
用于区分“普通代码”和“异常代码”。
- 处理者模式 (Handler Mode):谁在用:所有的 中断服务例程 (ISR) 和 异常处理函数。特点:永远处于特权级。中断发生时,处理器自动进入此模式;中断返回时,自动退出。
- 线程模式 (Thread Mode):谁在用:普通的 主应用程序 (main 函数及后台任务)。特点:复位后默认进入此模式。它可以是特权级,也可以是用户级。
两种特权级 (Privilege Levels)
用于提供内存访问保护机制。
- 特权级 (Privileged Level):权限:上帝视角。可以访问所有内存地址(包括系统控制寄存器 NVIC, SCB 等),执行所有指令。默认:系统复位后,默认处于 特权级。
- 用户级 (User Level):权限:受限视角。不能访问系统关键寄存器(如 NVIC, SYSTICK)。不能访问被 MPU 保护的特权内存区。这些区域通常是操作系统的区域。试图访问受限资源会触发 HardFault 或 BusFault。目的:运行不受信任的程序或普通的 OS 任务,防止它们把系统搞崩。
总结
Handler 模式专管中断,永远是特权的;
Thread 模式跑应用程序,复位是特权的,但可以切成用户级;
特权切用户很简单(改寄存器),用户想回特权必须通过 SVC 系统调用(异常)。
寄存器及其作用(务必掌握)
Cortex-M3 处理器内部包含两类核心寄存器:一是 通用寄存器 (R0-R15),其中 R0-R7 (低组) 可被所有指令(包括 16 位 Thumb)访问,而 R8-R12 (高组) 主要由 32 位 Thumb-2 指令访问,R13-R15 则有特定用途(SP, LR, PC);二是 特殊功能寄存器(如 xPSR, PRIMASK, CONTROL),它们负责保存处理器状态和控制运行模式,且必须通过专用的系统指令(MSR/MRS)才能访问。
寄存器组

a.通用寄存器
R0-R12(通用寄存器)
- R0~R3 通常用来传递函数参数,所以函数形参一般不超过 4 个!
- R4~R11 用来保存程序运算的中间结果或函数的局部变量等(一般都是硬件自动保存)
- R12 常用来作为函数调用过程中的临时寄存器。
- 但是注意:绝大多数 16 位 Thumb 指令只能访问 R0‐R7,而 32 位 Thumb‐2 指令可以访问所有寄存器。
R13(栈指针,SP)
- 物理寄存器:通用寄存器 R13 被用作堆栈指针。
- 主堆栈指针(MSP):或写作 SP_main。这是缺省的堆栈指针,它由 OS 内核、异常服务例程以及所有需要特权访问的应用程序代码来使用。
- 进程堆栈指针(PSP):或写作 SP_process。用于常规的应用程序代码(不处于异常服用例程中时)。
- 用途:永远指向当前堆栈的栈顶(Stack Top)。
- 操作:在函数调用(保存现场)和中断处理时,负责利用 PUSH(入栈)和 POP(出栈)指令管理内存数据。
- 对齐规则:SP 的最低两位永远是 0。这意味着堆栈地址必须是 4 字节对齐 的(Word Aligned)。例如:SP 可以是 0x20001000 或 0x20001004,但绝不可能是 0x20001001。

▪特点:在函数调用和中断处理中,栈指针用于管理栈的入栈(PUSH)和出栈(POP)操作。
R14(链接寄存器,LR)
▪用途:存储函数调用返回地址。
▪特点:在函数调用时,ARM处理器会将返回地址存储到LR寄存器中。在函数返回时,从LR寄存器中获取返回地址。
R15(程序计数器,PC)
▪用途:存储当前指令的地址。
▪特点:PC寄存器始终指向当前正在执行的指令的地址。每次指令执行后,PC会自动更新到下一条指令的地址。CPU一条一条不停地取指令,程序也就源源不断地一直运行下去。
举个🌰:比如我们运行函数的时候他是怎么运行的呢?可以理解为是把函数的地址加载到了 PC 指针上,然后就会运行 PC 指针指向的这个函数(这个地方再去复习一下函数指针)
b.特殊功能寄存器

- 程序状态字寄存器组(PSRs)
- Application PSR (APSR)
- Execution PSR (EPSR)
- Interrupt PSR (IPSR)
- 中断屏蔽寄存器组(PRIMASK, FAULTMASK, BASEPRI) 只有在特权级下,才允许访问这 3 个寄存器PRI-MASK、FAULT-MASK 和 BASE-PRI 寄存器主要用于异常或者中断的屏蔽。每一个异常都有一个优先级的属性。



要访问 PRIMASK, FAULTMASK 以及 BASEPRI,同样要使用 MRS/MSR 指令,如:
MRS R0, BASEPRI ; 读取 BASEPRI 到 R0 中 MRS R0, FAULTMASK ; 似上 MRS R0, PRIMASK ; 似上 MSR BASEPRI, R0 ; 写入 R0 到 BASEPRI 中 MSR FAULTMASK, R0 ; 似上 MSR PRIMASK, R0 ; 似上
c.控制寄存器(CONTROL)
- CONTROL[1] (堆栈选择位): 决定线程模式使用 MSP(0) 还是 PSP(1)。限制:Handler 模式下该位恒为 0(强制使用 MSP)。只有在特权级下才允许修改此位。
- CONTROL[0] (特权级位): 0 为特权级,1 为用户级。单向限制: 特权级可直接写 1 切换到用户级;但用户级禁止写此位,想返回特权级必须触发异常(如 SVC),在异常服务例程中修改。
CONTROL 寄存器用于定义特权级和堆栈指针的选择,仅能通过特殊指令 (MRS/MSR) 访问:

MRS <gp_reg>, <special_reg> ;读特殊功能寄存器的值到通用寄存器 MSR <special_reg>, <gp_reg> ;写通用寄存器的值到特殊功能寄存器
d.状态寄存器(了解)
CPSR(当前程序状态寄存器)
•用途:存储当前处理器的状态信息,包括条件标志、中断屏蔽位等。
•主要字段:
◦N(负标志)表示结果为负。
◦Z(零标志):表示结果为零。
◦C(进位标志):表示有进位或借位。
◦V(溢出标志):表示有溢出。
◦I(IRQ中断屏蔽位):1表示禁止IRQ中断,0表示允许IRQ中断。
◦F(FIQ中断屏位):1表示禁止FIQ中断,0表示允许FIQ中断。
◦M(模式位):表示当前处理器的工作模式(如用户模式、中断模式等)。
SPSR(保存的程序状态寄存器)
•用途:在中断或异常处理时,保存当前的CPSR值。
•特点:当处理器进入中断或异常处理模式时,CPSR的值会被保存到SPSR中。在中断或异常处理结束时,从SPSR中恢复CPSR的值。
指令集(了解 Thumb‐2)
Thumb‐2 指令集为编程带来了更多的灵活性。许多数据操作现在能用更短的代码搞定,这意味着 Cortex‐M3 的代码密度更高,也就对存储器的需求更少。


历史痛点 (ARM7 时代)
在 Cortex-M3 之前的处理器(如 ARM7TDMI),必须在两种互斥的状态间切换:开发者需要混合编程,处理器需要在运行时进行状态切换(Switching Overhead),既浪费时间又增加软件管理的复杂度。
- ARM 状态 :执行 32 位指令。性能强,但代码体积大。
- Thumb 状态 :执行 16 位指令。代码密度高(省 Flash),但性能弱(功能是 ARM 的子集)。
M3 的突破 (Thumb-2)
Cortex-M3 只支持 Thumb-2 指令集 ,彻底抛弃了传统的 ARM 指令集。
- 水乳交融 :Thumb-2 允许 16 位指令 和 32 位指令 在同一个指令流中混合使用,无需手动切换状态。取指都按 32 位处理。同一周期最多可以取出两条指令,留下了更多的带宽给数据传输。
- 自动识别 :处理器自动判断指令长度。
- 双重优势 :既拥有 Thumb 的高代码密度,又拥有 ARM 的高性能。
优点:
消灭切换开销:不再需要在 32 位/16 位 状态间跳来跳去,节省了执行时间和指令空间。
中断响应更快:以前中断必须在 ARM 状态下处理,现在直接在 Thumb-2 下处理,无需切换,响应更迅速。
开发更简单:不需要再考虑哪个文件用 ARM 编译、哪个用 Thumb 编译,统一汇编器 (Unified Assembler) 搞定一切。
从入门到上岸,一站式搞定求职! 本硕纯机械,无竞赛无论文,后转行嵌入式软件开发(因为课题组师哥转嵌入式拿到30Woffer之后狠狠心动),秋招最终收获35W+offer可以为27届或者28届的的UU们提供参考,可以关注一下!!!

查看15道真题和解析