UCOS的任务管理
任务控制块及其初始化 学过操作操作系统的朋友都应该熟悉进程控制块这个概念,这几乎已经成为了我们抽象在操作系统中运行任务的一个统一标准,而这里的任务控制块和进程控制块其实是一个概念。在$\mu$C/OS-$\amalg$中,设计了如下数据结构来对其中运行的任务进行抽象和管理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 typedef struct os_tcb { OS_STK *OSTCBStkPtr; /* Pointer to current top of stack */ ... struct os_tcb *OSTCBNext; /* Pointer to next TCB in the TCB list */ struct os_tcb *OSTCBPrev; /* Pointer to previous TCB in the TCB list */ ... INT32U OSTCBDly; /* Nbr ticks to delay task or, timeout waiting for event */ INT8U OSTCBStat; /* Task status */ INT8U OSTCBStatPend; /* Task PEND status */ INT8U OSTCBPrio; /* Task priority (0 == highest) */ INT8U OSTCBX; /* Bit position in group corresponding to task priority */ INT8U OSTCBY; /* Index into ready table corresponding to task priority */ OS_PRIO OSTCBBitX; /* Bit mask to access bit position in ready table */ OS_PRIO OSTCBBitY; /* Bit mask to access bit position in ready group */ ... } OS_TCB;
从如上数据结构,我们容易看出,TCB主要描述了如下几方面的信息:
堆栈
任务状态
任务优先级相关
这些信息是任务运行不可或缺的,同时又包含了TCB本身的组织结构和一些其他功能相关的信息。不像在复杂操作系统中那样,任务与任务之间只存在对等关系,不存在父子,兄弟等复杂的关系,而且功能复杂度也简单的多,因此在$\mu$C/OS-$\amalg$的TCB结构相对复杂操作系统的PCB来说简单得多。
对于任务控制块的初始化函数如下所示。
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 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 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 OS_CPU_SR cpu_sr; #endif OS_TCB *ptcb; #if OS_TASK_REG_TBL_SIZE > 0u INT8U i; #endif #if OS_TASK_CREATE_EXT_EN > 0u #if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) INT8U j; #endif #endif OS_ENTER_CRITICAL(); ptcb = OSTCBFreeList; (1) if (ptcb != (OS_TCB *)0) { (2) OSTCBFreeList = ptcb->OSTCBNext; OS_EXIT_CRITICAL(); ptcb->OSTCBStkPtr = ptos; (3) ptcb->OSTCBPrio = (INT8U)prio; ptcb->OSTCBStat = OS_STAT_RDY; ptcb->OSTCBStatPend = OS_STAT_PEND_OK; ptcb->OSTCBDly = 0; #if OS_TASK_CREATE_EXT_EN > 0u ptcb->OSTCBExtPtr = pext; (4) ptcb->OSTCBStkSize = stk_size; ptcb->OSTCBStkBottom = pbos; ptcb->OSTCBOpt = opt; ptcb->OSTCBId = id; #else pext = pext; stk_size = stk_size; pbos = pbos; opt = opt; id = id; #endif #if OS_TASK_DEL_EN > 0u ptcb->OSTCBDelReq = OS_ERR_NONE; (5) #endif #if OS_LOWEST_PRIO <= 63u ptcb->OSTCBY = (INT8U)(prio >> 3u); (6) ptcb->OSTCBX = (INT8U)(prio & 0x07u); #else ptcb->OSTCBY = (INT8U)((INT8U)(prio >> 4u) & 0xFFu); ptcb->OSTCBX = (INT8U) (prio & 0x0Fu); #endif ptcb->OSTCBBitY = (OS_PRIO)(1uL << ptcb->OSTCBY); ptcb->OSTCBBitX = (OS_PRIO)(1uL << ptcb->OSTCBX); #if OS_EVENT_EN > 0u ptcb->OSTCBEventPtr = (OS_EVENT *)0; (7) #if (OS_EVENT_MULTI_EN > 0u) ptcb->OSTCBEventMultiPtr = (OS_EVENT **)0; #endif #endif #if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) && (OS_TASK_DEL_EN > 0u) ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; (8) #endif #if OS_MBOX_EN || (OS_Q_EN && (OS_MAX_QS >= 2)) ptcb->OSTCBMsg = (void *)0; #endif #if OS_TASK_PROFILE_EN > 0u ptcb->OSTCBCtxSwCtr = 0uL; ptcb->OSTCBCyclesStart = 0uL; ptcb->OSTCBCyclesTot = 0uL; ptcb->OSTCBStkBase = (OS_STK *)0; ptcb->OSTCBStkUsed = 0uL; #endif #if OS_TASK_NAME_EN > 0u ptcb->OSTCBTaskName = (INT8U *)(void *)"?"; #endif #if OS_TASK_REG_TBL_SIZE > 0u for (i = 0u; i < OS_TASK_REG_TBL_SIZE; i++) { ptcb->OSTCBRegTbl[i] = 0u; } #endif OSTCBInitHook(ptcb); (9) OS_ENTER_CRITICAL(); OSTCBPrioTbl[prio] = ptcb; (10) OS_EXIT_CRITICAL(); OSTaskCreateHook(ptcb); (11) #if OS_TASK_CREATE_EXT_EN > 0u #if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) for (j = 0u; j < OS_TLS_TBL_SIZE; j++) { ptcb->OSTCBTLSTbl[j] = (OS_TLS)0; } OS_TLS_TaskCreate(ptcb); #endif #endif OS_ENTER_CRITICAL(); (12) ptcb->OSTCBNext = OSTCBList; ptcb->OSTCBPrev = (OS_TCB *)0; if (OSTCBList != (OS_TCB *)0) { OSTCBList->OSTCBPrev = ptcb; } OSTCBList = ptcb; OSRdyGrp |= ptcb->OSTCBBitY; (13) OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; OSTaskCtr++; OS_EXIT_CRITICAL(); return (OS_ERR_NONE); (14) } OS_EXIT_CRITICAL(); return (OS_NO_MORE_TCB); }
TCB初始化函数主要完成TCB的分配和调度相关的初始化,同时还提供了两个钩子函数OSTCBInitHook和OSTaskCreateHook,这两个函数是可用于用户对任务进行独立配置。
$\mu$C/OS-$\amalg$的调度管理 就绪队列
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 yxhlfx@163.com