uCOS-II-2.93.01 for STC32G12K128 请帮忙查错
本移植参考STC论坛网友tzz1983的移植方案,使用定时器4模拟软件中断PendSv
一,使用注意:
本移植整个工程统一使用寄存器组0,用户不能修改寄存器组。寄存器组1,2,3共24字节用于data/edata区。
中断函数执行完毕,执行RETI返回前不建议关闭中断总开关。如果关闭一般认为是程序员的Bug。
系统启动前不能开中断,不然OSIntNesting一直会++。
二,void OSStartHighRdy(void)行数提供了3种方法切换到第一个任务。
- <font size="3">//方法1:使用ERET返回,返回前需要从新调整堆栈的内容,由于任务第一次运行,R4,R5,R6 给任何值都没关系。
-
- //读取任务的SP
- __asm { MOV DR4,OSTCBCur }
- __asm { MOV WR2,@WR6+0x2 }
- __asm { MOV DR60,DR0 }
-
- //寄存器出栈
- __asm { POP PSW }
- __asm { POP DR0 }
- __asm { POP DR4 }
- __asm { POP DR8 }
- __asm { POP DR12 }
- __asm { POP DR16 }
- __asm { POP DR20 }
- __asm { POP DR24 }
- __asm { POP DR28 }
- __asm { POP DR56 }
-
- //PC和PSW1出栈
- __asm { POP R4 }
- __asm { POP R6 }
- __asm { POP R5 }
- __asm { POP PSW1 }
-
- //把返回地址格式做成ERET的返回格试
- __asm { PUSH R5 }
- __asm { PUSH R4 }
- __asm { PUSH R6 }
- __asm { SETB EA }
- //用ERET指令转移到任务中去, 0XAA是ERET指令的编码
- __asm { DB 0AAH }
-
- //方法2:使用RETI返回,由于系统刚开始,其他中断都没有开始触发。用RETI完全没问题的。
-
- //读取任务的SP
- __asm { MOV DR4,OSTCBCur }
- __asm { MOV WR2,@WR6+0x2 }
- __asm { MOV DR60,DR0 }
-
- //寄存器出栈
- __asm { POP PSW }
- __asm { POP DR0 }
- __asm { POP DR4 }
- __asm { POP DR8 }
- __asm { POP DR12 }
- __asm { POP DR16 }
- __asm { POP DR20 }
- __asm { POP DR24 }
- __asm { POP DR28 }
- __asm { POP DR56 }
- __asm { SETB EA }
- __asm { RETI }
-
- //方法3:使用PendSvIsr中断切换到第一个任务
- //巧妙指向DR0内存位置。SP保存到任务控制块的时候,实际操作是MOV DR0,DR0,也就是DR0值不变
-
- OSTCBCur = (OS_TCB *)0;
- PendSv_GenerateSWInterrupt();
- EA = 1;
- while(1);</font>
复制代码
三,优化了OS_CPU_PendSVHandler中断函数
- <font size="3">void OS_CPU_PendSVHandler( void )
- {
- //函数入口标号,中断跳转到入口标号,解决huge和large存储模式不一样函数名字不一样的问题。
- __asm {OS_CPU_PendSVHandler_00: }
- //寄存器入栈
- __asm { PUSH DR56 }
- __asm { PUSH DR28 }
- __asm { PUSH DR24 }
- __asm { PUSH DR20 }
- __asm { PUSH DR16 }
- __asm { PUSH DR12 }
- __asm { PUSH DR8 }
- __asm { PUSH DR4 }
- __asm { PUSH DR0 }
- __asm { PUSH PSW }
-
-
- //SP保存到任务控制块
- __asm { MOV DR0,DR60 }
- __asm { MOV DR4,OSTCBCur }
- __asm { MOV @WR6+0x2,WR2 }
-
-
- //保存并关EA ,其实EA=0问题也不大,如果中断返回的时候EA=0,这个很明显是程序员的bug
- __asm { SETB C }
- __asm { JBC EA,PendSvIsr_01 }
- __asm { CLR C }
- __asm { PendSvIsr_01: }
- __asm { PUSH PSW }
-
- OSTaskSwHook();
- OSPrioCur = OSPrioHighRdy;
- OSTCBCur = OSTCBHighRdy;
-
- //恢复EA
- __asm{ POP PSW }
- __asm{ MOV EA,C }
-
-
-
- //读取任务的SP
- // ;OSTCBCur = OSTCBHighRdy; 的汇编
- // MOV DR4,OSTCBHighRdy
- // MOV OSTCBCur,DR4
- //说明DR4的值已经是OSTCBCur,下面这条可以屏蔽
- // __asm { MOV DR4,OSTCBCur }
- __asm { MOV WR2,@WR6+0x2 }
- __asm { MOV DR60,DR0 }
-
- //寄存器出栈
- __asm { POP PSW }
- __asm { POP DR0 }
- __asm { POP DR4 }
- __asm { POP DR8 }
- __asm { POP DR12 }
- __asm { POP DR16 }
- __asm { POP DR20 }
- __asm { POP DR24 }
- __asm { POP DR28 }
- __asm { POP DR56 }
-
- //中断返回
- __asm { RETI }
- }</font>
复制代码
四,函数入口标号,中断跳转到入口标号,解决huge和large存储模式不同,函数名字不一样的问题。
/*-----------------------------------------------------------*
PendSv 向量入口引导
*-----------------------------------------------------------*/
__asm {OS_CPU_PendSVHandler_00: }
__asm { CSEG AT PendSv_EntryAddress }
__asm { JMP OS_CPU_PendSVHandler_00 }
附件是最新版本的源码:
|