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来控制的,因此,在进入任务前,你开关总中断都是无意义的操作,只有这里才是开总中断的地方,要特别注意。当然,你也可以在每个任务开始设置总中断,但那样比较复杂。