BUG二:
ASP
PUSH DP:ST1
對應有:
POP DP:ST1
NASP
本人在解決第1個問題后,在中斷中調用系統信號量函數,發現一調用,系統就崩潰了,經過試驗,發現是堆棧指針對齊的問題,即ASP 和 NASP
造成的。ASP受ST1中的一個位控制,所以添加此代碼,
保存ST1。同時保存DP1是因為要保證堆棧地址為偶數地址,其實保存DP不起什么作用,僅僅是用來對齊堆棧地址為偶數地址,沒有其他的意思。
在os_cpu_c.c文件中,也作了些修改,如下:
void *OSTaskStkInit (void (*task)(void *pd), void *pdata, void *ptos, INT16U
opt)
{
INT16U *stk;
INT16U temp;
opt = opt; /* 'opt' is not used, prevent warning */
stk = (INT16U *)ptos; /* Load stack pointer */
temp = ((INT32U)pdata)&0x0000ffff; /* Simulate call to function with
argument */
*stk++ = (INT16U)temp; /* 保存低16位 */
temp = ((INT32U)pdata)>>16; /* Simulate call to function with argument
*/
*stk++ = (INT16U)(temp); /* 保存高16位*/
*stk++ = 0x0000; /* ST0 = 0x1111 */
*stk++ = 0x0000; /* T = 0x0000 */
*stk++ = 0x0000; /* AL = 0x3333 */
*stk++ = 0x0000; /* AH = 0x2222 */
*stk++ = 0x0000; /* PL = 0x5555 */
*stk++ = 0x0000; /* PH = 0x4444 */
*stk++ = 0x0000; /* AR0 = 0x7777 */
*stk++ = 0x0000; /* AR1 = 0x6666 */
*stk++ = 0x0A0A; /* ST1 = 0x080B */
*stk++ = 0x0000; /* DP = 0x8888 */
*stk++ = 0x2003; /* IER = 0xBBBB */
*stk++ = 0x2003; /* DBGSTAT = 0xAAAA */
temp = ((INT32U)task)&0x0000ffff;
*stk++ = (INT16U)temp; /* 保存低16位 */
temp = ((INT32U)task)>>16; /* Save task entry */
*stk++ = (INT16U)(temp); /* 保存高16位 */
// PUSH RPC
temp = ((INT32U)task)&0x0000ffff; /* RPCL = 0xCCCC */
*stk++ = (INT16U)temp; /* 保存低16位 */
temp = ((INT32U)task)>>16; /* RPCH = 0xCCCC */
*stk++ = (INT16U)(temp); /* 保存高16位*/
/*
下為手工保存的寄存器
PUSH AR1H:AR0H
PUSH XAR2
PUSH XAR3
PUSH XAR4
PUSH XAR5
PUSH XAR6
PUSH XAR7
PUSH XT
PUSH ST1:DP
*/
*stk++ = 0x0000; /* 保存高16位 */
*stk++ = 0x0000; /* 保存高16位 */
*stk++ = 0x0000; /* 保存高16位 */
*stk++ = 0x0000; /* 保存高16位 */
*stk++ = 0x0000; /* 保存高16位 */
*stk++ = 0x0000; /* 保存高16位 */
*stk++ = 0x0000; /* 保存高16位 */
*stk++ = 0x0000; /* 保存高16位 */
*stk++ = 0x0000; /* 保存高16位 */
*stk++ = 0x0000; /* 保存高16位 */
*stk++ = 0x0000; /* 保存高16位 */
*stk++ = 0x0000; /* 保存高16位 */
*stk++ = 0x0000; /* 保存高16位 */
*stk++ = 0x0000; /* 保存高16位 */
*stk++ = 0x0000; /* 保存高16位 */
*stk++ = 0x0000; /* 保存高16位 */
*stk++ = 0x0A0A; /* ST1 */
*stk++ = 0x0000; /* DP */
stk++;
return ((void *)stk);
}
文件中比較重要的地方都以紅色作了標記,這里特別說明:
temp = ((INT32U)pdata)&0x0000ffff; /* Simulate call to function with
argument */
*stk++ = (INT16U)temp; /* 保存低16位 */
temp = ((INT32U)pdata)>>16; /* Simulate call to function with argument
*/
*stk++ = (INT16U)(temp); /* 保存高16位*/
這個好像沒什么用,這樣做只是為了避免編譯時出現告警(和原來比較)。
*stk++ = 0x0A0A; /* ST1 = 0x080B */
這個特別重要。因為進入任務后,中斷必須都是開著的,這個值直接用來設置ST1,詳細見ST1的位說明。任務在第一次進入時,NASP指令不能起作用也由這里控制(任務堆棧一般為偶地址)。總中斷是由ST1來控制的,因此,在進入任務前,你開關總中斷都是無意義的操作,只有這里才是開總中斷的地方,要特別注意。當然,你也可以在每個任務開始設置總中斷,但那樣比較復雜。