【UCOSIII】UCOSIII的初始化和启动

UCOSIII系统初始化

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

一般UCOSIII的main函数遵循以下的格式编写:

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

也就是说:

  • 最先肯定是要调用OSInit()初始化UCOSIII;
  • 创建任务,一般我们在main()函数中只创建一个start_task任务,其他任务都在start_task任 务 中 创 建, 在 调 用OSTaskCreate()函 数 创 建 任 务 的 时 候 一 定 要 调 用OS_CRITICAL_ENTER()函数进入临界区,任务创建完以后调用OS_CRITICAL_EXIT()函数退出临界区;
  • 最后调用OSStart()函数开启UCOSIII。

需要注意:我们在调用OSStart()开启UCOSIII之前一定要至少创建一个任务,其实我们在调用OSInit()函数初始化UCOSIII的时候已经创建了一个空闲任务和时钟节拍任务。

接下来,我们看一下UCOSIII的初始化函数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();                                           /* 钩子函数    */

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

    OSRunning                       =  OS_STATE_OS_STOPPED; /* UCOSIII正在运行的标志  */

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

    OSTCBCurPtr                     = (OS_TCB *)0;          /* 指向正在运行任务控制块的指针 */
    OSTCBHighRdyPtr                 = (OS_TCB *)0;        //指向最高优先级就绪任务控制块的指针

    OSPrioCur                       = (OS_PRIO)0;           /* 正在运行任务的优先级 */
    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();                                          /* 优先级初始化  */

    OS_RdyListInit();                                       /* 任务就绪列表初始化  */

    
#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);                                 /* 空闲任务初始化  */
    if (*p_err != OS_ERR_NONE) {
        return;
    }


    OS_TickTaskInit(p_err);                                 /* 时钟节拍任务初始化 */
    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();
}

可以看出,函数OSInit()主要负责建立任务控制链表、就绪任务表等一些数据结构,并对系统使用的全局变量进行初始化。

我们之前讲5个系统任务的时候说到,空闲任务、时钟节拍任务是必须创建的任务;而统计任务、定时任务、中断服务管理任务则是可选任务。怎么保证这一点呢?

在这里就得到解答了。在UCOSIII的系统初始化函数OSInit()中,前两个任务OS_IdleTaskInit()和OS_TickTaskInit()都是一定要运行的,而后三个任务OS_StatTaskInit()、OS_TmrInit()和OS_IntQTaskInit()都采用条件编译的方式。只有在OS_CFG.h文件中配置开启后,才会运行这些任务。

既然是任务,那么就一定有优先级。那么这5个系统任务的优先级有事怎么分布的呢?

UCOSIII中以下优先级用户程序不能使用,因为这些优先级分配给了UCOSIII的5个系统内部任务:

  • 优先级0:中断服务服务管理任务 OS_IntQTask();
  • 优先级1:时钟节拍任务 OS_TickTask();
  • 优先级2:定时任务 OS_TmrTask();
  • 优先级OS_CFG_PRIO_MAX-2:统计任务 OS_StatTask();
  • 优先级OS_CFG_PRIO_MAX-1:空闲任务 OS_IdleTask()。


UCOSIII系统启动

使用函数OSStart()来启动UCOSIII,函数如下:

void  OSStart (OS_ERR  *p_err)
{
#ifdef OS_SAFETY_CRITICAL
    if (p_err == (OS_ERR *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
        return;
    }
#endif

    if (OSRunning == OS_STATE_OS_STOPPED) {
        OSPrioHighRdy   = OS_PrioGetHighest();              /* 寻找有就绪任务的最高优先级 */
        OSPrioCur       = OSPrioHighRdy;
        OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;        //寻找该优先级的任务控制块
        OSTCBCurPtr     = OSTCBHighRdyPtr;
        OSRunning       = OS_STATE_OS_RUNNING;
        OSStartHighRdy();                                   /* Execute target specific code to start task    */
       *p_err           = OS_ERR_FATAL_RETURN;              /* OSStart() is not supposed to return   */
    } else {
       *p_err           = OS_ERR_OS_RUNNING;                /* OS is already running  */
    }
}

在函数OSStart()中,用到了表示内核是否处于运行状态的变量OSRunning。若该变量为FALSE,则意味着内核处于未运行状态;若该变量为TRUE,则意味着内核处于运行状态。

由于在调用函数OSInit()进行初始化之后,已经将该值初始化为FALSE,所以在OSStart()函数中首先对OSRunning进行判断。如果该值为假,则查找最高优先级的就绪任务开始运行,并将OSRunning赋值为TRUE;否则,意味着内核已经处于运行状态了,函数OSInit()就什么工作也不做地返回。

猜你喜欢

转载自blog.csdn.net/qq_38410730/article/details/80764894