uC/OS-II进入or离开临界区三种方式

来源:互联网 发布:手机淘宝修改中差评 编辑:程序博客网 时间:2024/06/05 16:12

uC/OS-II中利用OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()来保护临界区,有三种方式:

  1. #if OS_CRITICAL_METHOD == 1  
  2. #define OS_ENTER_CRITICAL() __asm__("cli")  
  3. #define OS_EXIT_CRITICAL() __asm__("sti")  
  4. #endif  
  5.   
  6. #if OS_CRITICAL_METHOD == 2  
  7. #define OS_ENTER_CRITICAL() __asm__("pushf \n\t cli")  
  8. #define OS_EXIT_CRITICAL() __asm__("popf")  
  9. #endif  
  10.   
  11. #if OS_CRITICAL_METHOD == 3  
  12. #define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR())  
  13. #define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr))  
  14. #endif 
第一种方式是简单的开关中断,不适于中断嵌套显然是被摒弃的,只应用于不支持nvic的处理器中;

第二种方式和第三种方式都可以支持中断嵌套,但两者到底有什么区别呢,现在给出两种说法:

说法一

“将中断状态不加以区分的保存在堆栈中”vs“将中断状态保存在系统服务共享的局部变量中”,前者会导致这样一种情况“用户在调用象OSTimeDly()之类的服务之前就禁止中断,很有可能用户的应用程序会崩溃。发生这种情况的原因是任务被挂起直到时间期满,而中断是禁止的,因而用户不可能获得节拍中断!”即关闭了中断导致系统服务终止影响到任务运行。所以“将中断状态保存在系统服务共享的局部变量中”就可以避免。

说法二

参照了gcc编译结果的汇编模拟,无论是否加优化选项这一问题都存在。这个问题的起因很简单,gcc想聪明一点,一次把堆栈降个够,然后它就可以在栈上随意放参数去调用其他函数。尤其是在调用函数较多的时候,这种做法就更有意义。而且,gcc这种聪明与优化选项O好像没有太大关系,好像没有什么能禁止它这么做。但问题是,gcc不知道我们的OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()是操作了堆栈的,我尝试过使用__asm__ __volatile__("pushfd \n\tcli":::"memory")来通知gcc内存数据改变了,但显然gcc不认为堆栈也改变了。于是,OS_ENTER_CRITICAL()保存在栈上的状态就被冲掉了,比如被这里调用参数a的值。在恢复时,是否会引发异常,会引发什么异常,这个就要靠运气了。但我相信一个人的运气不会总是那么好的,所以最后别使用OS_CRITICAL_METHOD=2。

到底是哪种原因我也不清楚,我倾向与前者,有哪位大神给出更合理的解释,洗耳恭听。

0 0
原创粉丝点击