ucos 的疑问
我按照网上的方法自己移植了个ucos2.92版本的void Task1(void *ppdata)
{
ppdata = ppdata;
for(;;)
{
LED0 = ~LED0;
OSTimeDly(OS_TICKS_PER_SEC);
}
}
void Task2(void *ppdata)
{
ppdata = ppdata;
for(;;)
{
LED1=~LED1;
OSTimeDly(OS_TICKS_PER_SEC*2);
}
}
int main()
{
CKCON = 0x38;
Uart0_Init();
OSInit();
OSTaskCreate (Task1,(void *)0,&TaskStk,0);
OSTaskCreate (Task2,(void *)0,&TaskStk,1);
OSStart();
return 0;
}
我的问题是当task2运行到LED1=~LED1;
时发生了定时中断
执行
OSTickISR:
USING 0
CLREA
PUSHALL
LCALL _?OSIntEnter
CLRTR0
MOVTH0,#0E0H
MOVTL0,#0C0H
SETB TR0
MOV WATCH,#0A1H
LCALL _?OSTimeTick
LCALL _?OSIntExit
POPALL
RETI
在定时中断里OSIntEnter ()--》OSTimeTick--》OSIntExit--》
voidOSIntExit (void) reentrant
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SRcpu_sr = 0u;
#endif
if (OSRunning == OS_TRUE) {
OS_ENTER_CRITICAL();
if (OSIntNesting > 0u) { /* Prevent OSIntNesting from wrapping */
OSIntNesting--;
}
if (OSIntNesting == 0u) { /* Reschedule only if all ISRs complete ... */
if (OSLockNesting == 0u) { /* ... and not locked. */
OS_SchedNew();
OSTCBHighRdy = OSTCBPrioTbl;
if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */
#if OS_TASK_PROFILE_EN > 0u
OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task*/
#endif
OSCtxSwCtr++; /* Keep track of the number of ctx switches */
OSIntCtxSw(); /* Perform interrupt level ctx switch */ }
}
}
OS_EXIT_CRITICAL();
}
}
OSIntCtxSw_in:
MOVA,SP
CLRC
SUBB A,#OSStkStart
MOVR5,A
MOVR0,#LOW (OSTCBCur)
INCR0
MOVDPH,@R0
INCR0
MOVDPL,@R0
INCDPTR
MOVX A,@DPTR
MOVR0,A
INCDPTR
MOVX A,@DPTR
MOVR1,A
MOVDPH,R0
MOVDPL,R1
MOVA,R5
MOVX @DPTR,A
MOVR0,#OSStkStart
save_stack:
INCDPTR
INCR0
MOVA,@R0
MOVX @DPTR,A
DJNZ R5,save_stack
INCDPTR
MOVA,?C_XBP
MOVX @DPTR,A
INCDPTR
MOVA,?C_XBP+1
MOVX @DPTR,A
LCALL _?OSTaskSwHook
MOVR0,#OSTCBCur
MOVR1,#OSTCBHighRdy
MOVA,@R1
MOV@R0,A
INCR0
INCR1
MOVA,@R1
MOV@R0,A
INCR0
INCR1
MOVA,@R1
MOV@R0,A
MOVR0,#OSPrioCur
MOVR1,#OSPrioHighRdy
MOVA,@R1
MOV@R0,A
LJMP OSCtxSw_in
;-------------------------------------------------------------------------
RSEG ?PR?OSIntCtxSw?OS_CPU_A
OSIntCtxSw:
MOVA,SP
CLRC
SUBB A,#4
MOVSP,A
LJMP OSIntCtxSw_in
在保存堆栈时怎么没有保存pc的值到仿真栈中呢?只保存了栈长度 ACC BDPL DPH等
那么在下次轮到task2执行时RETI时怎么返回到LED1=~LED1;的下一行代码接着执行呢
中断发生,程序跳转到ISR时,PC就自动入栈了。执行RETI指令时,栈顶的PC值被弹出。 mitchell 发表于 2014-1-16 14:06
中断发生,程序跳转到ISR时,PC就自动入栈了。执行RETI指令时,栈顶的PC值被弹出。 ...
楼上正解,这是处理器自身具备的功能,自动保存PC mitchell 发表于 2014-1-16 14:06
中断发生,程序跳转到ISR时,PC就自动入栈了。执行RETI指令时,栈顶的PC值被弹出。 ...
那我再保存堆栈的时候,就不用保存pc的值了吧?
如果我在中断中改变sp的值,是不是就有可能当RETI返回时不会 接着运行中断前的下一条代码???
还有当我在中断中调用一个子程序,sp的值如何变化呢?
期盼你的回答,谢谢 king1314 发表于 2014-1-16 14:22
那我再保存堆栈的时候,就不用保存pc的值了吧?
如果我在中断中改变sp的值,是不是就有可能当RETI返回时 ...
那我再保存堆栈的时候,就不用保存pc的值了吧?
——不用。
如果我在中断中改变sp的值,是不是就有可能当RETI返回时不会 接着运行中断前的下一条代码???
——如果保证执行RETI时和进入ISR时的SP值是相同的,就可以接着运行中断前的下一条代码。否则不行。
还有当我在中断中调用一个子程序,sp的值如何变化呢?
——子程序自己会管理堆栈,以保证子程序返回以后和进入之前,SP的值是相同的。 mitchell 发表于 2014-1-16 14:32
那我再保存堆栈的时候,就不用保存pc的值了吧?
——不用。
在程序里有这样一句
?STACK SEGMENT IDATA
RSEG ?STACK
OSStack:
DS 40H
OSStkStart IDATA OSStack-1
定义一个预留的堆栈 且大小是40有什么用处呢?
pop或者push的时候,系统不是会自动分配的吗,
OSStkStart会随着硬件sp的变化而变化吗?? king1314 发表于 2014-1-16 17:45
在程序里有这样一句
?STACK SEGMENT IDATA
RSEG ?STACK
你的问题太基础。建议你仔细研究《微机原理》。 mitchell 发表于 2014-1-17 17:03
你的问题太基础。建议你仔细研究《微机原理》。
谢谢大侠指点,我是转行过来的,所以很多基础的东西不明白
页:
[1]