中断开关的实现
通过硬件(寄存器PRIMASK)实现全局中断开关:
CPU_INT_DIS(); 关闭中断(支持嵌套调用)
CPU_INT_EN(); 打开中断
其定义为:
#define CPU_INT_DIS() do { cpu_sr = CPU_SR_Save(); } while (0)
#define CPU_INT_EN() do { CPU_SR_Restore(cpu_sr); } while (0)
上述中断开关是最直接的一种中断方式,CPU_SR_Save()中通过汇编语言执行保存当前CPU的寄存器并关中断,然后通过CPU_SR_Restore()恢复寄存器值。
下面的中断实现通过对上述中断实施的进一步封装得到,系统直接控制全局中断实现:
CPU_CRITICAL_ENTER(); 进入中断 (在UCOS的cpu.h文件定义,支持嵌套)
CPU_CRITICAL_EXIT() ; 退出中断 是真的直接关掉中断
如果通过宏定义CPU_CFG_INT_DIS_MEAS_EN开启测量功能,CPU_CRITICAL_ENTER()相比较于CPU_INT_DIS()多了一个CPU_IntDisMeasStart()测量功能,若宏定义没开启这两对函数就完全相同。
下面的中断实现又是进一步对上面的进行有条件封装,通过系统有条件控制全局中断实现,任务前的判断实现:
OS_CRITICAL_ENTER();
OS_CRITICAL_EXIT();
或者在任务中,等待系统调度来实现中断:
OSIntEnter();
OSIntExit();
通常在进入中断处理函数的前后需要使用OSIntEnter()和OSIntExit(),能让OS与我们自己定义的中断函数产生联系甚至接管中断处理函数,而不至于破坏了系统调度的完整逻辑,例如:
void USART1_IRQHandler(void)
{
OSIntEnter();
if(USART_GetITStatus(USART1,USART_IT_RXNE))
{
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
OSIntExit();
}
其中关于函数的定义有:
void OSIntEnter(void)
{
if (OSRunning != OS_STATE_OS_RUNNING)
{
return;
}
if (OSIntNestingCtr >= (OS_NESTING_CTR)250u)
{
return;
}
OSIntNestingCtr++; //函数作用是对为中断嵌套深度全局变量OSIntNesting++,而在OSIntExit()进行OSIntNesting--操作
}
在中断服务函数中使用这对函数,是将中断和系统关联在一起,让系统可以感知到中断的发生,也是为了在中断处理函数后再进行相应的任务调度而不是回到中断前的地方,从而体现“实时”的性能。
但如果中断服务函数完成是十分迅速的(如写个标记)就没必要使用这对函数,因为这对函数也是需要一定的处理时间的,反而影响中断功能的完成。
在进入一些关键的代码段时,不允许被打断否者会出意外,需要加上临界区中断控制,在UCOSII中定义为:
OS_CPU_SR cpu_sr=0;
OS_ENTER_CRITICAL();
执行代码......
OS_EXIT_CRITICAL();
而在新的uCOS-III中改成了OS_CRITICAL_ENTER()和OS_CRITICAL_EXIT();
CPU_SR_ALLOC();
OS_CRITICAL_ENTER();
执行代码......
OS_CRITICAL_EXIT();
注意:如果在使用这对函数前不加CPU_SR_ALLOC(),会报错"cpu_sr" is undefined。
在使用这对函数时,OS_CRITICAL_ENTER()和OS_CRITICAL_EXIT()的具体实现还需要通过一个宏定义开关变量CPU_CFG_CRITICAL_METHOD控制,其列举的数值有3个:
OS_CRITICAL_METHOD= = 1时,直接使用处理器的开关中断指令来实现宏
#define OS_ENTER_CRITICAL()/OS_CRITICAL_ENTER() disable_int()
#define OS_EXIT_CRITICAL()/OS_CRITICAL_EXIT() enable_int()
这样存在一个问题,在从函数返回时,所有的中断可能都被使能了。
OS_CRITICAL_METHOD= = 2时,先把中断状态保存到堆栈再操作然后退出时恢复状态:
#define OS_ENTER_CRITICAL()/OS_CRITICAL_ENTER() asm(“PUSH PSW”); asm(“DI”);
#define OS_EXIT_CRITICAL()/OS_CRITICAL_EXIT() asm(“POP PSW”);
这种方法不会改变中断状态,避免前面的问题,但当用户使用的处理器有堆栈指针相对寻址模式时,可能出现严重错误。
OS_CRITICAL_METHOD= = 3时,只将处理器状态字保存在局部变量中:
#define OS_ENTER_CRITICAL()/OS_CRITICAL_ENTER() cpu_sr = get_processor_psw(); disable_interrupts();
#define OS_EXIT_CRITICAL()/OS_CRITICAL_EXIT() set_ processor_psw(cpu_sr);