|
ucos运行于atmega8l,时钟用内部1MHz晶振,系统时钟采用time2比较器,10ms一次中断。
以下是我自己的理解,如果有误,请指出。
ucos的任务调度分为OSCtxSw和OSIntCtxSw
1.正常情况下常情况下 OSTimeDlay调用OS_Sched调用 OSCtxSw
OSCtxSw的过程{PUSHRS, PUSHSREG ,SaveSPToTcb, LoadSPFromTcb,POPSREG,POPSP}
2.如果发生定时比较器中断,则调用OSTickISR{}
OSTickISR{}的过程{PUSHRS,PUSHSREG,OSIntNesting++,OSTimeTick,OSIntExit,POPSREG,POPSP}
OSIntCtxSw的过程{LoadSPFromTcb,POPSREG,POPSP}
我不解的地方就在2处。OSTickISR中在PUSHSREG后是否需要SaveSPToTcb。
按照流程,任务1在OSTickISR中,PUSHRS,PUSHSREG后,堆栈指针的位置为SP1,而此时TCB里的位置为上次任务保存的SP0,然后所有delaytime都减1,然后,OSIntExit 第一种情况:如果最高优先级还是当前任务的话,则直接返回SP1处,寄存器出栈。这个应该没有问题。
第二种情况:如果最高优先级不是当前任务的话,则调用OSIntCtxSw,此时SP的值为任务2的SP3,当新任务运行完后,再次调用任务1时,从TCB里面读取的值应该是SP0,而不是SP1,应该发生错误。
但是试验下来不管时候保存SP1,系统都能正常运行
请各位老师,高手赐教 O(∩_∩)O
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
我的相关代码
********************************************************************************************************
OSCtxSw:
PUSHRS ; Save current tasks context
PUSHSREG
LDS R30,OSTCBCur ; Z = OSTCBCur->OSTCBStkPtr
LDS R31,OSTCBCur+1 ;
IN r28,_SFR_IO_ADDR(SPL)
ST Z+,R28 ; Save Y (R29:R28) pointer
IN r29,_SFR_IO_ADDR(SPH)
ST Z+,R29 ;
LDS R16,OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy
STS OSPrioCur,R16
LDS R30,OSTCBHighRdy ; Let Z point to TCB of highest priority task
LDS R31,OSTCBHighRdy+1 ; ready to run
STS OSTCBCur,R30 ; OSTCBCur = OSTCBHighRdy
STS OSTCBCur+1,R31 ;
LD R28,Z+ ; Restore Y pointer
OUT _SFR_IO_ADDR(SPL),R28
LD R29,Z+ ;
OUT _SFR_IO_ADDR(SPH),R29
POPSREG
POPRS ; Restore all registers and the status register
RET
;*********************************************************************************************************
; INTERRUPT LEVEL CONTEXT SWITCH
;*********************************************************************************************************
OSIntCtxSw:
LDS R16,OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy
STS OSPrioCur,R16 ;
LDS R30,OSTCBHighRdy ; Z = OSTCBHighRdy->OSTCBStkPtr
LDS R31,OSTCBHighRdy+1 ;
STS OSTCBCur,R30 ; OSTCBCur = OSTCBHighRdy
STS OSTCBCur+1,R31 ;
LD R28,Z+ ; Restore Y pointer
OUT _SFR_IO_ADDR(SPL),R28
LD R29,Z+ ;
OUT _SFR_IO_ADDR(SPH),R29
POPSREG
POPRS ; Restore all registers and status register
RET
;********************************************************************************************************
; SYSTEM TICK ISR
;
; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred.
;********************************************************************************************************
OSTickISR:
SEI
PUSHRS ; Save all registers and status register
PUSHSREG
;-------------------------------------------------------------------------------------------------
;试验中, 这一保存SP的指令加不加都一样
; LDS R30,OSTCBCur ; Z = OSTCBCur->OSTCBStkPtr
; LDS R31,OSTCBCur+1 ;
; IN r28,_SFR_IO_ADDR(SPL)
; ST Z+,R28 ; Save Y (R29:R28) pointer
; IN r29,_SFR_IO_ADDR(SPH)
; ST Z+,R29
;-------------------------------------------------------------------------------------------------
LDS R16,OSIntNesting ; Notify uC/OS-II of ISR
INC R16 ;
STS OSIntNesting,R16 ;
RCALL OSTimeTick ; Call uC/OS-IIs tick updating function
RCALL OSIntExit ; Notify uC/OS-II about end of ISR
POPSREG
POPRS ; Restore all registers and status register
RET
;*********************************************************************************************
void OSTimeTick (void)
{
OS_TCB *ptcb;
if (OSRunning == OS_TRUE)
{
ptcb = OSTCBList;
while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO)
{
OS_ENTER_CRITICAL();
if (ptcb->OSTCBDly != 0)
{
if (--ptcb->OSTCBDly == 0)
{
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY)
{
OSRdyGrp|= ptcb->OSTCBBitY; OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
}
else
{
ptcb->OSTCBDly=1;
}
}
}
ptcb = ptcb->OSTCBNext; /* Point at next TCB in TCB list */
OS_EXIT_CRITICAL();
}
}
}
********************************************************************************************************************
void OSIntExit (void)
{
OS_ENTER_CRITICAL();
if (OSIntNesting > 0) { /* Prevent OSIntNesting from wrapping */
OSIntNesting--;
}
if (OSIntNesting == 0) { /* Reschedule only if all ISRs complete ... */
if (OSLockNesting == 0) { /* ... and not locked. */
OS_SchedNew();
if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
OSCtxSwCtr++; /* Keep track of the number of ctx switches */
OSIntCtxSw(); /* Perform interrupt level ctx switch */
}
}
}
OS_EXIT_CRITICAL();
} |
阿莫论坛20周年了!感谢大家的支持与爱护!!
一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
|