??
字號:
關于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 + -