📄
字号:
关于uCOS51V1.0版本不支持参数传递BUG的修正
2003/05/16 asdjf@163.com http://www.hjhj.com
uCOS51V1.0版本有一个严重BUG,不支持参数传递(在uCOS51V1.1版本中已经修正)。 网友YAYACOMNET指出此问题,经过检查是由于pdata没有入栈造成的。KEIL编译器对于函数参数的传递种类繁多,有时用寄存器,有时用仿真堆栈,还有的寄存器和堆栈混用,这下处理参数传递好象变得很复杂,似乎无法实现。幸运的是uC/OS-II的任务参数只有一个void *pdata,通过这个空指针,可以传递任意的结构体变量,用户参数安排在结构体里,使用灵活。经过查C51.PDF知,此种情况下,任务的void *ppdata参数恰好是用R3、R2、R1传递,而不通过虚拟堆栈。R3、R2、R1用于传递任务参数ppdata,其中R3代表存储器类型,R2为高字节偏移,R1为低字节位移。因为我用的全是XDATA,所以存储器类型固定为1即R3=1,见C51.PDF第178页说明。修改OS_CPU_C.C的部分代码如下:
void *OSTaskStkInit (void (*task)(void *pd), void *ppdata, void *ptos, INT16U opt) reentrant
{
OS_STK *stk;
ppdata = ppdata;
opt = opt; //opt没被用到,保留此语句防止告警产生
stk = (OS_STK *)ptos; //用户堆栈最低有效地址
*stk++ = 15; //用户堆栈长度
*stk++ = (INT16U)task & 0xFF; //任务地址低8位
*stk++ = (INT16U)task >> 8; //任务地址高8位
*stk++ = 0x00; //PSW
*stk++ = 0x0A; //ACC
*stk++ = 0x0B; //B
*stk++ = 0x00; //DPL
*stk++ = 0x00; //DPH
*stk++ = 0x00; //R0
//R3、R2、R1用于传递任务参数ppdata,其中R3代表存储器类型,R2为高字节偏移,R1为低字节位移。
//通过分析KEIL汇编,了解到任务的void *ppdata参数恰好是用R3、R2、R1传递,不是通过虚拟堆栈。
*stk++ = (INT16U)ppdata & 0xFF; //R1
*stk++ = (INT16U)ppdata >> 8; //R2
*stk++ = 0x01; //R3 因为我用的全是XDATA,所以存储器类型固定为1,见C51.PDF第178页说明。
*stk++ = 0x04; //R4
*stk++ = 0x05; //R5
*stk++ = 0x06; //R6
*stk++ = 0x07; //R7
//不用保存SP,任务切换时根据用户堆栈长度计算得出。
*stk++ = (INT16U) (ptos+MaxStkSize) >> 8; //?C_XBP 仿真堆栈指针高8位
*stk++ = (INT16U) (ptos+MaxStkSize) & 0xFF; //?C_XBP 仿真堆栈指针低8位
return ((void *)ptos);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -