之前的章节都是针对某个或某些知识点进行的专项讲解,重点在功能和代码解释。
回到最初开始学μC/OS-III系统时,当时就定下了一个目标,不仅要读懂,还要读透,改造成更适合中国宝宝体质的使用方式。在学完野火的教程后,经过几经思考,最后决定自己锦上添花,再续上几章。
 这几章想达成目的如下:
- 能够快速的上手
 - 能够控制系统的功能
 - 明白移植的过程
 - 能够根据需要的功能来裁剪源码
 
从第六十一章开始的章节都是熟读源码后,根据笔者的整理方法,按照某种逻辑从系统源码中抽出来的专项解释。
 笔者整理方法如下
- 各文件夹功能介绍(每个文件夹放什么文件,哪些是移植的,哪些不需要改,哪些需要修改)
 - 各文件功能概览(每个文件都明白有哪些东西,是系统的哪一部分)
 - 各文件函数概览(每个文件的有什么函数,函数的作用是什么,形参是什么)
 - 移植的本质与移植的顺序(哪些文件需要了解,哪些文件是移植的时候需要更换的)
 - 添加与裁剪源码(添功能与删功能怎么上手)
 - 常用的结构体列表
 - 常用宏介绍(如何用宏来控制整个系统,启用或关闭某个功能)
 - main函数常用的结构顺序
 - 创建任务的流程
 - 任务在几种队列的变化
 
每个整理方法会用一章或多章的篇幅来解释。
点击此处进入μC/OS-iii章节总目录
2024.05.08:UCOSIII第六十二节:常用的结构体(os.h文件)第一部分
- 六十八、UCOSIII:常用的结构体(os.h文件)第一部分
 - OS_TCB
 - OS_SEM
 - OS_FLAG_GRP
 
六十八、UCOSIII:常用的结构体(os.h文件)第一部分
OS_TCB
typedef struct os_tcb OS_TCB;
/*
------------------------------------------------------------------------------------------------------------------------
*                                                  TASK CONTROL BLOCK
------------------------------------------------------------------------------------------------------------------------
*/
struct os_tcb {
    CPU_STK             *StkPtr;                            /* Pointer to current top of stack                        */
    void                *ExtPtr;                            /* Pointer to user definable data for TCB extension       */
    CPU_STK             *StkLimitPtr;                       /* Pointer used to set stack 'watermark' limit            */
    OS_TCB              *NextPtr;                           /* Pointer to next     TCB in the TCB list                */
    OS_TCB              *PrevPtr;                           /* Pointer to previous TCB in the TCB list                */
    OS_TCB              *TickNextPtr;
    OS_TCB              *TickPrevPtr;
    OS_TICK_SPOKE       *TickSpokePtr;                      /* Pointer to tick spoke if task is in the tick list      */
    CPU_CHAR            *NamePtr;                           /* Pointer to task name                                   */
    CPU_STK             *StkBasePtr;                        /* Pointer to base address of stack                       */
#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
    OS_TLS               TLS_Tbl[OS_CFG_TLS_TBL_SIZE];
#endif
    OS_TASK_PTR          TaskEntryAddr;                     /* Pointer to task entry point address                    */
    void                *TaskEntryArg;                      /* Argument passed to task when it was created            */
    OS_PEND_DATA        *PendDataTblPtr;                    /* Pointer to list containing objects pended on           */
    OS_STATE             PendOn;                            /* Indicates what task is pending on                      */
    OS_STATUS            PendStatus;                        /* Pend status                                            */
    OS_STATE             TaskState;                         /* See OS_TASK_STATE_xxx                                  */
    OS_PRIO              Prio;                              /* Task priority (0 == highest)                           */
    CPU_STK_SIZE         StkSize;                           /* Size of task stack (in number of stack elements)       */
    OS_OPT               Opt;                               /* Task options as passed by OSTaskCreate()               */
    OS_OBJ_QTY           PendDataTblEntries;                /* Size of array of objects to pend on                    */
    CPU_TS               TS;                                /* Timestamp                                              */
    OS_SEM_CTR           SemCtr;                            /* Task specific semaphore counter                        */
                                                            /* DELAY / TIMEOUT                                        */
    OS_TICK              TickCtrPrev;                       /* Previous time when task was            ready           */
    OS_TICK              TickCtrMatch;                      /* Absolute time when task is going to be ready           */
    OS_TICK              TickRemain;                        /* Number of ticks remaining for a match (updated at ...  */
                                                            /* ... run-time by OS_StatTask()                          */
    OS_TICK              TimeQuanta;
    OS_TICK              TimeQuantaCtr;
#if OS_MSG_EN > 0u
    void                *MsgPtr;                            /* Message received                                       */
    OS_MSG_SIZE          MsgSize;
#endif
#if OS_CFG_TASK_Q_EN > 0u
    OS_MSG_Q             MsgQ;                              /* Message queue associated with task                     */
#if OS_CFG_TASK_PROFILE_EN > 0u
    CPU_TS               MsgQPendTime;                      /* Time it took for signal to be received                 */
    CPU_TS               MsgQPendTimeMax;                   /* Max amount of time it took for signal to be received   */
#endif
#endif
#if OS_CFG_TASK_REG_TBL_SIZE > 0u
    OS_REG               RegTbl[OS_CFG_TASK_REG_TBL_SIZE];  /* Task specific registers                                */
#endif
#if OS_CFG_FLAG_EN > 0u
    OS_FLAGS             FlagsPend;                         /* Event flag(s) to wait on                               */
    OS_FLAGS             FlagsRdy;                          /* Event flags that made task ready to run                */
    OS_OPT               FlagsOpt;                          /* Options (See OS_OPT_FLAG_xxx)                          */
#endif
#if OS_CFG_TASK_SUSPEND_EN > 0u
    OS_NESTING_CTR       SuspendCtr;                        /* Nesting counter for OSTaskSuspend()                    */
#endif
#if OS_CFG_TASK_PROFILE_EN > 0u
    OS_CPU_USAGE         CPUUsage;                          /* CPU Usage of task (0.00-100.00%)                       */
    OS_CPU_USAGE         CPUUsageMax;                       /* CPU Usage of task (0.00-100.00%) - Peak                */
    OS_CTX_SW_CTR        CtxSwCtr;                          /* Number of time the task was switched in                */
    CPU_TS               CyclesDelta;                       /* value of OS_TS_GET() - .CyclesStart                    */
    CPU_TS               CyclesStart;                       /* Snapshot of cycle counter at start of task resumption  */
    OS_CYCLES            CyclesTotal;                       /* Total number of # of cycles the task has been running  */
    OS_CYCLES            CyclesTotalPrev;                   /* Snapshot of previous # of cycles                       */
    CPU_TS               SemPendTime;                       /* Time it took for signal to be received                 */
    CPU_TS               SemPendTimeMax;                    /* Max amount of time it took for signal to be received   */
#endif
#if OS_CFG_STAT_TASK_STK_CHK_EN > 0u
    CPU_STK_SIZE         StkUsed;                           /* Number of stack elements used from the stack           */
    CPU_STK_SIZE         StkFree;                           /* Number of stack elements free on   the stack           */
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN
    CPU_TS               IntDisTimeMax;                     /* Maximum interrupt disable time                         */
#endif
#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
    CPU_TS               SchedLockTimeMax;                  /* Maximum scheduler lock time                            */
#endif
#if OS_CFG_DBG_EN > 0u
    OS_TCB              *DbgPrevPtr;
    OS_TCB              *DbgNextPtr;
    CPU_CHAR            *DbgNamePtr;
#endif
};
 
这是一个任务控制块(Task Control Block,TCB)的结构体定义,用于描述操作系统中的一个任务。
StkPtr: 指向任务当前堆栈顶部的指针。ExtPtr: 指向用于TCB扩展的用户可定义数据的指针。StkLimitPtr: 用于设置堆栈水位线的指针。NextPtr: 指向TCB列表中下一个TCB的指针。PrevPtr: 指向TCB列表中前一个TCB的指针。TickNextPtr和TickPrevPtr: 用于在定时器中跟踪任务的下一个和前一个节点。TickSpokePtr: 如果任务在定时器列表中,则指向定时器轮中的节点。NamePtr: 指向任务名称的指针。StkBasePtr: 指向堆栈基地址的指针。TLS_Tbl: 如果配置了线程本地存储,则用于存储线程本地存储的数组。TaskEntryAddr: 任务入口点地址的指针。TaskEntryArg: 任务创建时传递的参数。PendDataTblPtr: 指向包含任务挂起的对象列表的指针。PendOn: 表示任务当前挂起在哪个对象上。PendStatus: 指示挂起状态。TaskState: 任务状态。Prio: 任务优先级。StkSize: 任务堆栈大小。Opt: 通过OSTaskCreate()传递的任务选项。PendDataTblEntries: 挂起对象数组的大小。TS: 时间戳。SemCtr: 任务特定的信号量计数器。TickCtrPrev: 任务上次准备就绪的时间。TickCtrMatch: 任务下次准备就绪的绝对时间。TickRemain: 到达匹配的剩余滴答数。TimeQuanta和TimeQuantaCtr: 时间片轮转的时间片大小和剩余计数。MsgPtr和MsgSize: 如果启用了消息队列,则用于存储接收到的消息和消息大小。MsgQ: 与任务关联的消息队列。RegTbl: 任务特定的寄存器数组。FlagsPend、FlagsRdy和FlagsOpt: 如果启用了事件标志,则用于等待的事件标志、使任务准备就绪的事件标志以及标志选项。SuspendCtr: 用于跟踪任务挂起的嵌套计数器。CPUUsage和CPUUsageMax: 任务的CPU使用率和最大CPU使用率。CtxSwCtr、CyclesDelta、CyclesStart、CyclesTotal和CyclesTotalPrev: 任务的上下文切换次数和与CPU周期相关的一些计数器。StkUsed和StkFree: 任务堆栈中已使用和剩余的堆栈元素数量。IntDisTimeMax和SchedLockTimeMax: 最大中断禁用时间和最大调度器锁定时间,用于性能测量。DbgPrevPtr、DbgNextPtr和DbgNamePtr: 调试目的的前一个和后一个TCB指针以及任务名称的指针。
OS_SEM
typedef struct os_sem OS_SEM;
/*
------------------------------------------------------------------------------------------------------------------------
*                                                      SEMAPHORES
*
* Note(s) : See  PEND OBJ  Note #1'.
------------------------------------------------------------------------------------------------------------------------
*/
struct  os_sem {                                            /* Semaphore                                              */
                                                            /* ------------------ GENERIC  MEMBERS ------------------ */
    OS_OBJ_TYPE          Type;                              /* Should be set to OS_OBJ_TYPE_SEM                       */
    CPU_CHAR            *NamePtr;                           /* Pointer to Semaphore Name (NUL terminated ASCII)       */
    OS_PEND_LIST         PendList;                          /* List of tasks waiting on semaphore                     */
#if OS_CFG_DBG_EN > 0u
    OS_SEM              *DbgPrevPtr;
    OS_SEM              *DbgNextPtr;
    CPU_CHAR            *DbgNamePtr;
#endif
                                                            /* ------------------ SPECIFIC MEMBERS ------------------ */
    OS_SEM_CTR           Ctr;
    CPU_TS               TS;
};
 
这个结构体定义描述了一个信号量(Semaphore)。下面是结构体中各个字段的详细解释:
Type: 对象类型,应设置为OS_OBJ_TYPE_SEM,表示这是一个信号量对象。NamePtr: 指向信号量名称的指针,通常是一个以NUL终止的ASCII字符串。PendList: 等待信号量的任务列表,用于存储等待该信号量的任务的信息。DbgPrevPtr、DbgNextPtr和DbgNamePtr: 调试目的的前一个和后一个信号量指针以及信号量名称的指针。Ctr: 信号量计数器,表示信号量当前的可用资源数量。TS: 时间戳,记录信号量的最近更新时间。

 如果我们创建一个初始可用信号量个数为5的信号量,那么信号量创建成功的示意图具体见图
 
这个结构体包含了信号量的一般属性,例如名称、等待队列以及用于调试的指针,以及特定属性,例如信号量的计数器和时间戳。信号量是一种常用的同步原语,用于控制多任务环境中的资源访问。
OS_FLAG_GRP
typedef struct os_flag_grp OS_FLAG_GRP;
/*
------------------------------------------------------------------------------------------------------------------------
*                                                     EVENT FLAGS
*
* Note(s) : See  PEND OBJ  Note #1'.
------------------------------------------------------------------------------------------------------------------------
*/
struct  os_flag_grp {                                       /* Event Flag Group                                       */
                                                            /* ------------------ GENERIC  MEMBERS ------------------ */
    OS_OBJ_TYPE          Type;                              /* Should be set to OS_OBJ_TYPE_FLAG                      */
    CPU_CHAR            *NamePtr;                           /* Pointer to Event Flag Name (NUL terminated ASCII)      */
    OS_PEND_LIST         PendList;                          /* List of tasks waiting on event flag group              */
#if OS_CFG_DBG_EN > 0u
    OS_FLAG_GRP         *DbgPrevPtr;
    OS_FLAG_GRP         *DbgNextPtr;
    CPU_CHAR            *DbgNamePtr;
#endif
                                                            /* ------------------ SPECIFIC MEMBERS ------------------ */
    OS_FLAGS             Flags;                             /* 8, 16 or 32 bit flags                                  */
    CPU_TS               TS;                                /* Timestamp of when last post occurred                   */
};
 
这个结构体定义描述了一个事件标志组(Event Flag Group)。下面是结构体中各个字段的详细解释:
Type: 对象类型,应设置为OS_OBJ_TYPE_FLAG,表示这是一个事件标志组对象。NamePtr: 指向事件标志组名称的指针,通常是一个以NUL终止的ASCII字符串。PendList: 等待事件标志组的任务列表,用于存储等待该事件标志组的任务的信息。DbgPrevPtr、DbgNextPtr和DbgNamePtr: 调试目的的前一个和后一个事件标志组指针以及事件标志组名称的指针。Flags: 事件标志,可以是8、16或32位,用于表示不同的事件状态。TS: 时间戳,记录事件标志组的最近一次操作时间。

 如果我们创建一个事件,那么事件创建成功的示意图具体见图
 
事件标志组是一种用于多任务系统中任务间通信和同步的机制,它允许任务等待某些事件的发生,并在事件发生时被唤醒。该结构体包含了事件标志组的一般属性,例如名称、等待队列以及用于调试的指针,以及特定属性,例如事件标志和时间戳。



















