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 }
附件是最新版本的源码:uCOSII-STC32G-V1.00.zip
需要设置全局可重入。昨天最后整理新建了工程,忘记设置了。