μC/OSIII学习day4
介绍
支持多优先级,时基列表
# 支持多优先级
数字优先级越小,逻辑优先级越高.
# 优先级相关全局变量
os.h文件中定义了优先级相关的两个全局变量.
OS_EXT OS_PRIO OSPrioCur;//当前优先级
OS_EXT OS_PRIO OSPrioHighRdy;//最高优先级
2
# OSInit()函数
OS中定义的所有的全局变量都是在OSInit()
中初始化的,其中也包括优先级相关的全局变量.
void OSInit (OS_ERR *p_err){
/* 配置 OS 初始状态为停止态 */
OSRunning = OS_STATE_OS_STOPPED;
/* 初始化两个全局 TCB,这两个 TCB 用于任务切换 */
OSTCBCurPtr = (OS_TCB *)0;
OSTCBHighRdyPtr = (OS_TCB *)0;
/* 初始化优先级变量 */
OSPrioCur = (OS_PRIO)0;
OSPrioHighRdy = (OS_PRIO)0;
/* 初始化优先级表 */
OS_PrioInit();
/* 初始化就绪列表 */
OS_RdyListInit();
/* 初始化空闲任务 */
OS_IdleTaskInit(p_err);
if (*p_err != OS_ERR_NONE) {
return;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 任务控制块
优先级Prio
的数据类型为OS_PRIO
,宏展开后是8位的整型,所以只支持255个优先级.
struct os_tcb{
...
//任务优先级
OS_PRIO Prio;
...
}
2
3
4
5
6
# OSTaskCreate()函数
void OSTaskCreate (OS_TCB *p_tcb,
CPU_CHAR *p_name,
OS_TASK_PTR p_task,
void *p_arg,
OS_PRIO prio,
CPU_STK *p_stk_base,
CPU_STK_SIZE stk_limit,
CPU_STK_SIZE stk_size,
OS_MSG_QTY q_size,
OS_TICK time_quanta,
void *p_ext,
OS_OPT opt,
OS_ERR *p_err){
CPU_STK *p_sp;
CPU_SR_ALLOC();
/* 初始化 TCB 为默认值 */
OS_TaskInitTCB(p_tcb);
/* 初始化栈 */
p_sp = OSTaskStkInit( p_task,
p_arg,
p_stk_base,
stk_size );
p_tcb->Prio = prio;
p_tcb->StkPtr = p_sp;
p_tcb->StkSize = stk_size;
/* 进入临界段 */
OS_CRITICAL_ENTER();
/* 将任务添加到就绪列表 */
OS_PrioInsert(p_tcb->Prio);
OS_RdyListInsertTail(p_tcb);
/* 退出临界段 */
OS_CRITICAL_EXIT();
*p_err = OS_ERR_NONE;
}
void OS_TaskInitTCB(OS_TCB *p_tcb){
p_tcb->StkPtr = (CPU_STK *)0;
p_tcb->StkSize = (CPU_STK_SIZE )0u;
p_tcb->TaskDelayTicks = (OS_TICK )0u;
p_tcb->Prio = (OS_PRIO )OS_PRIO_INIT;
p_tcb->NextPtr = (OS_TCB *)0;
p_tcb->PrevPtr = (OS_TCB *)0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
OS_PRIO_INIT
(os.h)是任务TCB初始化的时候给的默认的一个优先级,宏展开等于OS_CFG_PRIO_MAX
,这是一个不会被OS使用到的优先级.
# OS_IdleTaskInit()函数
/* 空闲任务初始化 */
void OS_IdleTaskInit(OS_ERR *p_err){
/* 初始化空闲任务计数器 */
OSIdleTaskCtr = (OS_IDLE_CTR)0;
/* 创建空闲任务 */
OSTaskCreate( (OS_TCB *)&OSIdleTaskTCB,
(OS_TASK_PTR )OS_IdleTask,
(void *)0,
(OS_PRIO)(OS_CFG_PRIO_MAX - 1u),
(CPU_STK *)OSCfg_IdleTaskStkBasePtr,
(CPU_STK_SIZE)OSCfg_IdleTaskStkSize,
(OS_ERR *)p_err );
}
2
3
4
5
6
7
8
9
10
11
12
13
14
空闲任务的优先级最低,为OS_CFG_PRIO_MAX - 1u
# OSStart()函数
/* 启动 RTOS,将不再返回 */
2 void OSStart(OS_ERR *p_err){
if ( OSRunning == OS_STATE_OS_STOPPED ) {
#if 0
/* 手动配置任务 1 先运行 */
OSTCBHighRdyPtr = OSRdyList[0].HeadPtr;
#endif
/* 寻找最高的优先级 */
OSPrioHighRdy = OS_PrioGetHighest();
OSPrioCur = OSPrioHighRdy;
/* 找到最高优先级的 TCB */
OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;
OSTCBCurPtr = OSTCBHighRdyPtr;
/* 标记 OS 开始运行 */
OSRunning = OS_STATE_OS_RUNNING;
/* 启动任务切换,不会返回 */
OSStartHighRdy();
/* 不会运行到这里,运行到这里表示发生了致命的错误 */
*p_err = OS_ERR_FATAL_RETURN;
} else {
*p_err = OS_STATE_OS_RUNNING;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
OS_PrioGetHighest()
函数从全局变量优先级表OSPrioTbl[]
中获取最高的优先级存入OSPrioHighRdy
这个全局变量中,然后再赋值给OSPrioCur
这个全局变量.这两个变量在任务切换的时候需要用到.同样可以找到最高优先级的TCB以供后续使用.
# OS_CPU_PendSVHandler()函数
OS_CPU_PendSVHandler
CPSID I ; Prevent interruption during context switch
MRS R0, PSP ; PSP is process stack pointer
STMFD R0!, {R4-R11} ; Save remaining regs r4-11 on process stack
MOV32 R5, OSTCBCurPtr ; OSTCBCurPtr->OSTCBStkPtr = SP;
LDR R6, [R5]
STR R0, [R6] ; R0 is SP of process being switched out
; At this point, entire context of process has been saved
MOV R4, LR ; Save LR exc_return value
BL OSTaskSwHook ; OSTaskSwHook();
MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy;
MOV32 R1, OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
MOV32 R1, OSTCBHighRdyPtr ; OSTCBCurPtr = OSTCBHighRdyPtr;
LDR R2, [R1]
STR R2, [R5]
ORR LR, R4, #0x04 ; Ensure exception return uses process stack
LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
LDMFD R0!, {R4-R11} ; Restore r4-11 from new process stack
MSR PSP, R0 ; Load PSP with new process SP
CPSIE I
BX LR ; Exception return will restore remaining context
END
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# OSTimeDly()函数
/* 阻塞延时 */
void OSTimeDly(OS_TICK dly){
#if 0
/* 设置延时时间 */
OSTCBCurPtr->TaskDelayTicks = dly;
/* 进行任务调度 */
OSSched();
#endif
CPU_SR_ALLOC();
/* 进入临界区 */
OS_CRITICAL_ENTER();
/* 设置延时时间 */
OSTCBCurPtr->TaskDelayTicks = dly;
/* 从就绪列表中移除 */
//OS_RdyListRemove(OSTCBCurPtr);
OS_PrioRemove(OSTCBCurPtr->Prio);
/* 退出临界区 */
OS_CRITICAL_EXIT();
/* 任务调度 */
OSSched();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
任务处于阻塞态,将任务从就绪列表移除,这里只需将任务在优先级表中对应的位清除即可,暂时不需要把任务TCB从OSRdyList[]
中移除,因为接下来OSTimeTick()
函数还是通过扫描OSRdyList[]
来判断任务的延时时间是否到期.当我们加入了时基列表之后,当任务调用OSTimeDly()
函数进行延时,就可以把任务的TCB从就绪列表删除,然后把任务TCB插入时基列表,OSTimeTick()
函数判断任务的延时是否到期只需通过扫描时基列表即可.所以这里暂时不能把TCB从就绪列表中删除,只是将任务优先级在优先级表中对应的位清除来达到任务不处于就绪态的目的.
# OSSched()函数
根据优先级来调度任务
void OSSched(void){
#if 0
/* 如果当前任务是空闲任务,那么就去尝试执行任务 1 或者任务 2, 5 看看他们的延时时间是否结束,如果任务的延时时间均没有到期,那就返回继续执行空闲任务 */
if ( OSTCBCurPtr == &OSIdleTaskTCB ){
if (OSRdyList[0].HeadPtr->TaskDelayTicks == 0){
OSTCBHighRdyPtr = OSRdyList[0].HeadPtr;
}else if (OSRdyList[1].HeadPtr->TaskDelayTicks == 0){
OSTCBHighRdyPtr = OSRdyList[1].HeadPtr;
}else{
return; /* 任务延时均没有到期则返回,继续执行空闲任务 */
}
}else{
/* 如果是 task1 或者 task2 的话,检查下另外一个任务,
如果另外的任务不在延时中,就切换到该任务,
否则,判断下当前任务是否应该进入延时状态,
如果是的话,就切换到空闲任务.否则就不进行任何切换 */
if (OSTCBCurPtr == OSRdyList[0].HeadPtr){
if (OSRdyList[1].HeadPtr->TaskDelayTicks == 0){
OSTCBHighRdyPtr = OSRdyList[1].HeadPtr;
} else if (OSTCBCurPtr->TaskDelayTicks != 0){
OSTCBHighRdyPtr = &OSIdleTaskTCB;
} else {
/* 返回,不进行切换,因为两个任务都处于延时中 */
return;
}
}else if (OSTCBCurPtr == OSRdyList[1].HeadPtr){
if (OSRdyList[0].HeadPtr->TaskDelayTicks == 0){
OSTCBHighRdyPtr = OSRdyList[0].HeadPtr;
}else if (OSTCBCurPtr->TaskDelayTicks != 0){
OSTCBHighRdyPtr = &OSIdleTaskTCB;
}else{
/* 返回,不进行切换,因为两个任务都处于延时中 */
return;
}
}
}
/* 任务切换 */
OS_TASK_SW();
#endif
CPU_SR_ALLOC();(1)
/* 进入临界区 */
OS_CRITICAL_ENTER();(2)
/* 查找最高优先级的任务 */
OSPrioHighRdy = OS_PrioGetHighest();
OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;
/* 如果最高优先级的任务是当前任务则直接返回,不进行任务切换 */
if (OSTCBHighRdyPtr == OSTCBCurPtr){
/* 退出临界区 */
OS_CRITICAL_EXIT();
return;
}
/* 退出临界区 */
OS_CRITICAL_EXIT();
/* 任务切换 */
OS_TASK_SW();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
判断最高优先级任务是不是当前任务,如果是则直接返回,否则将继续往下执行,最后执行任务切换.
# OSTimeTick()函数
OSTimeTick()
函数在SysTick
中断服务函数中被调用,是一个周期函数,具体用于扫描就绪列表OSRdyList[]
,判断任务的延时时间是否到期,如果到期则将任务在优先级表中对应的位置位.
void OSTimeTick(void){
unsigned int i;
CPU_SR_ALLOC();
/* 进入临界区 */
OS_CRITICAL_ENTER();
/* 扫描就绪列表中所有任务的 TaskDelayTicks,如果不为 0,则减 1 */
#if 0
for (i=0; i<OS_CFG_PRIO_MAX; i++){
if (OSRdyList[i].HeadPtr->TaskDelayTicks > 0){
OSRdyList[i].HeadPtr->TaskDelayTicks --;
}
}
#endif
for (i=0; i<OS_CFG_PRIO_MAX; i++){
if (OSRdyList[i].HeadPtr->TaskDelayTicks > 0){
OSRdyList[i].HeadPtr->TaskDelayTicks --;
if (OSRdyList[i].HeadPtr->TaskDelayTicks == 0){
/* 为 0 则表示延时时间到,让任务就绪 */
//OS_RdyListInsert (OSRdyList[i].HeadPtr);
OS_PrioInsert(i);
}
}
}
/* 退出临界区 */
OS_CRITICAL_EXIT();
/* 任务调度 */
OSSched();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
扫描就绪列表OSRdyList[]
判断任务的延时时间是否到期,如果到期则将任务在优先级表中对应的位置位.
# 时基列表
- 时基列表是跟时间相关的,处于延时的任务和等待事件有超时限制的任务都会从就绪列表中移除,然后插入时基列表.
- 时基列表在
OSTimeTick()
函数中更新.
# μC/OS如何实现时基列表
# 时基列表变量
时基列表在代码层面上由全局数组OSCfg_TickWheel[]
和全局变量OSTickCtr
构成.//这里不对
# 任务控制块TCB
时基列表OSCfg_TickWheel[]
的每个成员都包含一条单向链表,被插入该条链表的TCB会按照延时时间做升序排列.
struct os_tcb{
...
//时基列表相关代码段
OS_TCB *TickNextPtr;
OS_TCB *TickPrevPtr;
OS_TICK_SPOKE *TickSpokePtr;
OS_TICK TickCtrMatch;
OS_TICK TickRemain;
...
}
2
3
4
5
6
7
8
9
10
TickNextPtr
用于指向链表中的下一个TCB节点.TickPrevPtr
用于指向链表中的上一个TCB节点.TickRemain
用于设置任务还需要等待多少个时钟周期,每到来一个时钟周期,该值会递减.TickCtrMatch
的值等于时基计数器OSTickCtr
的值加上TickRemain
的值,当TickCtrMatch
的值等于OSTickCtr
的值的时候,表示等待到期,TCB 会从链表中删除.- 每个被插入链表的TCB都包含一个字段
TickSpokePtr
,用于回指到链表的根部.
# 时列表相关函数
函数名称 | 函数作用 |
---|---|
OS_TickListInit() | 初始化时基列表. |
OS_TickListInsert() | 向时基列表中插入一个任务TCB. |
OS_TickListRemove() | 从时基列表删除一个指定的TCB节点. |
OS_TickListUpdate() | 更新时基计数器OSTickCtr,扫描时基列表中的任务延时是否到期. |
OS_TaskRdy() | 将任务从时基列表删除,插入就绪列表. |
OS_TickListInit()
函数//初始化时基列表的数据域 void OS_TickListInit(void){ OS_TICK_SPOKE_IX i; OS_TICK_SPOKE *p_spoke; for (i = 0u; i < OSCfg_TickWheelSize; i++) { p_spoke = (OS_TICK_SPOKE *)&OSCfg_TickWheel[i]; p_spoke->FirstPtr = (OS_TCB *)0; p_spoke->NbrEntries = (OS_OBJ_QTY )0u; p_spoke->NbrEntriesMax = (OS_OBJ_QTY )0u; } }
1
2
3
4
5
6
7
8
9
10
11
12都初始化为0.
OS_TickListInsert()
函数//将一个任务插入时基列表,根据延时时间的大小升序排列 void OS_TickListInsert(OS_TCB *p_tcb,OS_TICK time){ OS_TICK_SPOKE_IX spoke; OS_TICK_SPOKE *p_spoke; OS_TCB *p_tcb0; OS_TCB *p_tcb1; p_tcb->TickCtrMatch = OSTickCtr + time; p_tcb->TickRemain = time; spoke = (OS_TICK_SPOKE_IX)(p_tcb->TickCtrMatch % OSCfg_TickWheelSize); p_spoke = &OSCfg_TickWheel[spoke]; /* 插入 OSCfg_TickWheel[spoke] 的第一个节点 */ if (p_spoke->NbrEntries == (OS_OBJ_QTY)0u){ p_tcb->TickNextPtr = (OS_TCB *)0; p_tcb->TickPrevPtr = (OS_TCB *)0; p_spoke->FirstPtr = p_tcb; p_spoke->NbrEntries = (OS_OBJ_QTY)1u; } /* 如果插入的不是第一个节点,则按照 TickRemain 大小升序排列 */ else { /* 获取第一个节点指针 */ p_tcb1 = p_spoke->FirstPtr; while (p_tcb1 != (OS_TCB *)0){ /* 计算比较节点的剩余时间 */ p_tcb1->TickRemain = p_tcb1->TickCtrMatch - OSTickCtr; /* 插入比较节点的后面 */ if (p_tcb->TickRemain > p_tcb1->TickRemain){ if (p_tcb1->TickNextPtr != (OS_TCB *)0){ /* 寻找下一个比较节点 */ p_tcb1 = p_tcb1->TickNextPtr; } else { /* 在最后一个节点插入 */ p_tcb->TickNextPtr = (OS_TCB *)0; p_tcb->TickPrevPtr = p_tcb1; p_tcb1->TickNextPtr = p_tcb; p_tcb1 = (OS_TCB *)0; } } else {/* 插入比较节点的前面 */ /* 在第一个节点插入 */ if (p_tcb1->TickPrevPtr == (OS_TCB *)0) { p_tcb->TickPrevPtr = (OS_TCB *)0; p_tcb->TickNextPtr = p_tcb1; p_tcb1->TickPrevPtr = p_tcb; p_spoke->FirstPtr = p_tcb; }else{ /* 插入两个节点之间 */ p_tcb0 = p_tcb1->TickPrevPtr; p_tcb->TickPrevPtr = p_tcb0; p_tcb->TickNextPtr = p_tcb1; p_tcb0->TickNextPtr = p_tcb; p_tcb1->TickPrevPtr = p_tcb; } /* 跳出 while 循环 */ p_tcb1 = (OS_TCB *)0;(8) } } /* 节点成功插入 */ p_spoke->NbrEntries++;(9) } /* 刷新 NbrEntriesMax 的值 */ if (p_spoke->NbrEntriesMax < p_spoke->NbrEntries){ p_spoke->NbrEntriesMax = p_spoke->NbrEntries; } /* 任务 TCB 中的 TickSpokePtr 回指根节点 */ p_tcb->TickSpokePtr = p_spoke;(11) }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72OS_TickListRemove()
函数//从时基列表中移除一个任务 2 void OS_TickListRemove(OS_TCB *p_tcb){ OS_TICK_SPOKE *p_spoke; OS_TCB *p_tcb1; OS_TCB *p_tcb2; /* 获取任务 TCB 所在链表的根指针 */ p_spoke = p_tcb->TickSpokePtr;(1) /* 确保任务在链表中 */ if (p_spoke != (OS_TICK_SPOKE *)0) { /* 将剩余时间清零 */ p_tcb->TickRemain = (OS_TICK)0u; /* 要移除的刚好是第一个节点 */ if (p_spoke->FirstPtr == p_tcb) { /* 更新第一个节点,原来的第一个节点需要被移除 */ p_tcb1 = (OS_TCB *)p_tcb->TickNextPtr; p_spoke->FirstPtr = p_tcb1; if (p_tcb1 != (OS_TCB *)0) { p_tcb1->TickPrevPtr = (OS_TCB *)0; } } else {/* 要移除的不是第一个节点 */ /* 保存要移除的节点的前后节点的指针 */ p_tcb1 = p_tcb->TickPrevPtr; p_tcb2 = p_tcb->TickNextPtr; /* 节点移除,将节点前后的两个节点连接在一起 */ p_tcb1->TickNextPtr = p_tcb2; if (p_tcb2 != (OS_TCB *)0) { p_tcb2->TickPrevPtr = p_tcb1; } } /* 复位任务 TCB 中时基列表相关的字段成员 */ p_tcb->TickNextPtr = (OS_TCB *)0; p_tcb->TickPrevPtr = (OS_TCB *)0; p_tcb->TickSpokePtr = (OS_TICK_SPOKE *)0; p_tcb->TickCtrMatch = (OS_TICK )0u; /* 节点减 1 */ p_spoke->NbrEntries--;(5) } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44OS_TickListUpdate()
函数void OS_TickListUpdate(void){ OS_TICK_SPOKE_IX spoke; OS_TICK_SPOKE *p_spoke; OS_TCB *p_tcb; OS_TCB *p_tcb_next; CPU_BOOLEAN done; CPU_SR_ALLOC(); /* 进入临界段 */ OS_CRITICAL_ENTER(); /* 时基计数器 ++ */ OSTickCtr++; spoke = (OS_TICK_SPOKE_IX)(OSTickCtr % OSCfg_TickWheelSize);(2) p_spoke = &OSCfg_TickWheel[spoke];] p_tcb = p_spoke->FirstPtr; done = DEF_FALSE; while (done == DEF_FALSE) { if (p_tcb != (OS_TCB *)0) { p_tcb_next = p_tcb->TickNextPtr; p_tcb->TickRemain = p_tcb->TickCtrMatch - OSTickCtr; /* 节点延时时间到 */ if (OSTickCtr == p_tcb->TickCtrMatch) { /* 让任务就绪 */ OS_TaskRdy(p_tcb); } else { /* 如果第一个节点延时期未满,则退出 while 循环 因为链表是根据升序排列的,第一个节点延时期未满,那后面的肯定未满 */ done = DEF_TRUE; } /* 如果第一个节点延时期满,则继续遍历链表,看看还有没有延时期满的任务 如果有,则让它就绪 */ p_tcb = p_tcb_next;(7) } else { done = DEF_TRUE;(8) } } /* 退出临界段 */ OS_CRITICAL_EXIT(); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47OS_TaskRdy()
函数//将任务从时基列表删除,插入就列表 void OS_TaskRdy(OS_TCB *p_tcb){ /* 从时基列表删除 */ OS_TickListRemove(p_tcb); /* 插入就绪列表 */ OS_RdyListInsert(p_tcb); }
1
2
3
4
5
6
7
8
# OSTimeDly() 函数
void OSTimeDly(OS_TICK dly){
CPU_SR_ALLOC();
/* 进入临界区 */
OS_CRITICAL_ENTER();
#if 0
/* 设置延时时间 */
OSTCBCurPtr->TaskDelayTicks = dly;
/* 从就绪列表中移除 */
//OS_RdyListRemove(OSTCBCurPtr);
OS_PrioRemove(OSTCBCurPtr->Prio);
#endif
/* 插入时基列表 */
OS_TickListInsert(OSTCBCurPtr, dly);
/* 从就绪列表移除 */
OS_RdyListRemove(OSTCBCurPtr);
/* 退出临界区 */
OS_CRITICAL_EXIT();
/* 任务调度 */
OSSched();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# OSTimeTick() 函数
void OSTimeTick(void){
#if 0
unsigned int i;
CPU_SR_ALLOC();
/* 进入临界区 */
OS_CRITICAL_ENTER();
for (i=0; i<OS_CFG_PRIO_MAX; i++) {
if (OSRdyList[i].HeadPtr->TaskDelayTicks > 0) {
OSRdyList[i].HeadPtr->TaskDelayTicks --;
if (OSRdyList[i].HeadPtr->TaskDelayTicks == 0) {
/* 为 0 则表示延时时间到,让任务就绪 */
//OS_RdyListInsert (OSRdyList[i].HeadPtr);
OS_PrioInsert(i);
}
}
}
/* 退出临界区 */
OS_CRITICAL_EXIT();
#endif
/* 更新时基列表 */
OS_TickListUpdate();
/* 任务调度 */
OSSched();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31