【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()函数:
voidOSInit (OS_ERR*p_err) { CPU_STK*p_stk; CPU_STK_SIZEsize; #ifdef OS_SAFETY_CRITICAL if (p_err == (OS_ERR *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return; } #endifOSInitHook(); /* 钩子函数*/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; #endifif (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; #endifOS_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; } #endifOS_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; } #endifOS_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(); #endifOSCfg_Init(); }

可以看出,函数OSInit()主要负责建立任务控制链表、就绪任务表等一些数据结构,并对系统使用的全局变量进行初始化。
【【UCOSIII】UCOSIII的初始化和启动】我们之前讲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,函数如下:
voidOSStart (OS_ERR*p_err) { #ifdef OS_SAFETY_CRITICAL if (p_err == (OS_ERR *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return; } #endifif (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()就什么工作也不做地返回。
【UCOSIII】UCOSIII的初始化和启动
文章图片


    推荐阅读