【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。
接下来,我们看一下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()就什么工作也不做地返回。
文章图片
推荐阅读
- 宽容谁
- 我要做大厨
- 增长黑客的海盗法则
- 画画吗()
- 2019-02-13——今天谈梦想()
- 远去的风筝
- 三十年后的广场舞大爷
- 叙述作文
- 20190302|20190302 复盘翻盘
- 学无止境,人生还很长