常见任务格式
//每个任务都有一个挂起,可以进行任务切换
void Task_LED(void *arg)
{
(void)arg; // 'arg' 并没有用到,防止编译器提示警告
while (1)
{
//用户实现功能代码
OSTimeDlyHMSM(0, 0,0,1000); //任务挂起 实现任务切换
}
}
OSTimeDlyHMSM 时间延时 计数计算函数
// 延时时间计算 调用延时函数
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);
}
OSTimeDly()时间延时函数
// 延时函数 将本任务从就绪列表中清除,让后调用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(); /* 系统调度 */
}
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();
OSCtxSw 任务切换 汇编代码
//这里主要是为了产生 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
时间切换
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();
}
}
}
时钟源 硬件时间中断提供
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();
}