您现在的位置:首页 > 技术资料 | 上载库存 |
μC/OS-Il在TMS320VC33上的可靠应用
目前,μC/0S-II已经被成功移植到多种微处理器 上,其中也包括TMS320VC33。在μC/0S-II的网站上可以免费下载相关处理器的移植代码,这些代码可以作为 μC/OS-II应用中一个非常好的起点。笔者在应用这些 移植代码时遇到了一些问题,因此如何使移植更加可靠、 高效,仍然是一个值得深入探讨的话题。网上 TMS320VC33的移植代码已经完成了基本的移植工作, 本文不对移植的详细过程进行赘述,而只就移植及应用过程中的一些关键步骤和涉及到代码可靠性的问题进行讨论。 1 宏OS_ENTER_CRITlCAL和OS_EXIT_ CRITICAL
表1中,proga+l是单周期取指指令。如果prog a+l 是多周期取指指令(例如取指时含有等待状态),中断响应会延迟到prog a+l执行以后。由表1可知,DSP对中断 的响应是在取指边界而不是指令的执行边界。假设prog a一2是关中断指令“andn 2000H,st”,那么prog a一1、 prog a甚至prog a+l仍然是可中断的,必须等到prog a +l执行完毕后才能完全禁止中断。同样在开中断时,紧邻开中断指令的后三条指令是不响应中断的。现在考虑下面的情况:系统通过OS_ENTER_CRITICAL宏禁止中断时,同时发生了中断请求,并且紧邻的三条指令是访问全局变量的指令。此时,由于流水线结构的执行特点, DSP还是会响应中断,如果相应的中断服务程序也访问了同样的全局变量,这样就可能破坏数据的一致性,造成系统的崩溃。为了防止这种情况,必须在改变系统中断状态时能够消除流水线操作带来的影响。为可靠实现OS_ ENTER_CRlTICAL和OS_EXIT_CRITICAL宏,在修改 ST寄存器之前加一条指令“RPTS O”。因为在RPTS指 令执行过程中会自动禁止中断,并且停止流水线操作,只有RPTS指令的下一条指令执行完毕后,DSP才会重新打开流水线。这样就保证了改变DSP中断状态时不会响应中断,也不会执行其他指令。上述宏的可靠实现为:
需要说明的是,利用trap指令的实现方式也是可靠的,但trap和rets/reti会两次清除流水线,因而会对性能稍微有点影响。OS_ENTER_CRITICAL宏的另外两种实现方法首先要保存DSP的中断状态,然后再改变中断状态。相应的,OS_EXIT_CRlTICAL宏可直接从前面保存的状态进行恢复。由于流水线操作的影响,要正确保存ST寄存器的状态,直接的存储或压栈指令是不行的,需要一些附加的保护性代码,本文就不再深入讨论了。 2 OSRdyGrp和OSRdyTbl
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修饰符后的编译结果为: 3 中断处理程序 结语
|