首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

μC/OS-Il在TMS320VC33上的可靠应用 02

μC/OS-Il在TMS320VC33上的可靠应用 02

OSTimeTick函数的while循环结构从第5行开始至第23行结束。修改OSRdyGrp的语句是第8行,可以看出对OSRdyGrp的修改没有保存至相应的内存单元,而是保存在寄存器r0中,对OSRdyTbl的修改却直接保存到了内存单元(第14行)。位于循环体外的第4行语句将OSRdyGrp赋值给10,第24行将r0的内容保存至OSRdyGrp。编译器利用寄存器优化了对OSRdyGrp的访问,循环结构中OSRdyGrp值的每次改变都保存在寄存器中,只是在循环开始和结束时访问了两次内存,编译器这样的处理显然是高效的.如果不优化,语句“OSRdyGrp|=ptcb->OSTCBBitY”必须以读-改-写的方式实现,OSRdyGrp值的每次改变需要访问两次内存,而一般情况下对内存的访问是耗时的.应尽量避免。由上述代码容易看出,这样的优化使得对OSRdyGrp的访问位于临界区以外,因而引入了不安全因素。因为在时钟节拍中断服务程序OSTicklSR中允许嵌套中断,所以第19行以后的语句是可中断的。如果在20~23行之间发生了中断,并且相应的中断服务程序改变了OSRdyGrp,那么第24行的赋值可能使OSRdyrp获得一个错误的结果,造成 OSRdy(jrp与C)SRdyrTbl的不一致。第4行的赋值语句同样是危险的,如果有中断发生,rO中暂存的值不一定是当前正确的OSRdyGrp。奇怪的是,无论采用何种编译优化选项,编译器对OSRdyGrp的处理都是一样的,即使禁止优化也没有用。在函数0S_TaskStat中对于OSStatRdy 的处理,无论采用何种编译优化选项都不会对OSStatRdy 进行寄存器优化。知道原因后,对这一问题的处理是非常简单的,只要在OSRdyGrp声明时加上volatile修饰符(位于文件uCOS_II.H中)就可以禁止编译器对OSRdyGrp 进行寄存器优化。给OSRdyGrp加上volatile修饰符后的编译结果为:


    与上面的第7、8行对比可以看出,对OSRdyGrp的每次修改都访问了内存单元,并且是在临界区内进行的。
3 中断处理程序
    因为任务的切换是以中断方式进行的,如果某个中断向量的处理程序可能引起任务切换或者允许嵌套中断,该中断处理程序必须严格按照μC/OS_II要求的步骤进行。其中涉及到全部寄存器的保存与恢复、特定的μC/OS_II 函数调用、任务切换的处理等。虽然Code Composer支持 C语言的中断处理函数,但是C函数的中断处理程序不能产生正确的堆栈结构,所以最好不要直接用C语言处理中断而是使用汇编语言。惟一的例外是中断处理不涉及 μC/0S_II函数调用,并且禁止中断嵌套,这时使用C语言会比较方便。时钟节拍中断服务程序OSTicklSR为中断服务程序的编写提供了一个很好的范例。OSTicklSR 采用汇编语言实现了寄存器的保存与恢复,以及μC/OS_H 函数调用,真正的中断处理在C函数CSTimeTick中。用户的中断处理程序完全可以采用和OSTicklSR相同的汇编语言框架,然后用C函数完成实际的处理。需要说明的是,如果允许中断嵌套,开中断指令必须要放在OSin_ tEnter函数调用之后。如果在OSintEnter之前开中断,嵌套的中断服务程序不会知道自己是否是嵌套执行的,因而可能会执行任务切换。这样外层中断的堆栈将处于一个不确定的状态,引起系统的崩溃。关于这一点,网上移植代码的处理是不正确的。
返回列表