2009年4月7日

μC/OS-II 研究系列 - 001

临界段代码处理.

所谓临界段代码, Critical Sections of Code, 就是这段代码在执行时, 不希望也不允许有中断发生.
所有使用了系统变量, 也就是全局变量, 的代码段, 基本上都是属于这一类, 除非使用信号量的方式对全局变量加以了保护.
---------------------------------
处理方法:
封装了两个宏, OS_ENTER_CRITICAL(), OS_EXIT_CRITICAL(), 分别用于进入临界段, 退出临界段.
封装方式:
OS_CRITICAL_METHOD 宏定义, 用来指示采用何种封装方式.
#1
直接定义为关中断, 开中断.
/* pseudo code*/
#if OS_CRITICAL_METHOD == 1
#define OS_ENTER_CRITICAL() __asm_tag__ (CLI;)
#define OS_EXIT_CRITICAL() __asm_tag__ (STI;)
#endif

上面是伪代码, 使用的两条汇编指令 CLI STI 是 IA-32 以及 IA-64 架构中的关中断 Clear Interrupt, 开中断 Set Interrupt 指令. 具体可以参考 Intel 64 and IA-32 Architectures -- Software Developer's Manual 的第一卷 5.1.11.
pros:
# 简便, 迅速. 对于处理器速度很慢的系统尤其适用.
# 有些系统仅仅能够使用此类方法.
cons:
如果系统本身就是关中断状态, 那么使用 OS_ENTER_CRITICAL() OS_EXIT_CRITICAL() 组合后, 系统中断将打开. 这时便有可能产生严重错误.
#2
先保存当前状态, 再进入临界段代码, 退出时恢复.
保存方式可以使用堆栈, 如,
/* pseudo code*/
#if OS_CRITICAL_METHOD == 2
#define OS_ENTER_CRITICAL() __asm_tag__ (PUSHF; CLI;)
#define OS_EXIT_CRITICAL() __asm_tag__ (POPF;)
#endif

也可以根据编译器提供的方式, 如,
/* pseudo code*/
#if OS_CRITICAL_METHOD == 3
#define OS_ENTER_CRITICAL() \
cpu_sr = get_processor_psw(); \
disable_interrupt();
#define OS_EXIT_CRITICAL() \
set_processor_psw(cpu_sr);
#endif

其中 cpu_sr 是和系统的程序状态字寄存器, Program Status Register, 大小一致的变量.
如8051中的 PSW 是8位, 就应该定义, typedef unsigned char OS_CPU_SR; OS_CPU_SR cpu_sr;. 如 IA-32 架构的 EFLAGS 是32位, 则应该是 typedef unsigned long int OS_CPU_SR;.
pros:
没有第一种实现方式的错误.
cons:
占用的时钟周期自然就增加了, 对于系统的速度有所拖累.
---------------------------------
总结:
这里所提到的两个宏定义, 都是在 OS_CPU.h 文件中, 用于移植所需.
至于移植时, 采取何种办法, 根据各类架构应用而定.
如果对于「是否屏蔽了中断」不敏感, 那么使用第一种方式足矣. 如果敏感, 务必使用第二种, 否则系统定然崩溃或者挂起.
而在第二种中, 推荐使用编译器提供的方式, 而非内联汇编的堆栈操作. 因为有时候编译器对内联汇编支持不好, 可能导致对堆栈指针 SP 的处理出错.
---------------------------------
** 注意:
一旦进入临界段代码, 所有中断便随之关闭, 包括定时时钟中断 Clock Tick Interrupt. 如果在此时调用类似 OSTimeDly() 的延时功能函数, 便会导致系统挂起, 也就是死机, 因为时钟节拍中断无法得到服务. 谨慎起见, 调用任何功能函数前, 都要保证中断是开着的.
而且, 如果临界段代码太长, 占用时钟周期太多, 会导致系统对中断的响应变慢, 中断延时增加, 这对于商业实时系统是不可忍受的. 因此务必良好规划和设计, 将临界段代码压缩至最小, 切记切记.

- EOF -

没有评论:

发表评论

不要使用过激的暴力或者色情词汇.
不要充当勇猛小飞侠 --- 飘过 飞过 扑扑翅膀飞走 被雷得外焦里嫩地飞走.
万万不可充当小乌龟 --- 爬过.
构建河蟹社会 责任你有 我有 大家有 -_-

Creative Commons License 转载请指明出处. 谢谢合作.
/***********************
author: jtuki
http://jtuki.blogspot.com/
***********************/