【嵌入式八股17】Cortex
一、ARM 内核发展历史
ARM 内核随着技术发展不断演进,不同内核基于不同架构,在性能、功能等方面各有特点,以下是一些常见 ARM 内核及其对应的架构:
| ARM7 | ARMv6 |
| Cortex-M0 | ARMv6-M |
| Cortex-M0+ | ARMv6-M |
| Cortex-M3 | ARMv7-M |
| Cortex-M4 | ARMv7-M |
| Cortex-M7 | ARMv7-M |
| ARM9 | ARMv6 |
| ARM11 | ARMv6 |
| ARM12 | ARMv6 |
| Cortex-A7 | ARMv7-A |
| Cortex-A8 | ARMv7-A |
| Cortex-A9 | ARMv7-A |
| Cortex-A15 | ARMv7-A |
| Cortex-A17 | ARMv7-A |
| Cortex-A53 | ARMv8 |
| Cortex-A57 | ARMv8 |
| Cortex-A72 | ARMv8 |
二、Cortex-M0 系列芯片系统框图
Cortex-M0 系列芯片系统主要由多个关键部分组成,其系统框图展示了芯片内部的架构和各部分之间的关系,以下是系统的主要组成部分: 
- 中断控制器:负责管理芯片的中断请求,协调中断的处理过程。
- M0 内核:芯片的核心处理单元,执行指令和处理数据。
- AHB 总线:用于连接系统中的高速设备,实现数据的高速传输。
- 存储器和外设:包括芯片的内存以及各种外部设备,如传感器、通信接口等。
- 电源管理:控制芯片的电源供应,实现节能和稳定供电。
- 时钟树:为系统提供时钟信号,确保各部件的同步运行。
- 调试系统:方便开发人员对芯片进行调试和测试,查找和解决问题。
三、Cortex-M 系列寄存器
(一)通用寄存器
Cortex-M 系列包含多个通用寄存器,用于数据的存储和处理,在程序执行过程中发挥着重要作用,以下是通用寄存器列表:
(二)M0 特殊寄存器
除通用寄存器外,Cortex-M0 还有一些特殊寄存器,用于特定的功能和系统控制,以下是 M0 的特殊寄存器:
(三)M3/M4/M7 特殊寄存器
Cortex-M3、M4、M7 在 M0 特殊寄存器的基础上,还增加了一些特殊寄存器,以满足更复杂的功能需求,以下是它们的特殊寄存器:
1. MSP 和 PSP
- MSP(主堆栈指针):在中断处理中使用,系统复位后默认使用 MSP,在中断处理过程中也使用 MSP。
- PSP(进程堆栈指针):用于线程栈,通过配置 CONTROL 寄存器的相关位来切换使用 MSP 或 PSP。当 CONTROL 寄存器的第 1 位写 1 时,表示切换成 PSP。
2. xPSR
xPSR(程序状态寄存器)中的 IPSR(中断号寄存器)可以用来判断当前处于什么中断,帮助程序进行中断处理和状态判断。
3. PRIMASK
PRIMASK 是中断屏蔽寄存器,向其写 1 可以屏蔽所有中断(除了不可屏蔽中断和 hardfault 硬件错误中断),从而在需要时保护关键代码段不被中断干扰。
4. CONTROL
CONTROL 寄存器具有多种功能,其中第 1 位写 1 表示切换成 PSP;第 0 位用于控制线程模式的特权级别,0 表示特权级的线程模式,1 表示用户级的线程模式,而 Handler 模式永远都是特权级的。
5. FAULTMASK
FAULTMASK 寄存器用于屏蔽所有的 fault(NMI 不可屏蔽中断不受影响),当需要临时屏蔽错误异常时,可以使用该寄存器。
6. BASEPRI
BASEPRI 寄存器可以屏蔽所有优先级不高于某个具体数值的中断,通过设置该寄存器的值,可以灵活控制中断的响应。
四、栈空间操作
在 Cortex-M 系列中,栈的操作具有特定的规则:
- 栈的增长方向:栈向下递减,即栈顶地址随着数据的入栈而减小。
- 栈指针的指向:栈指针(SP)始终指向栈的最后一个数据,每次执行数据存储操作(push)前,SP 会首先减小,为新数据腾出空间。
五、异常和中断
(一)Cortex-M0 的异常和中断
Cortex-M0 最多支持 32 个外部中断,同时还包括一些系统异常,主要用于操作系统和错误处理,以下是一些主要的系统异常:
| reset | 1 | 上电复位、系统复位,是系统启动时的初始状态。 |
| NMI(不可屏蔽中断) | 2 | 由外部 NMI 输入脚触发,不可被屏蔽,用于处理关键的紧急事件。 |
| hardfault(硬件错误) | 3 | 当系统出现硬件故障时触发,如存储器访问错误等。 |
| SVCall(系统调用) | 11 | 用于执行系统服务调用指令,实现用户程序与操作系统之间的交互。 |
| PendSV(挂起系统调用) | 13 | 为系统设备而设的“可悬挂请求”,常用于任务切换等场景。 |
| systick(系统滴答) | 15 | 系统滴答定时器,提供周期性的时钟信号,用于系统的定时操作。 |
(二)NVIC(可嵌套向量中断控制器)
NVIC 是 Cortex-M 系列芯片中用于管理中断的重要部件,具有以下特点:
- 中断可嵌套:当一个中断正在处理时,如果有更高优先级的中断到来,可以中断当前的中断处理,先处理更高优先级的中断。
- 相同优先级的中断不可嵌套:对于相同优先级的中断,不会相互嵌套,必须等待当前中断处理完毕后,才能处理相同优先级的其他中断。
- 相同中断不可嵌套:同一个中断在处理过程中不会再次被嵌套处理,避免了递归调用的问题。
六、系统操作寄存器
Cortex-M 系列芯片包含许多系统管理的寄存器,它们分布在不同的地址范围,用于实现各种系统功能,以下是主要的系统操作寄存器及其地址范围和说明:
| 0xE000E008 - 0xE000E00F | System Control Block Table(系统控制块表) |
| 0xE000E010 - 0xE000E01F | 预留 |
| 0xE000E010 - 0xE000E01F | SysTick 操作寄存器(SysTick 定时器的控制和配置) |
| 0xE000E100 - 0xE000E4EF | NVIC 操作寄存器(中断控制器的相关配置和操作) |
| 0xE000ED00 - 0xE000ED3F | 系统控制块(包含一些系统控制和状态信息) |
| 0xE000EF00 - 0xE000EF03 | NVIC(中断控制器的部分寄存器) |
(一)NVIC 寄存器
NVIC 包含多个寄存器,用于控制中断的使能、失能、挂起等操作,以下是主要的 NVIC 寄存器及其地址和说明:
| 0xE000E100 | ISER(中断使能寄存器) | 用于使能相应的中断。 |
| 0xE000E180 | ICER(中断失能寄存器) | 用于失能相应的中断。 |
| 0xE000E200 | ISPR(中断挂起寄存器) | 用于设置相应中断的挂起状态。 |
| 0xE000E280 | ICPR(清除挂起中断的寄存器) | 用于清除相应中断的挂起状态。 |
| 0xE000E400 - 0xE000E41C | IPR0-7(中断优先级配置寄存器) | 用于配置中断的优先级。 |
(二)系统控制块 SCB 寄存器
系统控制块 SCB 包含多个寄存器,用于系统的控制和状态管理,以下是主要的 SCB 寄存器及其地址和说明:
| 0xE000ED00 | CPUID(CPU 标识寄存器) | 包含 CPU 的标识信息。 |
| 0xE000ED04 | ICSR(中断控制和状态寄存器) | 用于中断的控制和状态查询。 |
| 0xE000ED0C | AIRCR(应用中断和复位的寄存器) | 用于处理应用中断和复位操作。 |
| 0xE000ED10 | SCR(系统控制寄存器) | 用于系统的控制和配置。 |
| 0xE000ED14 | CCR(配置控制寄存器) | 用于配置系统的一些特性。 |
| 0xE000ED1C | SHPR2(System Handler Priority Register 2,系统处理优先级寄存器 2) | 用于设置系统处理的优先级。 |
| 0xE000ED20 | SHPR3(System Handler Priority Register 3,系统处理优先级寄存器 3) | 用于设置系统处理的优先级。 |
(三)SysTick 寄存器
SysTick 是系统滴答定时器,其相关寄存器用于控制和读取定时器的状态,以下是 SysTick 寄存器及其地址和说明:
| 0xE000E010 | SYST_CSR(SysTick 控制和状态寄存器) | 用于控制 SysTick 定时器的启动、停止、中断等功能,并查询其状态。 |
| 0xE000E014 | SYST_RVR(SysTick 重载寄存器) | 设置 SysTick 定时器的重载值,即定时周期。 |
| 0xE000E018 | SYST_CVR(SysTick 当前值寄存器) | 用于读取 SysTick 定时器的当前计数值。 |
| 0xE000E01C | SYST_CALIB(SysTick 校准寄存器) | 用于校准 SysTick 定时器。 |
七、Cortex-M0 启动流程
Cortex-M0 芯片的启动过程遵循特定的顺序,以下是其启动流程:
- 程序从 0x00000000 地址开始执行,这是系统启动的初始位置。
- M0 从程序 bin 文件的开始处第 2 个 word 运行 reset_handler 函数,该函数是启动过程中的关键函数。
- reset_handler 函数开始执行一些必要的初始化操作,包括 ramfunc 函数复制(将某些函数复制到 RAM 中以提高执行速度)、堆初始化(为动态内存分配做准备)、全局和静态变量初始化等,确保系统的基本运行环境准备就绪。
- 完成初始化后,跳转到 main 函数中,开始执行用户程序的主要逻辑。
八、中断向量表
中断向量表是存储中断服务程序地址的表格,在 Cortex-M0 中,中断向量表包含以下主要内容:
| sp 指针(堆栈指针的初始值) |
| resetHandler 地址(复位中断服务程序的地址) |
| NMIHandler 地址(不可屏蔽中断服务程序的地址) |
| hardfault 地址(硬件错误中断服务程序的地址) |
| reserved(预留位置) |
| systickHandler 地址(系统滴答中断服务程序的地址) |
| ......(其他中断服务程序的地址) |
九、大小端模式
Cortex-M0 支持大端模式和小端模式,大端模式是指数据的高位字节存储在低地址,小端模式则是数据的高位字节存储在高地址。不过一般芯片公司在设计时会选择小端模式,因为小端模式在一些情况下更符合程序的执行习惯和数据处理方式。
十、堆栈
在 Cortex-M 系列中,堆栈的增长方向具有特定的规律:
- 堆的增长方向:堆向上增长,即随着动态内存分配,堆的地址逐渐增大。
- 栈的增长方向:栈向下增长,如前面所述,栈顶地址随着数据的入栈而减小。
(一)压栈的寄存器
当发生中断或函数调用等情况时,需要将一些寄存器的值压入栈中保存,以便在恢复时能够还原现场,以下是常见的压栈寄存器:
| xPSR(程序状态寄存器) |
| PC(程序计数器) |
| LR(链接寄存器) |
| R12 |
| R3 |
| R2 |
| R1 |
| R0 |
十一、杂项指令集
Cortex-M 系列包含一些特殊的指令,用于实现特定的功能,以下是一些杂项指令及其说明:
| BKPT(断点) | 用于设置断点,方便调试时暂停程序执行。 |
| CPSID(关闭总中断) | 将 PRIMASK 寄存器置 1,关闭所有可屏蔽中断(除不可屏蔽中断和 hardfault)。 |
| CPSIE(打开总中断) | 将 PRIMASK 寄存器置 0,打开所有可屏蔽中断。 |
| DMB(数据存储器隔离) | 仅当所有在它前面的存储器访问操作都执行完毕后,才开始后面的存储器访问操作,用于保证存储器访问的顺序性。 |
| DSB(数据同步隔离) | 比 DMB 更严格,仅当所有在它前面的存储器访问操作都执行完毕后,才开始后面的指令执行,确保数据的一致性。 |
| ISB(指令同步隔离) | 最严格,会清洗流水线,保证所有它前面的指令都执行完毕之后,才执行后面的指令,用于指令执行的同步。 |
| MRS(从特殊寄存器读取数据到通用寄存器) | 用于从特殊寄存器中读取数据到通用寄存器,方便数据的处理和使用。 |
| MSR(从通用寄存器读取数据到特殊寄存器) | 与 MRS 相反,将通用寄存器中的数据写入特殊寄存器。 |
| NOP(空转指令) | 空操作指令,不执行任何实际操作,用于时间延迟或占位。 |
| SEV(产生 event) | 产生一个 event,用于唤醒等待 event 的线程。 |
| SVC(产生 SVC 系统调用中断) | 产生 SVC 系统调用中断,用于用户程序调用系统服务。 |
| WFE(等待 event) | 使当前线程进入等待状态,直到接收到一个 event。 |
| WFI(等待中断) | 使当前线程进入等待状态,直到接收到一个中断。 |
十二、M0/M3/M4/M7 区别
M0 基于 ARMv6-M 架构,M3、M4、M7 基于 ARMv7-M 架构,它们在架构、功能特性等方面存在诸多差异,以下为详细对比:
- 架构基础差异:
- M0 采用 ARMv6-M 架构,是 Cortex-M 系列中较为基础、简单的一款内核,主要适用于对成本、功耗和性能要求相对较低的应用场景,如简单的传感器节点、小型控制设备等。其指令集和功能相对有限,适合处理一些基本的控制任务。
- M3、M4、M7 基于 ARMv7-M 架构,在架构层面上具有更高的性能和更多的功能扩展能力。ARMv7-M 架构引入了一些新的特性和指令集,为更复杂的应用提供了支持。
- 功能特性对比:
- M3:
- 中断与异常管理增强:具备 basepri 寄存器,能够阻止某优先级或更低优先级的中断,使开发者可以更灵活地控制中断的响应,避免低优先级中断干扰关键任务的执行。faultmask 寄存器的引入提供了更多的错误管理特性,可用于屏蔽除不可屏蔽中断(NMI)之外的其他错误异常,便于在特定情况下对错误进行集中处理。
- 特权模式与线程模式控制:CONTROL 寄存器的 bit0 用于决定线程模式是特权模式还是用户模式,增加了系统的安全性和灵活性。特权模式下,线程可以访问系统的所有资源,适用于操作系统内核等关键代码的执行;用户模式下,线程的资源访问受到限制,可有效保护系统关键部分不被用户程序意外修改。
- 指令集与处理能力提升:支持 32 位 thumb 指令,相较于 M0 的指令集,32 位 thumb 指令在执行效率和代码密度上有更好的表现,能够更高效地处理复杂的计算任务。同时,具备位段特性和位域处理功能,方便对数据的位操作,适用于一些对数据处理精度要求较高的应用场景。
- 多处理器支持与中断数量扩展:支持多处理器,可满足更复杂的系统设计需求,如在一些需要并行处理任务的系统中,多处理器支持可以提高系统的整体性能。最多支持 240 个外部中断,相比 M0 的中断数量有了大幅提升,能够处理更多的外部事件,适用于对实时性要求较高的应用。
- 硬件功能与调试特性:拥有硬件除法功能,提高了数据处理能力,特别是在涉及除法运算的场景中,硬件除法可以显著提高运算速度。配备存储器保护单元(MPU),可对内存访问进行管理和保护,防止非法访问和数据破坏,增强了系统的安全性和稳定性。此外,还具备更多的调试和跟踪特性,方便开发人员进行程序的调试和优化。
- M4:
- 浮点运算与 SIMD 指令:在 ARMv7-M 架构基础上,增加了浮点特性,支持基本的浮点运算,能够处理带有小数的数值计算,适用于对精度要求较高的应用,如数字信号处理、科学计算等领域。同时,支持 SIMD(单指令多数据)指令,即单周期多指令,可在一个指令周期内处理多个数据,提高了数据处理的并行性和效率,尤其在处理大量数据的场景中表现出色。
- 饱和算法与单周期 MAC:具备饱和算法,在数据处理过程中,当数据超出表示范围时,饱和算法可以将数据限制在最大或最小值,避免数据溢出导致的错误,提高了系统的可靠性。单周期 MAC(乘法累加)功能使得乘法和累加操作可以在一个周期内完成,进一步提升了数据处理的速度,对于一些需要频繁进行乘法累加运算的算法,如数字滤波器等,具有重要意义。
- M7:
- 高性能与高主频:M7 内核具有更高的性能,其主频通常比 M3 和 M4 更高,能够在单位时间内处理更多的指令,适用于对运算速度要求极高的应用场景,如工业控制中的复杂算法运算、高端消费电子设备的多媒体处理等。
- 缓存机制优化:配备了更大容量的指令缓存(I-Cache)和数据缓存(D-Cache)。更大的缓存可以减少处理器访问外部存储器的次数,提高数据和指令的读取速度,从而显著提升系统的整体性能。例如,在处理大量数据的算法时,M7 能够更快地从缓存中获取数据,减少等待时间。
- 浮点运算与 DSP 指令集增强:M7 的浮点运算单元(FPU)性能更加强大,支持更多的浮点运算指令和更高精度的运算,能够更高效地处理复杂的浮点运算任务,如在 3D 图形渲染、科学计算等领域表现更为出色。同时,对数字信号处理(DSP)指令集进行了进一步扩展,提供了更丰富的 DSP 功能,在音频处理、视频编码解码、通信信号处理等领域具有更强的优势,能够更快速地完成数字信号的处理任务。
- 总线带宽提升:M7 的总线带宽比 M3 和 M4 更宽,能够支持更高的数据传输速率。这意味着在处理大量数据的应用中,M7 可以更快地将数据在处理器、存储器和其他外设之间传输,避免数据传输成为系统性能的瓶颈。
- M3:
以下是 M0、M3、M4、M7 更完整的特性对比表格:
| 架构 | ARMv6-M | ARMv7-M | ARMv7-M | ARMv7-M |
| basepri 寄存器 | 无 | 有,可阻止某优先级或更低优先级的中断 | 有 | 有 |
| faultmask 寄存器 | 无 | 有,提供更多错误管理特性 | 有 | 有 |
| CONTROL 寄存器 bit0 | 无此功能 | 用于决定是特权模式还是用户线程模式 | 有 | 有 |
| 指令集 | 16 位 Thumb 指令 | 32 位 Thumb 指令 | 32 位 Thumb 指令 | 32 位 Thumb 指令 |
| 位段特性 | 无 | 有 | 有 | 有 |
| 位域处理 | 无 | 有 | 有 | 有 |
| 多处理器支持 | 无 | 有 | 有 | 有 |
| 中断数量 | 最多 32 个外部中断 | 最多 240 个外部中断 | 最多 240 个外部中断 | 最多 240 个外部中断 |
| 硬件除法 | 无 | 有 | 有 | 有 |
| 存储器保护单元(MPU) | 无 | 有(可选) | 有(可选) | 有(可选) |
| 调试和跟踪特性 | 较少 | 更多 | 较多 | 丰富 |
| 浮点特性 | 无 | 无 | 有,支持基本浮点运算 | 强大,支持更多浮点运算指令和更高精度运算 |
| SIMD 指令 | 无 | 无 | 有(单周期多指令) | 有,且功能更强大 |
| 饱和算法 | 无 | 无 | 有 | 有 |
| 单周期 MAC(乘法累加) | 无 | 无 | 有 | 有 |
| 性能(主频) | 较低 | 中等 | 较高 | 高 |
| 缓存容量 | 较小或无 | 有一定缓存 | 较大缓存 | 更大容量的 I-Cache 和 D-Cache |
| DSP 指令集 | 无 | 基本 | 有扩展 | 进一步扩展 |
| 总线带宽 | 较窄 | 中等 | 较宽 | 更宽 |
十三、M3 系统框图
Cortex-M3 的系统框图展示了其内部各组件的连接和协同工作方式,通过该框图可以清晰地了解 M3 内核如何与其他部分配合实现系统功能。(此处可结合具体的系统框图图片进行更详细的讲解,如各总线的连接关系、不同模块的功能及交互等)
十四、M3 快速开关中断汇编指令
在 Cortex-M3 中,通过特定的汇编指令可以快速实现中断和异常的开关控制,这些指令直接操作相关的寄存器,以满足系统对中断管理的需求:
| CPSID I | PRIMASK = 1 | 关闭所有可屏蔽中断(除不可屏蔽中断 NMI 和硬错误中断 hardfault),设置 PRIMASK 寄存器为 1 来屏蔽中断,常用于保护关键代码段不被中断干扰。 |
| CPSIE I | PRIMASK = 0 | 打开所有可屏蔽中断,将 PRIMASK 寄存器设置为 0,恢复中断的响应。 |
| CPSID F | FAULTMASK = 1 | 关闭除 NMI 之外的所有异常,通过设置 FAULTMASK 寄存器为 1 来屏蔽各类异常,仅允许 NMI 中断发生。 |
| CPSIE F | FAULTMASK = 0 | 打开所有异常,将 FAULTMASK 寄存器设置为 0,恢复异常的响应。 |
十五、M3 内核 CONTROL 寄存器
M3 内核的 CONTROL 寄存器在系统中起着关键的控制作用,主要用于堆栈指针的选择和线程模式的特权级别控制:
- CONTROL[1]:用于堆栈指针的选择。
- 当 CONTROL[1] = 0 时,选择主堆栈指针 MSP(复位后缺省值)。主堆栈指针 MSP 主要用于异常处理(Handler 模式),在系统复位后默认使用 MSP,并且在异常处理过程中只能使用 MSP,以确保系统的稳定性和安全性。
- 当 CONTROL[1] = 1 时,选择进程堆栈指针 PSP。在线程模式(没有在响应异常)下,可以使用 PSP,它为线程的局部变量和函数调用提供独立的堆栈空间,提高了系统的灵活性和多任务处理能力。但需要注意的是,在 Handler 模式下,不得往该位写 1,即不能使用 PSP。
- CONTROL[0]:用于控制线程模式的特权级别。
- 当 CONTROL[0] = 0 时,为特权级的线程模式。在特权级线程模式下,线程可以访问系统的所有资源,包括一些受保护的寄存器和内存区域,适用于操作系统内核等需要高权限操作的代码。
- 当 CONTROL[0] = 1 时,为用户级的线程模式。用户级线程模式对资源的访问受到限制,不能访问某些敏感资源,从而增强了系统的安全性,防止用户程序对系统关键部分的意外修改或破坏。而 Handler 模式永远都是特权级的,不受 CONTROL[0] 位的影响。
十六、异常和中断
Cortex-M3 支持丰富的异常和中断类型,这使得它能够灵活地处理各种系统事件和外部请求:
Cortex‐M3 支持大量异常,包括 16 - 4 - 1 = 11 个系统异常,和最多 240 个外部中断——简称 IRQ。
| 0 | N/A | N/A | 表示当前没有异常在运行,系统处于正常执行状态。 |
| 1 | 复位 | -3(最高) | 系统上电或手动复位时触发,是系统启动的起点。在复位后,系统会进行一系列的初始化操作,如寄存器的初始化、内存的初始化等,然后开始执行用户程序。 |
| 2 | NMI(不可屏蔽中断) | -2 | 由外部 NMI 输入脚触发,具有很高的优先级,不可被屏蔽。常用于处理关键的紧急事件,如电源故障、硬件安全事件等,确保系统能够及时响应这些重要的外部信号。 |
| 3 | 硬(hard) fault | -1 | 当系统出现严重的硬件错误或故障时触发,如存储器访问错误、总线错误等。所有被除能的 fault(当前被禁用或 FAULTMASK 被置位),都将“上访”成硬 fault。硬 fault 的处理需要特别谨慎,因为它可能涉及到系统的严重问题,需要及时排查和修复。 |
| 4 | MemManage(存储器管理 fault) | 可编程 | 当 MPU(存储器保护单元)检测到访问犯规(如非法访问、越界访问等)以及访问非法位置时,会引发此 fault。此外,企图在“非执行区”取指也会触发该异常。该异常的优先级可编程设置,以便根据具体需求进行灵活处理。 |
| 5 | 存储器管理 fault(总线 fault) | 可编程 | 从总线系统收到错误响应时触发,原因可以是预取流产(Abort)或数据流产,或者企图访问协处理器失败等。总线 fault 同样可以通过编程设置优先级,以确保系统能够及时处理总线相关的错误。 |
| 6 | 用法(usage) Fault | 可编程 | 当发生一些不符合指令用法的操作时触发,如未定义的指令、无效的操作数等。该异常可以帮助开发人员检测和纠正程序中的错误,提高代码的质量和稳定性。 |
| 7 - 10 | 保留 | N/A | 这些编号保留给未来的系统扩展或特定用途,当前未使用。 |
| 11 | SVCall(系统调用) | 可编程 | 当执行系统服务调用指令(SVC)时引发的异常,用于实现用户程序与操作系统之间的交互。通过 SVC 指令,用户程序可以请求操作系统提供的服务,如内存分配、文件操作等,从而实现系统资源的管理和共享。 |
| 12 | 调试监视器 | 可编程 | 当触发调试相关的事件时,如设置断点、数据观察点或者接收到外部调试请求时,会引发调试监视器异常。开发人员可以利用该异常进行程序的调试和跟踪,查找和解决代码中的问题。 |
| 13 | 保留 | N/A | 保留给未来的系统扩展或特定用途。 |
| 14 | PendSV(挂起系统调用) | 可编程 | 为系统设备而设的“可悬挂请求”,常用于实现任务切换等场景。在多任务系统中,当一个任务需要切换到另一个任务时,可以通过 PendSV 异常来实现平滑的任务切换,确保系统的高效运行。 |
| 15 | SysTick(系统滴答定时器) | 可编程 | 系统滴答定时器是一个周期性溢出的时基定时器,通过配置相关寄存器可以设置其定时周期。当定时器溢出时,会引发 SysTick 异常,常用于实现系统的定时任务、延时操作等。 |
| 16 | IRQ(外部中断) | #0(可编程) | 外部中断是由外部设备(如传感器、按键等)触发的中断请求,最多支持 240 个外部中断。每个外部中断的优先级可以通过编程进行设置,以满足不同外部设备的实时性要求。 |
| 17 | IRQ(外部中断) | #1(可编程) | 同上述外部中断,可根据需求设置优先级。 |
| ... | ... | ... | ... |
| 255 | IRQ(外部中断) | #239(可编程) | 外部中断的编号范围从 16 到 255,共 240 个外部中断,可灵活配置优先级。 |
十七、MPU 存储器保护单元
Cortex-M3 的 MPU(存储器保护单元)是一个可选的重要组件,它为系统的存储器访问提供了额外的保护和管理功能:
- 访问限制:MPU 可以对特权级访问和用户级访问分别施加不同的访问限制。在特权级访问中,通常允许对所有内存区域进行读写操作,但可以通过 MPU 进行更精细的控制;而在用户级访问中,MPU 可以限制用户程序对某些敏感内存区域的访问,如操作系统内核的代码和数据区域,从而提高系统的安全性。
- 犯规检测与处理:当检测到存储器访问犯规(如非法读、非法写、越界访问等)时,MPU 会产生一个 fault 异常。这个异常可以由相应的 fault 异常服务例程来捕获和分析,开发人员可以在服务例程中进行错误处理,如记录错误日志、尝试恢复错误或采取其他纠正措施,以确保系统的稳定性和可靠性。
- 内存区域管理:MPU 在保护内存时是按区管理的(region)。它可以将内存划分为多个区域,并为每个区域设置不同的访问权限,如只读、读写、可执行等。例如,可以将某些内存 region 设置成只读,以防止该区域的内容被意外更改;在多任务系统中,还可以利用 MPU 把不同任务之间的数据区隔离,避免任务之间的数据冲突和干扰。
- 应用场景:在实际应用中,MPU 被广泛应用于操作系统、工业控制、航空航天等领域。在操作系统中,MPU 可以保护内核数据不被用户程序破坏,确保系统的稳定运行;在工业控制中,MPU 可以防止外部干扰或错误操作导致的内存访问错误,提高系统的安全性和可靠性;在航空航天领域,由于对系统的安全性和稳定性要求极高,MPU 更是必不可少的组件,许多行业标准都规定了必须使用 MPU 来行使保护职能。
一些八股模拟拷打Point,万一有点用呢

