ARM寄存器简介
支持不同类型编译器的宏定义
__CC_ARM
- 对应编译器:ARM Compiler (也叫 ARM C Compiler),是 ARM 公司开发的编译器,通常用于嵌入式开发。
- 用途:这个宏在使用 ARM 编译器(如
armcc
或armclang
)时会被自动定义。 - 典型用途:用于在代码中加入特定于 ARM 编译器的指令或者优化。
__ICC_ARM
- 对应编译器:IAR Embedded Workbench for ARM(IAR ARM 编译器),这是一个广泛用于嵌入式系统的编译工具链。
- 用途:这个宏在使用 IAR 编译器时会被自动定义。
- 典型用途:用于区分代码在 IAR 编译器下的特定实现或特性。
__GNUC__
- 对应编译器:GNU 编译器套件(GCC),这是一个开源的编译器,广泛用于各种平台和操作系统,支持多种架构(包括 ARM)。
- 用途:这个宏在使用 GCC 或其变种(如
arm-none-eabi-gcc
)时会被自动定义。 - 典型用途:用于针对 GCC 编译器进行条件编译,可以在 GCC 下启用特定的功能或优化。
总结:
__CC_ARM
:用于 ARM 编译器(如 armcc 或 armclang)。__ICC_ARM
:用于 IAR 编译器(IAR Embedded Workbench for ARM)。__GNUC__
:用于 GNU 编译器(如 GCC,支持多种平台)。
屏蔽中断函数
屏蔽全局中断
PRIMASK 寄存器 是 ARM 处理器的一个特殊寄存器,用于控制中断的全局使能/屏蔽。它的作用是控制是否允许中断发生。具体来说,
设置 PRIMASK 为 1 时,会禁用所有的不可屏蔽中断(Non-Maskable Interrupts,NMI 和 Hard Fault 之外的中断);
而设置为 0 时,则允许中断的发生。
这个函数的作用是通过给定的 priMask 值,设置 ARM 处理器的 PRIMASK 寄存器,从而控制中断的使能或屏蔽。
\param [in] priMask Priority Mask
*/
__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
{
register uint32_t __regPriMask __ASM("primask");
__regPriMask = (priMask);
}
屏蔽临界中断
如何屏蔽某个优先级一下的中断
你提供的代码是一个 ARM Cortex-M 体系结构的内联函数实现,用于设置
BASEPRI
寄存器的值。BASEPRI
寄存器是一个控制寄存器,用于设置中断优先级的屏蔽阈值,影响哪些中断可以被触发。它是 ARM Cortex-M 处理器中重要的控制寄存器之一,通常在嵌入式系统的操作系统(RTOS)中用于实现中断优先级的控制。代码分析
__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) { register uint32_t __regBasePri __ASM("basepri"); __regBasePri = (basePri & 0xff); }
1.
__STATIC_INLINE
:
__STATIC_INLINE
是一个修饰符,表示这个函数是静态内联函数。内联函数(inline
)告诉编译器尽可能将函数调用内联化,从而提高效率。STATIC
表示该函数在当前文件范围内有效,不能在其他文件中访问。这种写法通常用于库函数或者操作硬件寄存器的辅助函数,以便减少函数调用的开销。
2.
uint32_t __regBasePri __ASM("basepri")
:
register
表示该变量应当存储在寄存器中,而非内存。通过将变量声明为register
,编译器会尽量将其存储在 CPU 寄存器中,这样可以提高访问速度。
__ASM("basepri")
是 GCC 风格的内嵌汇编语法,用来告诉编译器将该变量与 ARM 的BASEPRI
寄存器关联。也就是说,这行代码将__regBasePri
变量映射到BASEPRI
寄存器,以便在后续操作中可以直接对BASEPRI
寄存器进行赋值。3.
__regBasePri = (basePri & 0xff)
:
basePri & 0xff
用于确保传入的basePri
参数的值不会超过 8 位(即只保留低 8 位)。BASEPRI
寄存器是 8 位的(在 ARM Cortex-M 处理器中,BASEPRI
的位宽为 8),因此只会使用basePri
参数的低 8 位来设置BASEPRI
寄存器。4. 功能实现:
该函数将输入的
basePri
值(经过 8 位掩码处理)写入到BASEPRI
寄存器中。
BASEPRI
寄存器控制中断的屏蔽级别。其值是一个优先级屏蔽值,决定了当前处理器是否允许响应某些中断。如果当前中断优先级高于BASEPRI
寄存器的值,则该中断会被屏蔽。
BASEPRI
寄存器简介在 ARM Cortex-M 处理器中,
BASEPRI
是一个用于中断优先级屏蔽的寄存器,它使得在特定优先级下,只有优先级高于或等于BASEPRI
的中断才会被响应。其工作原理如下:
值的含义:
BASEPRI
寄存器的值是 8 位的(对于 Cortex-M),通常表示中断的屏蔽优先级。当
BASEPRI
寄存器的值设置为某个优先级时,所有优先级低于该值的中断将被屏蔽(不被处理),而优先级高于或等于该值的中断将被允许。例如,如果
BASEPRI
设置为0x10
(16的十六进制表示),那么只有优先级高于0x10
的中断可以被触发。设置
BASEPRI
的用途:
BASEPRI
寄存器用于调度器或者中断管理中,以允许操作系统或任务管理器屏蔽低优先级的中断,在处理关键任务或代码段时,避免中断打断当前执行。它常常用于嵌入式系统中,在实时操作系统(RTOS)中控制中断优先级。
示例:如何使用
__set_BASEPRI
假设你在开发一个实时操作系统,可能会在某些时刻禁用优先级较低的中断,确保高优先级任务的稳定执行。你可以使用这个函数来设置
BASEPRI
寄存器。void enter_critical_section(void) { __set_BASEPRI(0x80); // 设置 BASEPRI 为 0x80,屏蔽所有优先级低于 0x80 的中断 } void exit_critical_section(void) { __set_BASEPRI(0x00); // 退出临界区,恢复为默认的中断优先级屏蔽 }
总结
该函数用于设置
BASEPRI
寄存器的值,以控制中断的优先级屏蔽。通过使用
basePri & 0xff
,确保只使用basePri
的低 8 位来控制BASEPRI
。
BASEPRI
的值影响中断的响应行为,允许控制哪些中断可以被触发,哪些需要被屏蔽,通常用于实时操作系统中的临界区管理。
PSP,MSP
在 ARM 架构中,
PSP
(Process Stack Pointer)寄存器是一个用于管理进程或线程栈的指针寄存器。它是 ARMv7-M 和 ARMv8-M 等架构中的一部分,特别用于 Cortex-M 系列处理器。PSP
与MSP
(Main Stack Pointer)共同工作,它们用于不同的栈模式。1. PSP 的定义与作用
PSP
是进程栈指针,用于在特定的模式下(通常是线程模式)指向栈顶的位置。它是 Cortex-M 处理器中的一个特殊寄存器,主要用于嵌入式操作系统的任务切换和栈管理。具体来说,PSP
用于管理每个任务(线程)或进程的栈,当任务上下文切换时,操作系统会切换PSP
。
- MSP(Main Stack Pointer):通常用于异常处理和中断上下文,指向主栈(用于处理异常、中断等)。
- PSP(Process Stack Pointer):通常用于线程模式,指向进程栈(应用程序代码或任务的栈)。
2. PSP 与 MSP 的切换
默认模式下:
- 当 MCU 处于 异常模式(比如进入中断或系统调用)时,
MSP
(主栈指针)被使用。- 当 MCU 处于 线程模式(应用程序代码执行时),如果程序显式地切换到了
PSP
,那么就会使用PSP
。任务切换: 在操作系统中,多个任务需要切换上下文。当任务切换时,操作系统保存当前任务的栈内容到当前的栈指针(通常是
PSP
),并恢复下一个任务的栈指针(也是通过PSP
)。这保证了每个任务有独立的栈空间。3. 如何切换到 PSP
ARM Cortex-M 处理器通过特定的指令和控制寄存器来切换栈指针:
切换到
PSP
:
- 当 CPU 进入线程模式时,可以通过设置
CONTROL
寄存器的位来选择使用PSP
。- 例如,
CONTROL
寄存器的SPSEL
位为1
时,栈指针会使用PSP
,而不是默认的MSP
。MRS R0, CONTROL ; 读取 CONTROL 寄存器 ORR R0, R0, #1 ; 设置 SPSEL 位为 1 MSR CONTROL, R0 ; 更新 CONTROL 寄存器
从
PSP
切换回MSP
:
- 通过将
CONTROL
寄存器的SPSEL
位清零,CPU 就会使用MSP
。4. PSP 在任务栈中的应用
在使用 RTOS(如 FreeRTOS)时,操作系统需要为每个任务分配独立的栈空间。当任务启动时,
PSP
会被设置为该任务的栈底(或栈顶的指针)。在任务切换时,操作系统保存当前任务的PSP
并加载新任务的PSP
。5. PSP 寄存器的结构
PSP 寄存器是一个 32 位寄存器,指向当前任务栈的顶部(栈增长方向是从高地址到低地址)。因此,PSP 会随着栈的推入(函数调用、局部变量分配等)向低地址递减。
- 栈帧:当函数被调用时,栈帧会被压入栈中,其中包含函数返回地址、保存的寄存器等信息,PSP 会在此过程中自动更新。
6. 总结
- PSP:进程栈指针,用于指向线程模式下的栈空间。
- MSP:主栈指针,用于指向异常模式下的栈空间。
- 通过设置
CONTROL
寄存器的SPSEL
位,可以在PSP
和MSP
之间切换。PSP
在多任务环境下为每个任务提供独立的栈空间,保证任务切换时栈的隔离。
PSP
寄存器的管理是 ARM Cortex-M 系列处理器在多任务操作系统中的一个重要功能,确保每个任务具有自己的栈空间,避免栈溢出和数据冲突。
中断优先级管理寄存器
ISPR 是 Interrupt Software Priority Register 的缩写,通常在基于 ARM Cortex-M 处理器的微控制器中使用。它是一个用于中断优先级管理的寄存器,允许软件设置中断的优先级。ISPR 寄存器可以帮助实现中断的优先级控制和处理中断的顺序。
算术操作的结果、条件判断等标志寄存器
APSR 是 Application Program Status Register 的缩写,是 ARM 架构中一个重要的状态寄存器,负责存储处理器的当前状态信息,特别是在程序执行期间的标志位。它包含了许多影响程序执行和控制流程的标志位,例如算术操作的结果、条件判断等。
APSR 寄存器的主要组成部分:
在 ARM 处理器中,APSR 通常包括以下几个标志位:
N (Negative flag)
N 位表示最后一次算术或逻辑操作的结果是否为负数。如果操作结果为负,N 位被设置为 1,否则为 0。
Z (Zero flag)
Z 位表示最后一次算术或逻辑操作的结果是否为零。如果结果为零,Z 位被设置为 1,否则为 0。
C (Carry flag)
C 位表示最后一次算术操作是否产生进位(对于加法)或借位(对于减法)。对于无符号整数运算,C 位指示是否有进位或借位。
V (Overflow flag)
V 位表示最后一次算术操作是否发生溢出。如果在有符号整数运算中,结果溢出了表示的范围,V 位会被设置为 1,否则为 0。
Q (Saturation flag)
Q 位在某些特定操作中(如饱和算术运算)被设置,表示该操作结果是否发生饱和。饱和运算是指当计算结果超出了数据类型的最大值或最小值时,结果会被固定为最大或最小值。
APSR 在 ARM 架构中的作用
APSR 主要用于反映处理器的状态,以便程序根据不同的标志位进行条件跳转或执行不同的操作。这些标志位在算术运算、比较、逻辑操作等执行时被更新,且通常与 条件执行 和 分支指令(如 BEQ、BNE、BGT 等)配合使用,以实现条件判断和流程控制。
1. 标志位的更新
每当进行算术操作(如加法、减法、乘法等)时,处理器会自动更新 APSR 寄存器中的标志位。
比如,ADD 指令会更新 APSR,根据加法结果设置 N、Z、C 和 V 标志位。
在进行 CMP(比较)指令时,处理器会更新 APSR 以反映两个数的比较结果,通常是通过设置 Z 标志来指示两个数是否相等。
2. 条件执行
ARM 处理器支持条件执行机制,条件执行依赖 APSR 中的标志位。例如,如果 Z 位为 1(表示操作结果为零),可以通过条件指令(如 BEQ)进行跳转。
程序信息状态寄存器
xPSR(Extended Program Status Register)是 ARM 架构中用于存储处理器当前状态的重要寄存器,特别是在 ARM Cortex-M 系列微处理器中,xPSR 用于保存程序执行的状态信息。它比传统的 APSR 更为扩展,包含更多的控制位和状态标志。xPSR 在处理器进入或退出异常(例如中断)时非常关键。
xPSR 结构
xPSR 寄存器的位结构通常包括以下几个部分:
N (Negative Flag)
这与 APSR 中的 N 位相同,表示最后一次算术或逻辑操作的结果是否为负。
Z (Zero Flag)
这与 APSR 中的 Z 位相同,表示最后一次算术或逻辑操作的结果是否为零。
C (Carry Flag)
这与 APSR 中的 C 位相同,表示最后一次算术操作是否产生进位或借位。
V (Overflow Flag)
这与 APSR 中的 V 位相同,表示最后一次算术操作是否发生溢出。
Q (Saturation Flag)
与 APSR 中的 Q 位相同,表示操作是否发生了饱和。
IT[3:0] (If-Then Control Bits)
这些控制位用于支持 ARM 指令集中的 If-Then 语句。它们指示下一个几条指令是否需要条件执行。
GE[3:0] (Greater-than or Equal Flags)
这些标志与算术操作的条件代码相关,表示大于或等于的条件结果。
T (Thumb State)
这个位表示当前处理器处于 Thumb 模式还是 ARM 模式。Thumb 模式是 ARM 的一种指令集变种,指令较短,适用于内存受限的系统。
I (Interrupt Disable)
这个位表示是否禁用了中断。如果 I 位为 1,则禁用中断。
F (Fast Interrupt Disable)
这个位表示是否禁用了快速中断(FIQ)。如果 F 位为 1,则禁用快速中断。
M[4:0] (Mode Bits)
这些位表示当前处理器的工作模式。不同的模式有不同的处理优先级和特权级。例如,主模式(USER)、中断模式(IRQ)和快速中断模式(FIQ)等。
CONTROL Register
在某些 ARM 系列中,xPSR 还与 CONTROL 寄存器结合使用,后者控制特权模式与用户模式的切换、栈指针的选择等。
EXC_RETURN (Exception Return)
在发生异常时,xPSR 还保存异常返回信息,表示异常返回地址和状态。