uC/OS-II进入or离开临界区三种方式
来源:互联网 发布:手机淘宝修改中差评 编辑:程序博客网 时间:2024/06/05 16:12
uC/OS-II中利用OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()来保护临界区,有三种方式:
- #if OS_CRITICAL_METHOD == 1
- #define OS_ENTER_CRITICAL() __asm__("cli")
- #define OS_EXIT_CRITICAL() __asm__("sti")
- #endif
- #if OS_CRITICAL_METHOD == 2
- #define OS_ENTER_CRITICAL() __asm__("pushf \n\t cli")
- #define OS_EXIT_CRITICAL() __asm__("popf")
- #endif
- #if OS_CRITICAL_METHOD == 3
- #define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR())
- #define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr))
- #endif
第二种方式和第三种方式都可以支持中断嵌套,但两者到底有什么区别呢,现在给出两种说法:
说法一
“将中断状态不加以区分的保存在堆栈中”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。
到底是哪种原因我也不清楚,我倾向与前者,有哪位大神给出更合理的解释,洗耳恭听。
- uC/OS-II进入or离开临界区三种方式
- 学习札记--uC/OS-II处理临界区代码的三种方法小结
- 学习札记--uC/OS-II处理临界区代码的三种方法小结
- uC/OS-II简介
- UC/OS -II入门
- uC/OS-II
- uC/OS-II 下载
- uC/OS II总结
- uC/OS-II 简介
- UC/OS-II笔记
- uC/OS-II 移植
- uc/os-ii介绍
- uC/OS II简介
- uC/OS-II简介
- uC/OS-II (2)
- 初学uC/OS II
- uC/OS II移植
- uc/os-ii信号量
- C++调用 python 函数及返回值的处理【元组,字符串...】
- sqlserver数据库优化
- android线性布局LinearLayout源代码
- POJ训练计划2632_Crashing Robots(模拟)
- C#3.0介绍(十二)-Lambda表达式中Lifting
- uC/OS-II进入or离开临界区三种方式
- 转: C#操作SQL Server数据库
- libcurl之curl_easy_getinfo的使用教程
- 开源类库工具整理
- TShop
- VirtualBox 里安装win7 / win8 不能全屏的解决方法
- 从Trie树(字典树)谈到后缀树(10.28修订)
- 使用宏(Macro)扩展Visual Studio IDE
- 地图定位