OSTCBTbl任务控制块数组,OSTCBPrioTbl里面包含任务控制块指针,和就绪表是对应的,然后就是任务的优先级等。经过查看跟踪Stack栈内容,也未发现问题。然后无意中看到我cpu的sr寄存器中GIE被关了,而且莫名其妙的cpu的oscoff和cpuoff,及scg0,scg1置位了。这让我很纳闷,GIE关了任务肯定不能调度,但是我也没有主动去进入低功耗模式。因为我的空闲任务中的钩子函数是空的,那么程序哪里会主动关呢?
整整3天就是在想,上网百度了也没有结果。不过我只能怀疑我的OS
timeTick()函数了,因为430没有可屏蔽的定时器,不像cortex-m0内核,有个system定时器,优先级很高。就只能选用了开门狗定时器了。也怪自己手残,觉得定时器中断处理应该和cortex-m0差不多,就这样处理了:
#pragmavector=WDT_VECTOR__interrupt
void WDT_ISR(void)
{
OS_CPU_SR cpu_sr; //使用方式3
OS_ENTER_CRITICAL();
OSIntNesting++; //中断嵌套层数
OS_EXIT_CRITICAL();
OSTimeTick();
OSIntExit(); //中断级任务调度
}
但是在430Os_cpu_a.s43中,中断函数是这样实现的,使用汇编语言,因为汇编不是很熟,c语言看着舒服。经过对比,这是处理最大的区别:
mov.w &OSTCBCur, R13
mov.w SP, 0(R13)mov.w &OSISRStkPtr, SP
为什么中断处理的时候使用到了主堆栈,大家可以看这个函数
OSStartHighRdy
call #OSTaskSwHook
mov.b #1, &OSRunning
mov.w SP, &OSISRStkPtr
mov.w &OSTCBHighRdy, R13
mov.w @R13, SP
POPALL
reti
函数OSStartHighRdy是在ucos初始化ucos变量和创建至少一个任务空闲任务,在osstart中调用的,说白了就是第一次调用优先级最高的任务,而OSISRStkPtr也就保存了程序的主堆栈,在没有申请局部量的情况下,他应该跟我们普通的main里的栈顶地址是一样的。这个OSISRStkPtr的作用就在这体现了,但是我也有疑问了,为什么在执行中断任务的时候用了任务的栈就会出现如此大的问题。这是我这次调试过程中最大的疑问?因为水平有限,对430内核不是很了解,cortex-m0内核也不是很懂。之前用cortex-m0调试没关注到这块,请大神为我解答。这是430TICK ISR函数的注释:但我还是不太明白为什么不能用任务的堆栈呢?
; Notes : 1) The following C pseudo-codedescribes the operations being performed in the code below.;;
Save all the CPU registers;
if (OSIntNesting == 0) {;
OSTCBCur->OSTCBStkPtr =SP;;
SP = OSISRStkPtr; /* Use the ISR stack from now on */;
};
OSIntNesting++;;
Enable interrupt nesting; /* Allow nesting of interrupts(if needed) */;
Clear the interrupt source;;
OSTimeTick(); /* Call uC/OS-II'stick handler */;
DISABLE generalinterrupts; /* Must DIbefore calling OSIntExit() */;
OSIntExit();;
if (OSIntNesting == 0) {;
SP =OSTCBHighRdy->OSTCBStkPtr; /*Restore the current task's stack */;
};
Restore the CPU registers;
Return from interrupt.;;
2) ALL ISRs should be writtenlike this!;;
3) You MUST disable generalinterrupts BEFORE you call OSIntExit() because an interrupt ;
COULD occur just asOSIntExit() returns and thus, the new ISR would save the SP of ;
the ISR stack and NOT the SPof the task stack. This of course willmost likely cause;
the code to crash. By disabling interrupts BEFORE OSIntExit(),interrupts would be;
disabled when OSIntExit()would return. This assumes that you areusing OS_CRITICAL_METHOD;
#3 (which is the preferedmethod).;;
4) If you DON'T use a separateISR stack then you don't need to disable general interrupts ;
just before callingOSIntExit(). The pseudo-code for an ISRwould thus look like this:;;
Save all the CPU registers;
if (OSIntNesting == 0) {;
OSTCBCur->OSTCBStkPtr =SP;;
};
OSIntNesting++;;
Enable interrupt nesting; /* Allow nesting of interrupts (ifneeded) */;
Clear the interrupt source;;
OSTimeTick(); /* Call uC/OS-II'stick handler */;
OSIntExit();;
Restore the CPU registers;
Return interrupt.;
0