Ucos源码分析
1.Ucos源码分析------任务控制块与任务调度
2.Ucos源码分析------事件控制块与事件控制
3.Ucos源码分析------信号量
4.Ucos源码分析------邮箱与队列
5.Ucos源码分析------事件标志组
6.Ucos源码分析------内存管理
7.Ucos源码分析------临界区与中断管理
8.Ucos源码分析------OS启动
9.Ucos总结
必须在调用OSStart()函数之前调用OSInit(),而只有在调用OSStart()函数之后,UCOS才真正开始运行多任务。
int main(void)
{
//系统初始化
OSInit();
//创建主任务
OSTaskCreate(MainTask, (void *)0, &MainTask_Stk[MainTask_StkSize-1], MainTask_Prio);
// 开始任务调度
OSStart();
return 0;
}
1.OS初始化
1.1 OSInt()
void OSInit (void)
{
//钩子函数,初始化开始前的
#if OS_VERSION >= 204
OSInitHookBegin(); /* Call port specific initialization code */
#endif
//初始化一些全局变量
OS_InitMisc(); /* Initialize miscellaneous variables */
//就绪表初始化
OS_InitRdyList(); /* Initialize the Ready List */
//初始化 空任务控制块链表
OS_InitTCBList(); /* Initialize the free list of OS_TCBs */
//初始化 空事件控制块链表
OS_InitEventList(); /* Initialize the free list of OS_EVENTs */
//OS_MAX_FLAGS 最大任务事件标注组事件数目
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
OS_FlagInit(); /* Initialize the event flag structures */
#endif
//OS_MAX_MEM_PART 最大内存控制块数目
#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
OS_MemInit(); /* Initialize the memory manager */
#endif
//OS_MAX_QS 最大队列事件数目
#if (OS_Q_EN > 0) && (OS_MAX_QS > 0)
OS_QInit(); /* Initialize the message queue structures */
#endif
//初始化空闲任务
OS_InitTaskIdle(); /* Create the Idle Task */
#if OS_TASK_STAT_EN > 0
OS_InitTaskStat(); /* Create the Statistic Task */
#endif
//钩子函数,初始化结束后的
#if OS_VERSION >= 204
OSInitHookEnd(); /* Call port specific init. code */
#endif
}
1.2系统中全局变量的初始化
因为Ucos是不允许创建相同的任务优先级的,所以在系统调度中OS_Sched(),获取了当前就绪表OSRdyGrp[]中最高优先级任务的优先级,通过任务优先级表OSTCBPrioTbl[ ]能很快获得任务控制块。
1.3系统中空闲控制链表的初始化
2.任务的创建
INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio)
参数
task:任务函数指针
pdata:向任务传递参数
ptos:指向任务栈顶的指针,OS_STK_GROWTH设置为1,栈被认为是向下增长
prio:任务优先级
INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_STK *psp;
INT8U err;
#if OS_ARG_CHK_EN > 0
if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */
return (OS_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
//防止其他任务创建相同优先级的任务
if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority */
OSTCBPrioTbl[prio] = (OS_TCB *)1; /* Reserve the priority to prevent others from doing ... */
/* ... the same thing until task is created. */
OS_EXIT_CRITICAL();
//任务堆栈初始化
// R0-R12的初始化 指定LR返回地址为Task
psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, 0); /* Initialize the task's stack */
// 任务控制块的初始化
err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);
//如果成功创建任务控制块
if (err == OS_NO_ERR) {
OS_ENTER_CRITICAL();
// 创建的任务数目+1
OSTaskCtr++; /* Increment the #tasks counter */
OS_EXIT_CRITICAL();
// 系统是否允许状态
if (OSRunning == TRUE) { /* Find highest priority task if multitasking has started */
// 任务调度
OS_Sched();
}
} else {
OS_ENTER_CRITICAL();
// 允许其它该优先级的任务可以创建
OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others */
OS_EXIT_CRITICAL();
}
return (err);
}
OS_EXIT_CRITICAL();
return (OS_PRIO_EXIST);
}
INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U )
用户不能调用
INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_TCB *ptcb;
OS_ENTER_CRITICAL();
// 获取空闲任务控制块链表 表头指针对应的任务控制块
ptcb = OSTCBFreeList; /* Get a free TCB from the free TCB list */
//是否成功获取任务控制块(空闲任务控制块链表 是否是最后一个)
if (ptcb != (OS_TCB *)0) {
// 空闲任务控制块链表 表头指针 后移
OSTCBFreeList = ptcb->OSTCBNext; /* Update pointer to free TCB list */
OS_EXIT_CRITICAL();
// 任务控制块初始话
ptcb->OSTCBStkPtr = ptos; /* Load Stack pointer in TCB */
ptcb->OSTCBPrio = (INT8U)prio; /* Load task priority into TCB */
ptcb->OSTCBStat = OS_STAT_RDY; /* Task is ready to run */
ptcb->OSTCBDly = 0; /* Task is not delayed */
#if OS_TASK_CREATE_EXT_EN > 0
ptcb->OSTCBExtPtr = pext; /* Store pointer to TCB extension */
ptcb->OSTCBStkSize = stk_size; /* Store stack size */
ptcb->OSTCBStkBottom = pbos; /* Store pointer to bottom of stack */
ptcb->OSTCBOpt = opt; /* Store task options */
ptcb->OSTCBId = id; /* Store task ID */
#else
pext = pext; /* Prevent compiler warning if not used */
stk_size = stk_size;
pbos = pbos;
opt = opt;
id = id;
#endif
#if OS_TASK_DEL_EN > 0
ptcb->OSTCBDelReq = OS_NO_ERR;
#endif
// 任务优先级初始化 在这初始化方便后面获取任务优先级
ptcb->OSTCBY = prio >> 3; /* Pre-compute X, Y, BitX and BitY */
ptcb->OSTCBBitY = OSMapTbl[ptcb->OSTCBY];
ptcb->OSTCBX = prio & 0x07;
ptcb->OSTCBBitX = OSMapTbl[ptcb->OSTCBX];
#if OS_EVENT_EN > 0
ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* Task is not pending on an event */
#endif
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0)
ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; /* Task is not pending on an event flag */
#endif
#if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0))
ptcb->OSTCBMsg = (void *)0; /* No message received */
#endif
#if OS_VERSION >= 204
// 创建TCB钩子函数
OSTCBInitHook(ptcb);
#endif
// 新建任务钩子函数
OSTaskCreateHook(ptcb); /* Call user defined hook */
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = ptcb;
// 将当前任务控制块指针 加入任务优先级表
ptcb->OSTCBNext = OSTCBList; /* Link into TCB chain */
ptcb->OSTCBPrev = (OS_TCB *)0;
// 将已用任务控制块 连接成双向表
if (OSTCBList != (OS_TCB *)0) {
OSTCBList->OSTCBPrev = ptcb;
}
// 已用任务控制块链表 表头指向当前新加入的任务
OSTCBList = ptcb;
// 任务就绪组 加入当前新加入的任务
OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */
// 任务就绪表 加入当前新加入的任务
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
OS_EXIT_CRITICAL();
return (OS_NO_MORE_TCB);
}
创建一个任务后
3.系统启动 OSStart ()
void OSStart (void)
{
INT8U y;
INT8U x;
// 系统运行状态判断
if (OSRunning == FALSE) {
// 获取任务优先级最高的任务
y = OSUnMapTbl[OSRdyGrp]; /* Find highest priority's task priority number */
x = OSUnMapTbl[OSRdyTbl[y]];
OSPrioHighRdy = (INT8U)((y << 3) + x);
// 因为系统刚启动,所以任务优先级最高的任务优先级 就是现在运行的任务优先级
OSPrioCur = OSPrioHighRdy;
// 从任务优先级表 获取任务优先级最高的任务
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run */
// 因为系统刚启动,所以任务优先级最高的任务 就是现在运行的任务
OSTCBCur = OSTCBHighRdy;
// 用户的钩子函数
OSStartHighRdy(); /* Execute target specific code to start task */
}
}