文章目录
说明:
在操作系统内核代码里,进入、退出临界代码如下:
unsigned int OS_CPU_SR_Save(void);
void OS_CPU_SR_Restore(unsigned int sr);
#define RAW_SR_ALLOC() unsigned int cpu_sr = 0
#define USER_CPU_INT_DISABLE() {cpu_sr = OS_CPU_SR_Save();}
#define USER_CPU_INT_ENABLE() {OS_CPU_SR_Restore(cpu_sr);}
//下面是汇编部分
OS_CPU_SR_Save
MRS R0, PRIMASK ;MRS: 状态寄存器到通用寄存器的传送指令
CPSID I ;屏蔽了所有中断,只剩下NMI、复位中断、硬件中断,也屏蔽了PendSV
BX LR
OS_CPU_SR_Restore
MSR PRIMASK, R0 ;MSR: 通用寄存器到状态寄存器的传送指令。
BX LR
关于其使用,一般会在执行进临界区之前,先执行以下语句:
RAW_SR_ALLOC();
该语句即是声明一个变量cpu_sr ,初始值为0;
然后调用进入临界区关闭中断指令:
USER_CPU_INT_DISABLE();
这个宏定义相当于执行
cpu_sr = OS_CPU_SR_Save();
其中cpu_sr是我们刚刚声明的初始值为0的变量。这个函数会调用汇编部分代码:
OS_CPU_SR_Save
MRS R0, PRIMASK ;MRS: 状态寄存器到通用寄存器的传送指令
CPSID I ;屏蔽了所有中断,只剩下NMI、复位中断、硬件中断,也屏蔽了PendSV
BX LR
将PRIMASK中断状态寄存器的值读到R0里,然后关闭中断,然后返回。我们要知道,在ARM架构里,函数返回值是通过寄存器R0传递的,因此就把PRIMASK传递给了cpu_sr。
当执行完临界区代码后,想退出临界区,就会执行
USER_CPU_INT_ENABLE();
这个宏定义相当于执行OS_CPU_SR_Restore(cpu_sr)函数,而在ARM架构里,参数传递是通过寄存器来传递的,因此0就被放在了寄存器R0里面。然后执行汇编部分代码,
OS_CPU_SR_Restore
MSR PRIMASK, R0 ;MSR: 通用寄存器到状态寄存器的传送指令。
BX LR
将PRIMASK中断屏蔽寄存器设置为了R0的值,而R0的值等于函数传入的形参cpu_sr,而cpu_sr的值是进入临界区前PRIMASK的值,就实现了恢复到进临界区之前的状态