UCGUI 联系客服

发布时间 : 星期一 文章UCGUI更新完毕开始阅读40228020aaea998fcd220e05

的值所对应的地址,找到它保存的SP值,该值对应的是存储PU寄存器的堆栈区,根据这个堆栈区的值,可以看到保存的X,Y,A,B,以及任务函数的首地址是否正确了。在这里,这个地址要指向OS_TaskIdle(),这样在OSStartHighRdy()运行后,程序才能跳转到OS_TaskIdle()运行。

如果没有跳转,则说明OsTaskStkInit()推入堆栈出错了。这时,可以重新单步执行,在空闲任务创建函数OS_InitTaskIdle()加入断点,再单步执行,直到运行到OSTaskStkInit(),进入该函数,观察调试器中的存储器区中对应的堆栈处,是否对CPU寄存器进行了正确的保存,尤其注意任务函数地址的存储。

在我调试过程中,发现任务函数的地址没有被正确的保存,单步执行,发现程序中,任务存储一句有问题,之后加以改正,程序运行正常。 代码如下:

OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) {

INT16U *wstk; INT8U *bstk;

opt = opt; /* 'opt' is not used, prevent warning */ wstk=(INT16U *)ptos /* Load stack pointer */

wstk=(INT16U)p_arg;/* Simulate call to function with argument */ 原程序出错处

//*--wstk = (INT16U)(((INT32U)task) >> 8); /* Put task return address on top of stack */

//*--wstk = (INT16U)(((INT32U)task) >> 8); /* Put task return address on top of stack */ 修改后

*--wstk = (INT16U)((INT32U)task); /* Return address of simulated call。 Format: PCH:PCL */

*--wstk=(INT16U)0x2222; /* Y Register */

20

*--wstk=(INT16U)0x1111; /* X Register */ *--wstk=(INT16U)0xBBAA; /* D Register */

*--wstk = (INT16U)0x0080; /* CCR: Disable STOP, Int。 Level = 0。 User Mode */

bstk = (INT8U *)wstk; /* Convert WORD ptr to BYTE ptr to set CCR */

*--bstk = *(INT8U *)0x10;/* Save the GPAGE register */ *--bstk = *(INT8U *)0x17;/* Save the EPAGE register */ *--bstk = *(INT8U *)0x16;/* Save the RPAGE register */

*--bstk = (INT8U )task;/* Save the task's PPAGE register value*/ return ((OS_STK *)bstk);/* Return pointer to new top-of-stack */ }

2 验证OSCtxSw()函数

在已经知道OSTaskStkInit函数正确后,就可以在程序中加入一个任务,并不断的切换到空闲任务。这里是使用的软中断swi来调用OSCtxSw函数的。(必须保证程序中的中断向量表中swi中断向量的地址已经链接到了OSCtxSw函数上) 代码如下:

#define TASK_STK_SIZE 1024

OS_STK TaskStartStk[TASK_STK_SIZE]; /* 定义任务堆栈 */ INT8U err;

TASKDATA TaskStartData; TASKDATA *pdata;

void TaskStart(TASKDATA *pdata); void main(void) {

Init_Settings();

TaskStartData。PPAGE1 = 0xFE; DisableInterrupts;

21

OSInit();

OSTaskCreateExt(TaskStart,

(void *)&TaskStartData, /* Arguments passed to TaskStart() */ (void *)&TaskStartStk[TASK_STK_SIZE-1], /* Set Top-Of-Stack */

9, /* Lowest priority level */ 0, /* Task ID,no use */ &TaskStartStk[0], /* Set Bottom-Of-Stack */ TASK_STK_SIZE,

(void *)0, /* No TCB extension */ OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking and clear stack */ OSStart(); }

void TaskStart(TASKDATA *pdata) {

pdata = pdata; while(1) {

OSTimeDly(1); } }

在任务TaskStart中只有一个OSTimeDly(1),因为没有允许中断,也没有打开时钟节拍,所以OSTimeDly(1)不会返回到TaskStart。

单步执行进入OSTimeDly函数,它接着调用OS_Sched(),如果中断向量表正确,则会再调用OSCtxSw(),在该函数返回后,应该进入OS_TaskIdle()。 3 验证OSIntCtxSw()和OSTickISR()函数

在测试之前,需要保证时钟中断向量指向了时钟节拍中断服务子程序OSTickISR(),然后必须在第一个任务出,初始化时钟并开中断,绝对不能在

22

OSStart()之前开启时钟中断。 代码如下:

#define TASK_STK_SIZE 1024

OS_STK TaskStartStk[TASK_STK_SIZE]; /* 定义任务堆栈 */ OS_STK Task1Stk[TASK_STK_SIZE]; INT8U err;

TASKDATA TaskStartData; TASKDATA Task1Data; TASKDATA *pdata;

void TaskStart(TASKDATA *pdata); void Task1(TASKDATA *pdata); void main(void) {

Init_Settings();

TaskStartData。PPAGE1 = 0xFE; Task1Data。PPAGE1 = 0xFE; DisableInterrupts;

OSInit();

OSTaskCreateExt(TaskStart,

(void *)&TaskStartData, /* Arguments passed to TaskStart() */ (void *)&TaskStartStk[TASK_STK_SIZE-1], /* Set Top-Of-Stack */ 9, /* Lowest priority level */ 0, /* Task ID,no use */ &TaskStartStk[0], /* Set Bottom-Of-Stack */ TASK_STK_SIZE,

23