单片机内核什么是内核这是一个很抽象的问题。有时会听到 ARMv7-M、ARMv7-A 架构又听过 Cortex-M3、Cortex-M4 内核——它们分别是什么本文以 M3/M4 内核为切入点介绍内核与架构的基本概念。本文以文字为主尽量简单描述。M3/M4 内核先看下面这张M3/M4 内核框图这里先不用纠结“内核”到底是什么意思。看到这张图你可能会产生两个疑问为什么 M3 和 M4 的内核框图可以共用同一张图图中为什么没有外设问题一为什么 M3/M4 共用同一张框图查阅 M3 和 M4 的内核手册会发现它们的内容几乎完全一样——无论是内核寄存器R0~R15还是特殊功能寄存器xPSR、CONTROL 等。这是因为它们都隶属于ARMv7-M 架构因此寄存器、流水线设计等均相同流水线细节不了解也没关系。有兴趣的话可以对比core_cm3.h和core_cm4.h两个文件你会发现它们基本一致。甚至内核中最核心的“内核外设”区别于芯片厂商添加的片上外设——如 NVIC、SysTick、MPU、SCB 以及调试相关的 ITM、DWT、IPI——也完全相同连地址都一样。这种一致性正是“同属 ARMv7-M 架构”的体现。ARMv7-M 架构规定了内核的流水线设计并强制包含 NVIC、SysTick 等单元图中已标出同时包含可选的 MPU 和调试单元M3/M4 都实现了。这些单元的统一地址也是 ARMv7-M 规范的一部分。那么不同之处在哪里M4 包含浮点运算单元FPU而 M3 没有。这是两者最大的差异。为什么一个有 FPU、一个没有却都属于 ARMv7-M因为 ARMv7-M 架构允许在系统控制空间SCS的地址范围内添加不同的内核单元来实现功能扩展。FPU 的存在与否并未跳出 ARMv7-M 的框架但有了 FPU 就可以执行浮点运算指令。至此第一个问题已解答M3/M4 共用同一框图因为它们差异不大且同属 ARMv7-M。但需要注意ARMv7-M 并不只包含 M3/M4——例如 M7 内核还增加了 Cache。更准确的理解是M3/M4/M7 都是 ARMv7-M 架构的具体实现子集。问题二为什么框图中没有外设如果对 STM32 有较深入的理解不难知道所谓外设对内核而言就是挂载在地址总线上的一些寄存器。内核通过地址总线访问它们再通过数据总线读写数据。外设这部分完全由芯片厂商自由设计——这就是为什么即使都是 M3/M4 内核不同芯片的外设差异却很大。尽管外设不同但内核访问它们的方式完全一样如 LDR、STR 指令只是寄存器的值设置不同导致外设的工作模式不同。因此外设不属于内核的一部分但地址/数据总线属于内核设计的一部分。小结什么是内核什么是架构基于以上分析可以这样理解内核执行指令所需的硬件支持。架构一种内核设计蓝图。因此ARMv7-M提供整体设计框架Cortex-M3 / M4 / M7是该框架的具体实现STM32F407VET6则是这个具体实现再加上厂商配套的外围设施。内核寄存器和内核外设上一小节说到内核是一种具体实现其中这个具体实现中相同的部分主要是内核寄存器和内核外设所以我们这里主要介绍以下M4内核相信读者到这里为止对内核架构具体芯片应该有了一定的了解了。在地址划分中有一块称为“私有外设总线”PPB的区域与内核框图中底部的 PPB 对应通过专用总线访问。这部分与普通外设不同包含的单元与内核工作模式紧密相关我称之为内核外设。本文重点介绍三个核心部分NVIC、SCB、SysTick。其他部分触类旁通可自行探索。在此之前先介绍内核寄存器。推荐参考《M3/M4 内核权威指南》讲解非常详细大多数问题都能从中找到答案。内核通用寄存器R0~R12通用目的寄存器主要用于数据计算和缓存。R13SP堆栈指针寄存器。程序运行时自动切换主栈指针MSP和进程栈指针PSP。R14LR连接寄存器通常保存程序返回地址。R15PC程序计数器始终指向下一条要执行的指令。R0~R12没有太多特别之处主要用于缓存临时变量。函数调用时部分寄存器用于传递参数。SP栈指针在物理上只有一个寄存器但对应两个逻辑指针MSP 和 PSP具体使用哪个由特殊寄存器 CONTROL 决定。中断中使用 MSP裸机程序中也使用 MSP而在 RTOS 环境下任务运行时使用 PSP。掌握这些基本够用。LR连接寄存器的使用可分为三种场景中断打断了主程序中断嵌套函数调用前两种属于中断场景中断发生时会自动将xPSR, PC, LR, R12, R3, R2, R1, R0压入当前栈。中断函数执行结束后LR 通常保存一个特殊值称为特殊值1执行BX LR即可自动恢复现场继续执行主程序。若发生中断嵌套硬件同样自动压栈LR 保存另一个特殊值特殊值2执行BX LR恢复上一层中断现场。在这两种中断场景中LR 存放的是特殊值真正的返回地址来自压栈的 PC 值。函数调用场景硬件不会自动压栈需要软件手动压栈通常保存 R4~R11或根据需求额外保存。此时 LR 保存的是真正的返回地址上一级函数中下一条指令的地址最后通过BX LR跳转回去。PC始终指向下一条要执行的指令。内核特殊寄存器1. xPSR组合程序状态寄存器32 位寄存器反映 CPU 的运算状态和当前异常编号由三个子寄存器组成APSR位 [31:27]包含 N负、Z零、C进位/借位、V溢出、Q饱和标志仅 M4/M7 等支持 DSP 的内核有。EPSR位 [24]TThumb 位必须为 1。若清零执行指令会触发 HardFaultCortex-M 只支持 Thumb 指令集。IPSR位 [8:0]Exception Number记录当前正在执行的异常/中断编号0 表示主程序16 以上为外部中断。2. PRIMASK优先级屏蔽寄存器位数1 位含义“全局中断开关”作用置 1 时屏蔽所有可配置优先级的中断只有 NMI 和 HardFault 能抢占。常用场景进入临界区Critical Section时调用__disable_irq()将其置 1。3. FAULTMASK异常屏蔽寄存器位数1 位含义“更高级别的屏蔽”作用比 PRIMASK 更强。置 1 时甚至能屏蔽 HardFault只有 NMI 可以抢占。常用场景极少数极其关键的系统错误处理代码。4. BASEPRI基本优先级屏蔽寄存器位数8 位实际有效位数由芯片厂商决定通常为高 3 或 4 位含义“优先级阈值过滤”作用设定一个阈值。例如设为0x50所有优先级数值大于等于0x50即优先级较低的中断都会被屏蔽而优先级高于0x50的中断仍可触发。常用场景RTOS如 FreeRTOS用于中断嵌套管理既能保护内核任务又不像 PRIMASK 那样一刀切。5. CONTROL控制寄存器决定 CPU 的“身份”和“装备”nPRIV位 [0]0 特权级1 用户级非特权限制访问某些特殊寄存器。SPSEL位 [1]0 使用主栈指针MSP1 使用进程栈指针PSP。FPCA位 [2]仅带 FPU 的内核表示当前是否使用浮点单元。若为 1中断入栈时会额外压入浮点寄存器。这些寄存器没有内存地址只能通过MRS读和MSR写指令访问。内核外设寄存器部分较为枯燥此处仅列出各内核外设的寄存器结构直接从core_cm4.h复制。如需深入了解可借助 AI 工具或查阅手册。其实这个代码在使用cubemx创建的工程中就会生成的也可直接在评论区我。这个手册网上还是比较好找的1. SCB 寄存器typedefstruct{__IMuint32_tCPUID;/*! Offset: 0x000 (R/ ) CPUID Base Register */__IOMuint32_tICSR;/*! Offset: 0x004 (R/W) Interrupt Control and State Register */__IOMuint32_tVTOR;/*! Offset: 0x008 (R/W) Vector Table Offset Register */__IOMuint32_tAIRCR;/*! Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */__IOMuint32_tSCR;/*! Offset: 0x010 (R/W) System Control Register */__IOMuint32_tCCR;/*! Offset: 0x014 (R/W) Configuration Control Register */__IOMuint8_tSHP[12U];/*! Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */__IOMuint32_tSHCSR;/*! Offset: 0x024 (R/W) System Handler Control and State Register */__IOMuint32_tCFSR;/*! Offset: 0x028 (R/W) Configurable Fault Status Register */__IOMuint32_tHFSR;/*! Offset: 0x02C (R/W) HardFault Status Register */__IOMuint32_tDFSR;/*! Offset: 0x030 (R/W) Debug Fault Status Register */__IOMuint32_tMMFAR;/*! Offset: 0x034 (R/W) MemManage Fault Address Register */__IOMuint32_tBFAR;/*! Offset: 0x038 (R/W) BusFault Address Register */__IOMuint32_tAFSR;/*! Offset: 0x03C (R/W) Auxiliary Fault Status Register */__IMuint32_tPFR[2U];/*! Offset: 0x040 (R/ ) Processor Feature Register */__IMuint32_tDFR;/*! Offset: 0x048 (R/ ) Debug Feature Register */__IMuint32_tADR;/*! Offset: 0x04C (R/ ) Auxiliary Feature Register */__IMuint32_tMMFR[4U];/*! Offset: 0x050 (R/ ) Memory Model Feature Register */__IMuint32_tISAR[5U];/*! Offset: 0x060 (R/ ) Instruction Set Attributes Register */uint32_tRESERVED0[5U];__IOMuint32_tCPACR;/*! Offset: 0x088 (R/W) Coprocessor Access Control Register */}SCB_Type;2. NVIC 单元寄存器typedefstruct{__IOMuint32_tISER[8U];/*! Offset: 0x000 (R/W) Interrupt Set Enable Register */uint32_tRESERVED0[24U];__IOMuint32_tICER[8U];/*! Offset: 0x080 (R/W) Interrupt Clear Enable Register */uint32_tRESERVED1[24U];__IOMuint32_tISPR[8U];/*! Offset: 0x100 (R/W) Interrupt Set Pending Register */uint32_tRESERVED2[24U];__IOMuint32_tICPR[8U];/*! Offset: 0x180 (R/W) Interrupt Clear Pending Register */uint32_tRESERVED3[24U];__IOMuint32_tIABR[8U];/*! Offset: 0x200 (R/W) Interrupt Active bit Register */uint32_tRESERVED4[56U];__IOMuint8_tIP[240U];/*! Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */uint32_tRESERVED5[644U];__OMuint32_tSTIR;/*! Offset: 0xE00 ( /W) Software Trigger Interrupt Register */}NVIC_Type;3. SysTick 单元寄存器typedefstruct{__IOMuint32_tCTRL;/*! Offset: 0x000 (R/W) SysTick Control and Status Register */__IOMuint32_tLOAD;/*! Offset: 0x004 (R/W) SysTick Reload Value Register */__IOMuint32_tVAL;/*! Offset: 0x008 (R/W) SysTick Current Value Register */__IMuint32_tCALIB;/*! Offset: 0x00C (R/ ) SysTick Calibration Register */}SysTick_Type;声明本文内容为作者原创笔记。在写作过程中使用了 AI 辅助工具进行语言润色和排版优化但所有技术观点、分析及结论均来自作者本人。