UCOSIII学习-任务管理

2023-05-16

UCOSIII学习-任务管理

  • 1、UCOSIII 任务组成
  • 2、UCOSIII 默认系统任务
  • 3、UCOSIII 任务状态
  • 4、任务堆栈
      • 1. 任务堆栈的创建
      • 2. 任务堆栈初始化
  • 5、任务控制块
      • 1. 任务控制块创建
      • 2. 任务控制块初始化
  • 6、任务就绪表
      • 1. 优先级
      • 2. 就绪表
  • 7、任务调度
      • 1. 可剥夺型任务调度
      • 2. 任务调度点
      • 3. 调度器上锁与解锁
      • 4. 时间片轮转调度
  • 8、任务切换
      • 1. 任务切换
  • 9、UCOSIII系统初始化

1、UCOSIII 任务组成

UCOSIII由任务堆栈、任务控制块、任务函数三部分组成。

  1. 任务堆栈:保存工作环境,如寄存器的值
  2. 任务控制块:记录任务的各个属性
  3. 任务函数:任务具体的实现代码

2、UCOSIII 默认系统任务

  1. 空闲任务:必须任务,由UCOSIII自己创建的第一个任务
  2. 时钟节拍任务:必须创建
  3. 统计任务:可选任务。用来统计CPU使用率和各个任务的堆栈使用量
  4. 定时任务:可选任务。向用户提供定时服务
  5. 中断服务管理任务:可选任务

3、UCOSIII 任务状态

  1. 休眠态(INITIAL): 任务已经在空闲任务池中(CPU的flash中),但还未受到UCOSIII管理
  2. 等待态(IDLE): 任务一旦被创建就进入等待态,或者正在运行的任务需要等待一段时间或者等待某个事件(任务完成或者任务退出了),此时系统把CPU的使用权交给别的任务,当前任务就进入等待态
  3. 就绪态(READY): 系统为任务分配了任务控制块,并且任务已经在就绪表中登记,具备了被执行的条件,此时任务就在就绪态
  4. 运行态(RUNNING): 任务获得CPU使用权,正在运行
  5. 中断服务态(SUSPEND): 当发生中断,当前的任务会被挂起,CPU先去执行中断服务函数,此时当前任务需要等待资源或者等待其他任务结束

4、任务堆栈

1. 任务堆栈的创建

  1. 遵循 先进先出FIFO 原则的一块连续内存空间
  2. 存储任务切换时或中断时CPU寄存器的内容
  3. 每个任务都有自己的堆栈空间

2. 任务堆栈初始化

创建一个任务时,需要把系统启动这个任务时所需的CPU各个寄存器的初始值事先存放到任务堆栈中。当该任务获得CPU使用权时,就把任务堆栈的内容复制到CPU的寄存器中,开始运行任务。

5、任务控制块

1. 任务控制块创建

  1. 记录与任务相关的信息的 数据结构
  2. 每个任务都有自己的任务控制块
  3. 任务控制块需要自己创建
    结构体如下:
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
};

2. 任务控制块初始化

参考正点原子移植代码及PDF:

void  OS_TaskInitTCB (OS_TCB  *p_tcb)
{
#if OS_CFG_TASK_REG_TBL_SIZE > 0u
    OS_REG_ID   reg_id;
#endif
#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
    OS_TLS_ID   id;
#endif
#if OS_CFG_TASK_PROFILE_EN > 0u
    CPU_TS      ts;
#endif


    p_tcb->StkPtr             = (CPU_STK       *)0;
    p_tcb->StkLimitPtr        = (CPU_STK       *)0;

    p_tcb->ExtPtr             = (void          *)0;

    p_tcb->NextPtr            = (OS_TCB        *)0;
    p_tcb->PrevPtr            = (OS_TCB        *)0;

    p_tcb->TickNextPtr        = (OS_TCB        *)0;
    p_tcb->TickPrevPtr        = (OS_TCB        *)0;
    p_tcb->TickSpokePtr       = (OS_TICK_SPOKE *)0;

    p_tcb->NamePtr            = (CPU_CHAR      *)((void *)"?Task");

    p_tcb->StkBasePtr         = (CPU_STK       *)0;

    p_tcb->TaskEntryAddr      = (OS_TASK_PTR    )0;
    p_tcb->TaskEntryArg       = (void          *)0;

#if (OS_CFG_PEND_MULTI_EN > 0u)
    p_tcb->PendDataTblPtr     = (OS_PEND_DATA  *)0;
    p_tcb->PendDataTblEntries = (OS_OBJ_QTY     )0u;
#endif

    p_tcb->TS                 = (CPU_TS         )0u;

#if (OS_MSG_EN > 0u)
    p_tcb->MsgPtr             = (void          *)0;
    p_tcb->MsgSize            = (OS_MSG_SIZE    )0u;
#endif

#if OS_CFG_TASK_Q_EN > 0u
    OS_MsgQInit(&p_tcb->MsgQ,
                (OS_MSG_QTY)0u);
#if OS_CFG_TASK_PROFILE_EN > 0u
    p_tcb->MsgQPendTime       = (CPU_TS         )0u;
    p_tcb->MsgQPendTimeMax    = (CPU_TS         )0u;
#endif
#endif

#if OS_CFG_FLAG_EN > 0u
    p_tcb->FlagsPend          = (OS_FLAGS       )0u;
    p_tcb->FlagsOpt           = (OS_OPT         )0u;
    p_tcb->FlagsRdy           = (OS_FLAGS       )0u;
#endif

#if OS_CFG_TASK_REG_TBL_SIZE > 0u
    for (reg_id = 0u; reg_id < OS_CFG_TASK_REG_TBL_SIZE; reg_id++) {
        p_tcb->RegTbl[reg_id] = (OS_REG)0u;
    }
#endif

#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
    for (id = 0u; id < OS_CFG_TLS_TBL_SIZE; id++) {
        p_tcb->TLS_Tbl[id]    = (OS_TLS)0;
    }
#endif

    p_tcb->SemCtr             = (OS_SEM_CTR     )0u;
#if OS_CFG_TASK_PROFILE_EN > 0u
    p_tcb->SemPendTime        = (CPU_TS         )0u;
    p_tcb->SemPendTimeMax     = (CPU_TS         )0u;
#endif

    p_tcb->StkSize            = (CPU_STK_SIZE   )0u;


#if OS_CFG_TASK_SUSPEND_EN > 0u
    p_tcb->SuspendCtr         = (OS_NESTING_CTR )0u;
#endif

#if OS_CFG_STAT_TASK_STK_CHK_EN > 0u
    p_tcb->StkFree            = (CPU_STK_SIZE   )0u;
    p_tcb->StkUsed            = (CPU_STK_SIZE   )0u;
#endif

    p_tcb->Opt                = (OS_OPT         )0u;

    p_tcb->TickCtrPrev        = (OS_TICK        )OS_TICK_TH_INIT;
    p_tcb->TickCtrMatch       = (OS_TICK        )0u;
    p_tcb->TickRemain         = (OS_TICK        )0u;

    p_tcb->TimeQuanta         = (OS_TICK        )0u;
    p_tcb->TimeQuantaCtr      = (OS_TICK        )0u;

#if OS_CFG_TASK_PROFILE_EN > 0u
    p_tcb->CPUUsage           = (OS_CPU_USAGE   )0u;
    p_tcb->CPUUsageMax        = (OS_CPU_USAGE   )0u;
    p_tcb->CtxSwCtr           = (OS_CTX_SW_CTR  )0u;
    p_tcb->CyclesDelta        = (CPU_TS         )0u;
    ts                        = OS_TS_GET();                /* Read the current timestamp and save                    */
    p_tcb->CyclesStart        = ts;
    p_tcb->CyclesTotal        = (OS_CYCLES      )0u;
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN
    p_tcb->IntDisTimeMax      = (CPU_TS         )0u;
#endif
#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
    p_tcb->SchedLockTimeMax   = (CPU_TS         )0u;
#endif

    p_tcb->PendOn             = (OS_STATE       )OS_TASK_PEND_ON_NOTHING;
    p_tcb->PendStatus         = (OS_STATUS      )OS_STATUS_PEND_OK;
    p_tcb->TaskState          = (OS_STATE       )OS_TASK_STATE_RDY;

    p_tcb->Prio               = (OS_PRIO        )OS_PRIO_INIT;

#if OS_CFG_DBG_EN > 0u
    p_tcb->DbgPrevPtr         = (OS_TCB        *)0;
    p_tcb->DbgNextPtr         = (OS_TCB        *)0;
    p_tcb->DbgNamePtr         = (CPU_CHAR      *)((void *)" ");
#endif
}

6、任务就绪表

1. 优先级

  1. UCOSIII理论上支持无限个任务,优先级无数个,默认64个优先级,同一个优先级使用时间片轮转调度的方法
  2. UCOSIII中优先级越高,数值越小

2. 就绪表

UCOSIII就绪表由两部分组成:

  1. 优先级位映射表:用来记录哪个优先级下有任务就绪
  2. 就绪任务列表:用来记录每一个优先级下所有就绪的任务。

7、任务调度

1. 可剥夺型任务调度

  1. 任务调度是中止当前正在运行的任务而去执行其他任务
  2. UCOSIII是可剥夺型内核。即当一个高优先级任务准备就绪,且此时发生任务调度,那么高优先级任务会获得CPU使用权
  3. 任务调度由任务调度器完成,任务调度器分为两种:任务级调度器,中断级调度器

2. 任务调度点

以正点原子STM32库函数为例,高亮为STM32重点关注点(常用)

  1. 释放信号量或者发送消息,也可通过配置相应的参数不发生任务调度。(内核对象时使用)
  2. 使用延时函数OSTimeDly()或者OSTimeDl yHMSM()
  3. 任务等待的事情还没发生(等待信号量,消息队列等)。
  4. 任务取消等待。
  5. 创建任务
  6. 删除任务
  7. 删除一个内核对象。
  8. 任务改变自身的优先级或者其他任务的优先级。
  9. 任务通过调用OSTaskSuspend将自身挂起
  10. 任务解挂某个挂起的任务
  11. 退出所有的嵌套中断
  12. 通过OSSchedUnlock给调度器解锁
  13. 任务调用OSSchedRoundRobinYield(放弃其执行时间片
  14. 用户调用oSSched()函数

3. 调度器上锁与解锁

有时候我们并不希望发生任务调度,因为始终有一些代码的执行过程是不能被打断的。此时我们就可以使用函数OSSchedLock()对调度器加锁,当我们想要恢复任务调度的时候就可以使用函数OSSchedUnlock()给已经上锁的任务调度器解锁。如:创建任务时

4. 时间片轮转调度

  1. UCOSIII允许一个优先级下有多个任务,每个任务可以执行指定的时间(时间片),然后轮到下一个任务,这个过程就是时间片轮转调度,当一个任务不想在运行的时候就可以放弃其时间片。
  2. 时间片轮转调度器为: 0S_SchedRounuRobin()。

8、任务切换

1. 任务切换

  1. 当UCOSIII需要切换到另外一个任务时,它将保存当前任务的现场到当前任务的堆栈中,主要是CPU寄存器值,然后恢复新的现场并且执行新的任务,这个过程就是任务切换
  2. 任务切换分为两种: 任务级切换、中断级切换
  3. 任务级切换函数为:OSCtxSw()
  4. 中断级切换函数为:OSIntCtxSw()

任务调度会调用任务切换,是包含关系。任务切换是保存与恢复现场的过程,至于任务调度,要比任务切换过程更为复杂。汇编代码如下:
任务级切换源码

;********************************************************************************************************
;                       PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw()
;
; Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch.  This function
;              triggers the PendSV exception which is where the real work is done.
;********************************************************************************************************

OSCtxSw
    LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)
    LDR     R1, =NVIC_PENDSVSET
    STR     R1, [R0]
    BX      LR

中断级切换源码

;********************************************************************************************************
;                   PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw()
;
; Note(s) : 1) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as
;              the result of an interrupt.  This function simply triggers a PendSV exception which will
;              be handled when there are no more interrupts active and interrupts are enabled.
;********************************************************************************************************

OSIntCtxSw
    LDR     R0, =NVIC_INT_CTRL                                  ; Trigger the PendSV exception (causes context switch)
    LDR     R1, =NVIC_PENDSVSET
    STR     R1, [R0]
    BX      LR

9、UCOSIII系统初始化

在使用UCOSIII之前我们必须先初始化UCOSIII,函数OSInit()用来完成UCOSIII的初始化,而且OSInit()必须先于其他UCOSIII函数调用,包括oSStart()函数。
main():

int main(void)
{
	OS_ERR err;
	......
	//其他函数,一般为外设初始化函数
	......
	OSInit(&err);
	......
	//其他函数,一般为创建任务函数
	......
	OSStart(&err);
}

OSInit():

void  OSInit (OS_ERR  *p_err)
{
    CPU_STK      *p_stk;
    CPU_STK_SIZE  size;

#ifdef OS_SAFETY_CRITICAL
    if (p_err == (OS_ERR *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
        return;
    }
#endif
    OSInitHook();                                           /* Call port specific initialization code                 */

    OSIntNestingCtr                 = (OS_NESTING_CTR)0;    /* Clear the interrupt nesting counter                    */

    OSRunning                       =  OS_STATE_OS_STOPPED; /* Indicate that multitasking not started                 */

    OSSchedLockNestingCtr           = (OS_NESTING_CTR)0;    /* Clear the scheduling lock counter                      */

    OSTCBCurPtr                     = (OS_TCB *)0;          /* Initialize OS_TCB pointers to a known state            */
    OSTCBHighRdyPtr                 = (OS_TCB *)0;

    OSPrioCur                       = (OS_PRIO)0;           /* Initialize priority variables to a known state         */
    OSPrioHighRdy                   = (OS_PRIO)0;
    OSPrioSaved                     = (OS_PRIO)0;

#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
    OSSchedLockTimeBegin            = (CPU_TS)0;
    OSSchedLockTimeMax              = (CPU_TS)0;
    OSSchedLockTimeMaxCur           = (CPU_TS)0;
#endif

#ifdef OS_SAFETY_CRITICAL_IEC61508
    OSSafetyCriticalStartFlag       =  DEF_FALSE;
#endif

#if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
    OSSchedRoundRobinEn             = DEF_FALSE;
    OSSchedRoundRobinDfltTimeQuanta = OSCfg_TickRate_Hz / 10u;
#endif

    if (OSCfg_ISRStkSize > (CPU_STK_SIZE)0) {
        p_stk = OSCfg_ISRStkBasePtr;                        /* Clear exception stack for stack checking.              */
        if (p_stk != (CPU_STK *)0) {
            size  = OSCfg_ISRStkSize;
            while (size > (CPU_STK_SIZE)0) {
                size--;
               *p_stk = (CPU_STK)0;
                p_stk++;
            }
        }
    }

#if OS_CFG_APP_HOOKS_EN > 0u
    OS_AppTaskCreateHookPtr = (OS_APP_HOOK_TCB )0;          /* Clear application hook pointers                        */
    OS_AppTaskDelHookPtr    = (OS_APP_HOOK_TCB )0;
    OS_AppTaskReturnHookPtr = (OS_APP_HOOK_TCB )0;

    OS_AppIdleTaskHookPtr   = (OS_APP_HOOK_VOID)0;
    OS_AppStatTaskHookPtr   = (OS_APP_HOOK_VOID)0;
    OS_AppTaskSwHookPtr     = (OS_APP_HOOK_VOID)0;
    OS_AppTimeTickHookPtr   = (OS_APP_HOOK_VOID)0;
#endif

#if OS_CFG_TASK_REG_TBL_SIZE > 0u
    OSTaskRegNextAvailID    = (OS_REG_ID)0;
#endif

    OS_PrioInit();                                          /* Initialize the priority bitmap table                   */

    OS_RdyListInit();                                       /* Initialize the Ready List                              */
    
#if OS_CFG_FLAG_EN > 0u                                     /* Initialize the Event Flag module                       */
    OS_FlagInit(p_err);
    if (*p_err != OS_ERR_NONE) {
        return;
    }
#endif

#if OS_CFG_MEM_EN > 0u                                      /* Initialize the Memory Manager module                   */
    OS_MemInit(p_err);
    if (*p_err != OS_ERR_NONE) {
        return;
    }
#endif

#if (OS_MSG_EN) > 0u                                        /* Initialize the free list of OS_MSGs                    */
    OS_MsgPoolInit(p_err);
    if (*p_err != OS_ERR_NONE) {
        return;
    }
#endif

#if OS_CFG_MUTEX_EN > 0u                                    /* Initialize the Mutex Manager module                    */
    OS_MutexInit(p_err);
    if (*p_err != OS_ERR_NONE) {
        return;
    }
#endif

#if OS_CFG_Q_EN > 0u
    OS_QInit(p_err);                                        /* Initialize the Message Queue Manager module            */
    if (*p_err != OS_ERR_NONE) {
        return;
    }
#endif

#if OS_CFG_SEM_EN > 0u                                      /* Initialize the Semaphore Manager module                */
    OS_SemInit(p_err);
    if (*p_err != OS_ERR_NONE) {
        return;
    }
#endif

#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
    OS_TLS_Init(p_err);                                     /* Initialize Task Local Storage, before creating tasks   */
    if (*p_err != OS_ERR_NONE) {
        return;
    }
#endif

    OS_TaskInit(p_err);                                     /* Initialize the task manager                            */
    if (*p_err != OS_ERR_NONE) {
        return;
    }

#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
    OS_IntQTaskInit(p_err);                                 /* Initialize the Interrupt Queue Handler Task            */
    if (*p_err != OS_ERR_NONE) {
        return;
    }
#endif
  
    OS_IdleTaskInit(p_err);                                 /* Initialize the Idle Task                               */
    if (*p_err != OS_ERR_NONE) {
        return;
    }

    OS_TickTaskInit(p_err);                                 /* Initialize the Tick Task                               */
    if (*p_err != OS_ERR_NONE) {
        return;
    }

#if OS_CFG_STAT_TASK_EN > 0u                                /* Initialize the Statistic Task                          */
    OS_StatTaskInit(p_err);
    if (*p_err != OS_ERR_NONE) {
        return;
    }
#endif

#if OS_CFG_TMR_EN > 0u                                      /* Initialize the Timer Manager module                    */
    OS_TmrInit(p_err);
    if (*p_err != OS_ERR_NONE) {
        return;
    }
#endif

#if OS_CFG_DBG_EN > 0u
    OS_Dbg_Init();
#endif

    OSCfg_Init();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UCOSIII学习-任务管理 的相关文章

  • Baxter工作站建立及简单使用

    1 硬件 1个 Baxter Research Robot1台PC机或笔记本 xff0c 安装好Ubuntu系统 xff08 推荐Ubuntu16 04安装ROS kinetic xff09 1个无线路由器 xff08 千兆网口 xff09

随机推荐

  • selenium网页自动登录、打卡(二)

    文章目录 前言一 Python 43 Selenium二 通信环境 xff08 服务器 客户端 xff09 1 selenium借助cookie网页登录csdn2 私信发送消息流程3 将新增的逻辑融入原本的程序 前言 前面做了一个自动打卡的
  • 解决浏览器“由你的组织管理”或“由贵单位管理”

    寒假在家使用自己电脑时 xff0c 浏览器出现意外关闭 xff0c 一次以为没什么 xff0c 这两天出现好几次 xff0c 时不时地来一下 xff0c 太搞心态了 xff0c 必须给他解决了 一番检查后 xff0c 是浏览器自动安装了一款
  • Ubuntu18.04屏幕分辨率问题

    Ubuntu18 04屏幕分辨率问题 起因 本来昨天还好好的 xff0c 过了一夜 xff0c 就变了 xff0c 像极了咳咳 自行脑补 redwallbot 2小车上固定的屏幕 xff0c 屏幕分辨率本来应该是1920x1080的 xff
  • 使用frp实现内网穿透

    使用frp实现内网穿透 引言 一打五师兄走之前留了一块树莓派给我 xff0c 暑假闲来无事拿出来玩玩 如果每次都连接显示屏和键盘使用有点麻烦而且低级 正常笔记本和树莓派都连着实验室的WIFI xff0c 网段一样 xff0c 是可以ssh远
  • ffmpeg+nginx-rtmp转发视频流

    nginx与nginx rtmp module安装 画了好几天图 xff0c 实在有些乏力 xff0c 找点有意思的事情做做 觉得视频流传输挺有意思 xff0c B站找了些视频 xff0c 但感觉有些大同小异 xff0c 讲得不是很清楚 F
  • 2013 google校园招聘笔试题

    2013 google校园招聘笔试题 回忆版 xff0c 难免有错误 xff0c 欢迎指正 同时欢迎大家在评论中讨论答案 1 单项选择题 1 1如果把传输速率定义为单位时间内传送的信息量 xff08 以字节计算 xff09 多少 关于一下几
  • 调用微信公众号接口给女票每天打卡

    文章目录 前言一 微信公众号接口二 使用步骤 前言 最近网上很火的给女朋友做公众号推送 xff0c 作者 小红书 64 猪咪不是猪 且做作者 大方的共享成品 源码 43 教学 43 自动版本 起初 xff0c 人们认为这仅仅只是个简单且幼稚
  • js获取整个页面源码

    通过 outerHTML document documentElement outerHTML 通过异步请求 get window location href function res console log res 通过jQuery 34
  • 查看自己电脑被别人U盘拷贝文件

    windows 43 R reg query HKLM System currentcontrolset enum usbstor s gt c usb txt FriendlyName 第二种是使用USBViewer USBViewer
  • 普罗米修斯-docker安装

    1 只有一台服务器 xff0c 所以使用docker来进行试验 安装docker curl fsSL https get docker com bash s docker mirror Aliyun 查看安装版本 docker versio
  • netty参数设置

    1 通用参数 CONNECT TIMEOUT MILLIS Netty参数 xff0c 连接超时毫秒数 xff0c 默认值30000毫秒即30秒 MAX MESSAGES PER READ Netty参数 xff0c 一次Loop读取的最大
  • git 删除远程文件目录

    git rm r cached 文件夹名称 git add git commit m 34 aa 34 git push origin master
  • git删除远程分支

    branch 1 列出分支 xff0c a参数是列出所有分支 xff0c 包括远程分支 git branch a 2 创建一个本地分支 git branch branchname 3 创建一个分支 xff0c 并切换到该分支 git che
  • maven命令上传第三方包

    mvn deploy deploy file Dmaven test skip 61 true DgroupId 61 sdk的groupId DartifactId 61 包的名称 Dversion 61 版本号 如 xff1a 0 0
  • 解决图片上传权限问题

    linux默认umask为022 xff0c 对应权限为755 xff0c 其它用户可读可执行 可以vim etc profile xff0c 搜索umusk关键字查看 if UID gt 199 amp amp 34 96 usr bin
  • 微信小程序 解决 wx.request同步问题 方便开发 Promise方式

  • Python经典书籍有哪些?这份书单送给你_黑马程序员

    文章目录 一 Python 基础 01 Python编程 xff1a 从入门到实践 xff08 第2版 xff09 02 Python编程快速上手 xff08 第2版 xff09 03 Python编程初学者指南 04 笨方法 学Pytho
  • 记忆的方法

    1 第一招 xff0c 在背书的时候 xff0c 用双手捂住你的耳朵 xff0c 并且大声的朗读 研究表明 xff0c 用手捂着耳朵来朗读的话 xff0c 声音是直接通过骨骼来传输到内耳 xff0c 对大脑刺激会更加强烈 xff0c 记忆也
  • ssh登录服务器缓慢问题

    问题描述 问题刚开始是由pod启动失败 xff0c 报错unable to ensure pod container exists failed to create container for kubepods burstable pod8
  • UCOSIII学习-任务管理

    UCOSIII学习 任务管理 1 UCOSIII 任务组成2 UCOSIII 默认系统任务3 UCOSIII 任务状态4 任务堆栈1 任务堆栈的创建2 任务堆栈初始化 5 任务控制块1 任务控制块创建2 任务控制块初始化 6 任务就绪表1