常见任务格式函数
//每一个任务都有一个挂起,能够进行任务切换 void Task_LED(void *arg) { (void)arg; // 'arg' 并无用到,防止编译器提示警告 while (1) { //用户实现功能代码 OSTimeDlyHMSM(0, 0,0,1000); //任务挂起 实现任务切换 } }
// 延时时间计算 调用延时函数 INT8U OSTimeDlyHMSM (INT8U hours, //小时 INT8U minutes, //分钟 INT8U seconds, //秒 INT16U ms) //毫秒 { INT32U ticks; if (OSIntNesting > 0u) { /* 是否在中断See if trying to call from an ISR */ return (OS_ERR_TIME_DLY_ISR); } if (OSLockNesting > 0u) { /* 查看是否调度被锁See if called with scheduler locked */ return (OS_ERR_SCHED_LOCKED); } #if OS_ARG_CHK_EN > 0u if (hours == 0u) { //延时时间是否0 if (minutes == 0u) { if (seconds == 0u) { if (ms == 0u) { return (OS_ERR_TIME_ZERO_DLY); } } } } if (minutes > 59u) { return (OS_ERR_TIME_INVALID_MINUTES); /* 判断时间范围是否正确 */ } if (seconds > 59u) { return (OS_ERR_TIME_INVALID_SECONDS); } if (ms > 999u) { return (OS_ERR_TIME_INVALID_MS); } #endif //计算 延时的ms数 ticks = ((INT32U)hours * 3600uL + (INT32U)minutes * 60uL + (INT32U)seconds) * OS_TICKS_PER_SEC + OS_TICKS_PER_SEC * ((INT32U)ms + 500uL / OS_TICKS_PER_SEC) / 1000uL; //上面多了0.5ms为任务调度须要的时间 OSTimeDly(ticks); //延时函数 return (OS_ERR_NONE); }
// 延时函数 将本任务从就绪列表中清除,让后调用OS_Sched()从就绪表中找到最高级任务运行 void OSTimeDly (INT32U ticks) { INT8U y; #if OS_CRITICAL_METHOD == 3u /* 中断模式3 */ OS_CPU_SR cpu_sr = 0u; #endif if (OSIntNesting > 0u) { /* See if trying to call from an ISR 是否嵌套中断 */ return; } if (OSLockNesting > 0u) { /* See if called with scheduler locked 是否调度锁 */ return; } if (ticks > 0u) { /* 0 means no delay! */ OS_ENTER_CRITICAL(); //把OSRdyTbl清零 y = OSTCBCur->OSTCBY; OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX; //把OSRdyGrp清零:即去掉当前任务放到准备任务中 if (OSRdyTbl[y] == 0u) { OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY; } OSTCBCur->OSTCBDly = ticks; /* Load ticks in TCB */ OS_EXIT_CRITICAL(); OS_Sched(); /* 系统调度 */ }
void OS_Sched (void) { #if OS_CRITICAL_METHOD == 3u OS_CPU_SR cpu_sr = 0u; #endif OS_ENTER_CRITICAL(); if (OSIntNesting == 0u) { //是否中断嵌套 调度锁 if (OSLockNesting == 0u) { OS_SchedNew(); //找到最高级优先级 详解见 http://my.oschina.net/u/274829/blog/263287 OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; if (OSPrioHighRdy != OSPrioCur) { /* 最高级任务 不是当前任务 */ #if OS_TASK_PROFILE_EN > 0u OSTCBHighRdy->OSTCBCtxSwCtr++; /* 当前任务调度次数 */ #endif OSCtxSwCtr++; /*任务切换次数 Increment context switch counter */ OS_TASK_SW(); /* 任务切换 */ } } } OS_EXIT_CRITICAL();
//这里主要是为了产生 PendSV中断 任务切换在 PendSV_Handler 中进行切换 OSCtxSw PUSH {R4, R5} ;将R4,R5入栈 LDR R4, =NVIC_INT_CTRL ;触发PendSV异常 (causes context switch) LDR R5, =NVIC_PENDSVSET STR R5, [R4] ;产生软中断 POP {R4, R5} BX LR ;跳到原地址
任务切换详细过程PendSV_Handler 见http://my.oschina.net/u/274829/blog/266098 spa
时间切换 .net
void OSTimeTick (void) { OS_TCB *ptcb; #if OS_TICK_STEP_EN > 0u BOOLEAN step; #endif #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif #if OS_TIME_TICK_HOOK_EN > 0u OSTimeTickHook(); /* Call user definable hook */ #endif #if OS_TIME_GET_SET_EN > 0u OS_ENTER_CRITICAL(); OSTime++; //系统时间增长 OS_EXIT_CRITICAL(); #endif if (OSRunning == OS_TRUE) { #if OS_TICK_STEP_EN > 0u switch (OSTickStepState) { /* Determine whether we need to process a tick */ case OS_TICK_STEP_DIS: /* Yes, stepping is disabled */ step = OS_TRUE; break; case OS_TICK_STEP_WAIT: /* No, waiting for uC/OS-View to set ... */ step = OS_FALSE; /* .. OSTickStepState to OS_TICK_STEP_ONCE */ break; case OS_TICK_STEP_ONCE: /* Yes, process tick once and wait for next ... */ step = OS_TRUE; /* ... step command from uC/OS-View */ OSTickStepState = OS_TICK_STEP_WAIT; break; default: /* Invalid case, correct situation */ step = OS_TRUE; OSTickStepState = OS_TICK_STEP_DIS; break; } if (step == OS_FALSE) { /* Return if waiting for step command */ return; } #endif ptcb = OSTCBList; /* Point at first TCB in TCB list */ while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) { /* Go through all TCBs in TCB list */ OS_ENTER_CRITICAL(); if (ptcb->OSTCBDly != 0u) { /* No, Delayed or waiting for event with TO */ ptcb->OSTCBDly--; /* Decrement nbr of ticks to end of delay */ if (ptcb->OSTCBDly == 0u) { /* Check for timeout */ if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) { ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_PEND_ANY; //清除事件标志 ptcb->OSTCBStatPend = OS_STAT_PEND_TO; /*时间超时 标志 */ } else { ptcb->OSTCBStatPend = OS_STAT_PEND_OK; } if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { /*准备好了 */ OSRdyGrp |= ptcb->OSTCBBitY; //加到就绪队列 OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; } } } ptcb = ptcb->OSTCBNext; /* Point at next TCB in TCB list */ OS_EXIT_CRITICAL(); } } }
时钟源 硬件时间中断提供code
void OSTickHandler (void) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr; #endif OS_ENTER_CRITICAL(); OSIntNesting++; OS_EXIT_CRITICAL(); OSTimeTick(); /* uC/OS-II's OSTimeTick()*/ OSIntExit(); }