UCOSIII(2)——CPU_SR_Save与CPU_SR_Restore临界段代码的实现

临界段代码,也称作临界域,是一段不可分割的代码。

我们都知道在进入中断函数或者异常的时候代码会被打断而进入中断服务函数。而有些代码是不允许被打断的,比如:一些外围器件的的初始化(LCD)、任务函数的创建等等。所以在 uCOS 中包含了很多临界段代 码来保护临界段。

那么临界段函数是怎么操作的?简单啊——关中断关异常

临界端代码实现的汇编函数:

CPU_SR_Save
		;通过 MRS 指令将特殊寄存器 PRIMASK 寄存器的值读取到通用寄存器 R0。
        MRS     R0, PRIMASK    ; Set prio int mask to mask all (except faults)
        CPSID   I              ;关闭中断
        BX      LR


CPU_SR_Restore                 ; See Note #2.
	    ;通过 MSR 指令将通用寄存器 R0 的值写入到特殊寄存器 PRIMASK。
        MSR     PRIMASK, R0
        BX      LR

  • CPU_SR_Save是关闭中断函数
  • CPU_SR_Restore是恢复中断函数(准确来说是恢复PRIMASK 寄存器状态)

在这里插入图片描述
这里使用了CPSID I来关闭中断,但是没有用到CPSIDE I来开启中断。
那么中断是如何开启的呢?

答案就在以下这两个语句中,uCOS是通过恢复关中断前PRIMASK的状态来恢复中断的 :
MRS R0, PRIMASK ;通过 MRS 指令将特殊寄存器 PRIMASK 寄存器的值读取到通用寄存器 R0。
MSR PRIMASK, R0;通过 MSR 指令将通用寄存器 R0 的值写入到特殊寄存器 PRIMASK。

在uCOS里面,临界段代码的开关中断就是操控PRIMASK 寄存器来实现的。
一开始在关中断前用R0保存了PRIMASK 的值(MRS R0, PRIMASK),然后用CPSID I语句关掉中断;
在开启中断时(恢复状态),用语句(MSR PRIMASK, R0)把关中断以前PRIMASK 的值恢复到PRIMASK 中。
如果之前PRIMASK的值为1,那么恢复它的值也为1,也就是没有中断还是关着的没有打开,那么可以判断之前肯定发生了临界段代码的嵌套;如果之前PRIMASK为0,那么恢复后也为0,也就是说中断被开启了。

其实这样做是为了处理临界段发生嵌套时发生的情况(如果用CPSIE I来恢复中断就太粗暴了,如果之前已经发生了一个临界段而且还没有处理完,用CPSIE I开了中断,那之前使用了临界段的代码肯定要出错了)。

C语言中函数:

#define  CPU_SR_ALLOC()             CPU_SR  cpu_sr = (CPU_SR)0           //宏函数,相当于定义了一个32位变量cpu_sr ,并赋值为0

/*实现中断打开与关闭的4个函数,其实它们都是调用了上面所说的汇编函数*/
#define  CPU_INT_DIS()         do { cpu_sr = CPU_SR_Save(); } while (0) /* Save    CPU status word & disable interrupts.*/
#define  CPU_INT_EN()          do { CPU_SR_Restore(cpu_sr); } while (0) /* Restore CPU status word.                     */


#define  CPU_CRITICAL_ENTER()  do { CPU_INT_DIS(); } while (0)          /* Disable   interrupts.                        */
#define  CPU_CRITICAL_EXIT()   do { CPU_INT_EN();  } while (0)          /* Re-enable interrupts.                        */

————————————题外—————————————
开始时,我对C语言那几个函数不是很了解,总是看不懂;其实是由于我对#define宏定义的使用不熟悉,而且uCOS里面的宏定义实在有点多,刚开始看得有点晕。
其实这里是用到了宏函数!我用C语言就做了一个测试:

#include<stdio.h>
typedef unsigned  int                 CPU_INT32U; 
typedef  CPU_INT32U                 CPU_SR; 
/* 宏函数CPU_SR_ALLOC()的作用相当于定义一个32位变量cpu_sr并赋初值为0*/
#define  CPU_SR_ALLOC()            CPU_INT32U  cpu_sr = (CPU_INT32U)0
/*宏函数修改cpu_sr的值为11*/
#define  CPU_INT_DIS()         do { cpu_sr = 11; } while (0) 
void main ()
{
	 CPU_SR_ALLOC() ;                //相当于定义了一个变量cpu_sr
	 printf("cpu_sr=%d\n",cpu_sr);
	 CPU_INT_DIS();					//修改变量cpu_sr=11
	 printf("cpu_sr=%d",cpu_sr);
	 getch();					   //窗口停留函数,调试时使用

}

在这里插入图片描述
其实宏定义很简单,直接把你宏定义的内容直接放进代码代替那个宏里面看就可以了。
代替后的结果是:

#include<stdio.h>
void main ()
{
	 unsigned int cpu_sr=0;
	 printf("cpu_sr=%d\n",cpu_sr);
	 cpu_sr=11;								//修改变量cpu_sr=11
	 printf("cpu_sr=%d",cpu_sr);
	 getch();								 //窗口停留函数,调试时使用

}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
代码uC/OS-II操作系统中的一部分。主要涉及到操作系统中关于中断和临界区的处理。下面是对每个部分的解释: 1. `#define OS_CRITICAL_METHOD 3`:定义临界区保护方法。在本例中,使用了方法3,即使用汇编代码实现保护。 2. `#if OS_CRITICAL_METHOD == 3`:根据定义的保护方法选择不同的临界区保护方式。 3. `#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();}`:定义进入临界区的宏,其中`OS_CPU_SR_Save()`是一个汇编函数,用于保存CPU状态寄存器的值,并关闭中断。 4. `#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);}`:定义退出临界区的宏,其中`OS_CPU_SR_Restore(cpu_sr)`是一个汇编函数,用于恢复CPU状态寄存器的值,并打开中断。 5. `void OSCtxSw(void)`:任务切换函数,用于把当前任务切换到下一个就绪任务。 6. `void OSIntCtxSw(void)`:中断切换函数,用于在中断服务程序中切换任务。 7. `void OSStartHighRdy(void)`:启动系统,从最高优先级的任务开始执行。 8. `void OSPendSV(void)`:处理中断服务程序中的软件中断请求。 9. `#if OS_CRITICAL_METHOD == 3u`:同2。 10. `OS_CPU_SR OS_CPU_SR_Save(void)`:保存CPU状态寄存器的值,并关闭中断。 11. `void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr)`:恢复CPU状态寄存器的值,并打开中断。 12. `OS_CPU_EXT INT32U OSInterrputSum`:定义了一个全局变量,用于统计中断的次数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值