一、系统任务
UCOSIII默认有5个系统任务:
1、空闲任务:UCOSIII创建的第一个任务,UCOSIII必须创建的任务,此任务有UCOSIII自动创建,不需要用户手动创建。
2、时钟节拍任务:此任务也是必须创建的任务。遍历所有在等待延时结束或指定时间内等待某个内核对象的任务,及遍历节拍列表。
① 插入节拍列表:
dly 为要延时或等待的时间;
MatchValue = OSTickCtr +dly
节拍列表下标 = MatchValue %表格长度
该表是一个环形表,取模运算时一表格长度为模,将任务插入节拍列表中,在同一下标下按照延时或等待的时间长短排序。
② 每个节拍中断都会给此任务一个信号让其执行,通过对OSTickCtr求模(同上),找到对应的位置,与.TickCtrMatch比较是否相同,若相同就把相应的OS_TCB从时钟列表中删除,如果是等待延时,会把它放入就绪列表中;如果是等待某一事件,还需要将其从等待列表中删除;接着继续一本下标的下一个任务控制块比较。若不同则结束返回函数。
3、统计任务:可选任务,用来统计CPU使用率和各个任务的堆栈使用量。此任务是可选任务,由宏OS_CFG_STAT_TASK_EN控制是否使用此任务。可以统计CPU利用率
4、定时任务:用来向用户提供定时服务,也是可选任务,由宏OS_CFG_TMR_EN控制是否使用此任务。计时减到零会调用回调函数进行一系列操作。
5、中断服务管理任务:可选任务,由宏OS_CFG_ISR_POST_DEFERRED_EN控制是否使用此任务。当ISR调用UCOS_III中的“post”函数,要发送数据的副本和发送的目的地都会存入一个特别的缓冲队列中,当ISR执行完毕后,任务切换到中断服务管理任务,该任务会把存放的信息重发给相应的任务。做额外的这一步可以减少中断关闭的时间;否则,在ISR中还需要把任务从等待列表中删除,并把任务放在就绪表中,以及一些耗时的操作。
二、任务状态
从用户的角度看,UCOSIII的任务一共有5种状态:
1、休眠态:任务已经在CPU的flash中了,但是还不受UCOSIII管理。当任务被创建后会接受ucosiii的管理,当不再需要ucosiii的管理时将自身删除(调用函数OSTaskDel()),并没有删除此任务代码,而是使该任务无法获得CPU的使用权。
2、就绪态:系统为任务分配了任务控制块,并且任务已经在就绪表中登记,这时这个任务就具有了运行的条件,此时任务的状态就是就绪态。
3、运行态:任务获得CPU的使用权,正在运行。
4、等待态:正在运行的任务需要等待一段时间,或者等待某个事件,这个任务就进入了等待态,此时系统就会把CPU使用权转交给别的任务。当等待事件发生时,就会被放入就绪列表中,进入就绪态。
5、中断服务态:当发送中断,当前正在运行的任务会被挂起,CPU转而去执行中断服务函数,此时任务的任务状态叫做中断服务态。一般来说,ISR只是通知任务某个事件已经发生,而事件的处理则交给任务处理。ISR应当尽可能短,中断处理的大部分工作应当在UCOS_III可管理的任务级来做。ISR仅允许调用与Post()相关的这一类函数。
三、之间转换
1、任务在调用延时函数时,会将自身挂起,延时等待一段时间结束后会返回就绪态。
2、一个任务在等待一个事件的发生,如果没有时间限制会一直等下去,直到事件发生或等待的事件被删除,或者其他决定任务中止该等待过程;
3、一个任务在指定的一段时间内等待一个事件的发生,如果在这段时间内事件未发生就会进入就绪态且该任务会被通知等待超时。另外如果事件发生或等待的事件被删除,或者其他决定任务中止该等待过程,该等待过程结束。
四、任务控制块
(嵌入式实时操作系统UCOSIII P64)
struct os_tqcb {
CPU_STK *StkPtr; //指针变量,指向自身堆栈的栈顶,便于汇编代码访问
void *ExtPtr;//指向用户可定义的数据区,根据需要扩展TCB,如保存浮点运算器的运行环境。
CPU_STK *StkLimitPtr;//堆栈中的某个位置,设置堆栈眼神的限制位置,方便溢出检测
OS_TCB *NextPtr;
OS_TCB *PrevPtr;//任务就绪列表中双向链表的前后指针
OS_TCB *TickNextPtr;//
OS_TCB *TickPrevPtr;//正在延时或在指定时间内等待某个时间的任务的OS_TCB构成双向链表
OS_TICK_SPOKE *TickSpokePtr;//指的是该任务挂在时钟节拍的拿一根辐条上????
CPU_CHAR *NamePtr;//任务的名字
CPU_STK *StkBasePtr;//指向任务堆栈的基地址。永远是&MyTaskStk[0];
OS_TASK_PTR TaskEntryAddr;//任务代码的入口地址
void *TaskEntryArg;//包含了创建时传递给任务的参数的数值,p_arg值
OS_PEND_DATA *PendDataTblPtr; //UCOSIII允许任务挂在任意数目的信号量或消息队列上,它指向一个表,包含了任务等待的所有事件的信息
OS_STATE PendOn; /* 表示任务正在等待的事件的类型
必须是以下值:
OS_TASK_PEND_ON_NOTHING //Pending on nothing
OS_TASK_PEND_ON_FLAG //Pending on event flag group
OS_TASK_PEND_ON_TASK_Q // Pending on message to be sent to task
OS_TASK_PEND_ON_MULTI //Pendingon multiple semaphores and/or queues
OS_TASK_PEND_ON_MUTEX //Pendingon mutual exclusion semaphore
OS_TASK_PEND_ON_Q //Pending on queue
OS_TASK_PEND_ON_SEM //Pending on semaphore
OS_TASK_PEND_ON_TASK_SEM //Pending on signal to be sent to task
*/
OS_STATUS PendStatus;//表示等待的结果
OS_STATE TaskState;
OS_PRIO Prio;
CPU_STK_SIZE StkSize;
OS_OPT Opt;
OS_OBJ_QTY PendDataTblEntries;
CPU_TS TS;
OS_SEM_CTR SemCtr;
OS_TICK TickCtrPrev;
OS_TICK TickCtrMatch;
OS_TICK TickRemain;
OS_TICK TimeQuanta;
OS_TICK TimeQuantaCtr;
#if OS_MSG_EN > 0u
void *MsgPtr;
OS_MSG_SIZE MsgSize;
#endif
#if OS_CFG_TASK_Q_EN > 0u
OS_MSG_Q MsgQ;
#if OS_CFG_TASK_PROFILE_EN > 0u
CPU_TS MsgQPendTime;
CPU_TS MsgQPendTimeMax;
#endif
#endif
#if OS_CFG_TASK_REG_TBL_SIZE > 0u
OS_REG RegTbl[OS_CFG_TASK_REG_TBL_SIZE];
#endif
#if OS_CFG_FLAG_EN > 0u
OS_FLAGS FlagsPend;
OS_FLAGS FlagsRdy;
OS_OPT FlagsOpt;
#endif
#if OS_CFG_TASK_SUSPEND_EN > 0u
OS_NESTING_CTR SuspendCtr;
#endif
#if OS_CFG_TASK_PROFILE_EN > 0u
OS_CPU_USAGE CPUUsage;
OS_CPU_USAGE CPUUsageMax;
OS_CTX_SW_CTR CtxSwCtr;
CPU_TS CyclesDelta;
CPU_TS CyclesStart;
OS_CYCLES CyclesTotal;
OS_CYCLES CyclesTotalPrev;
CPU_TS SemPendTime;
CPU_TS SemPendTimeMax;
#endif
#if OS_CFG_STAT_TASK_STK_CHK_EN > 0u
CPU_STK_SIZE StkUsed;
CPU_STK_SIZE StkFree;
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN
CPU_TS IntDisTimeMax;
#endif
#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
CPU_TS SchedLockTimeMax;
#endif
#if OS_CFG_DBG_EN > 0u
OS_TCB *DbgPrevPtr;
OS_TCB *DbgNextPtr;
CPU_CHAR *DbgNamePtr;
#endif
};
我所存在的疑惑1、SemCtr表示意义 2、MsgQ表示意义 有清楚的请告知 谢谢!!