使用操作系統(tǒng),就要使用操作系統(tǒng)相關的資源(消息郵箱、信號量、互斥信號量、消息隊列、事件等),需要大致了解系統(tǒng)內核原理。
uC/OS-ii操作系統(tǒng)配置
uC/OS-ii系統(tǒng)配置就是修改os_cfg.h文件,就是使能或失能某些功能,即系統(tǒng)裁剪(使能開關量)。
系統(tǒng)的裁剪是通過預處理(配置了就編譯,沒配置就不編譯)實現的,預處理直接影響程序編譯的大小。
2. 主函數描述
main函數在裸機和操作系統(tǒng)中都是存在的,main函數是程序的入口函數,uC/OS-ii操作系統(tǒng)中重要的三個函數:
OSInit操作系統(tǒng)初始化;
OSTaskCreate創(chuàng)建任務;
OSStart啟動任務
(1) void OSInit (void)系統(tǒng)初始化函數
函數體位于os_core.c文件中。操作系統(tǒng)初始化就是對uC/os-ii系統(tǒng)的初始化,其中包括內核與系統(tǒng)資源的初始化,
void OSInit (void)
{
OSInitHookBegin(); /* Call port specific initialization code系統(tǒng)初始化開始Hook函數 */
OS_InitMisc(); /* Initialize miscellaneous variables初始化各變量 */
OS_InitRdyList(); /* Initialize the Ready List初始化就緒列表 */
OS_InitTCBList(); /* Initialize the free list of OS_TCBs 初始化任務控制塊 */
OS_InitEventList(); /* Initialize the free list of OS_EVENTs初始化事件控制塊 */
#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
OS_FlagInit(); /* Initialize the event flag structures初始化事件標志組 */
#endif
#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
OS_MemInit(); /* Initialize the memory manager初始化內存管理 */
#endif
#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
OS_QInit(); /* Initialize the message queue structures初始化消息隊列 */
#endif
OS_InitTaskIdle(); /* Create the Idle Task 創(chuàng)建空閑任務 */
#if OS_TASK_STAT_EN > 0u
OS_InitTaskStat(); /* Create the Statistic Task 創(chuàng)建任務 */
#endif
#if OS_TMR_EN > 0u
OSTmr_Init(); /* Initialize the Timer Manager */
#endif
OSInitHookEnd(); /* Call port specific init. code */
#if OS_DEBUG_EN > 0u
OSDebugInit();
#endif
}
前五個函數是系統(tǒng)內核必須初始化部分,有選通開關的時根據系統(tǒng)配置決定是否需要初始化的部分。
系統(tǒng)配置在此處體現出來。如:沒有使能“事件標志”即沒有使能該選項,那么程序也不會初始化事件標志組。
必須類:
與系統(tǒng)、任務緊密相關的初始化。這些初始化就是對變量、結構體等賦初始值。(如:系統(tǒng)運行標志位初始化暫停運行、最高優(yōu)先級指空等)它們的初始化位于系統(tǒng)內核os_core.c里面。
非必須類:
代碼前面有一個預處理標志位(選通開關),這些標志位位于os_cfg.h中,當不需要使用這些功能時,它們不會被初始化。
事件標志組、內存管理、消息隊列等這些屬于非必須類,它們的初始化位于自身的.c文件中(不位于os_core.c)。
[OS_FlagInit位于os_flag.c文件里面]
(2) OSTaskCreate創(chuàng)建任務函數
該函數體位于os_task.c文件中。創(chuàng)建任務主要是配置及初始化任務入口、任務相關的堆棧、優(yōu)先級、以及檢測參數的正確性等。
#if OS_TASK_CREATE_EN > 0u //系統(tǒng)配置使能
INT8U OSTaskCreate (void (*task)(void *p_arg),
void *p_arg,
OS_STK *ptos,
INT8U prio)
{
OS_STK *psp;
INT8U err;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register若臨界模式=3u,則給CPU_SR分頻空間*/
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508
if (OSSafetyCriticalStartFlag == OS_TRUE) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range確保優(yōu)先級在指定范圍內 */
return (OS_ERR_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
if (OSIntNesting > 0u) { /* Make sure we don't create the task from within an ISR確保我們不會從ISR中創(chuàng)建任務 */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_CREATE_ISR);
}
/*確保任務優(yōu)先級未被使用,即就緒態(tài)為0*/
if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority */
OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ... */
/* ... the same thing until task is created.保留這個優(yōu)先級,防止再次創(chuàng)建相同優(yōu)先級任務*/
OS_EXIT_CRITICAL();
psp = OSTaskStkInit(task, p_arg, ptos, 0u); /* Initialize the task's stack */
err = OS_TCBInit(prio, psp, (OS_STK *)0, 0u, 0u, (void *)0, 0u);
if (err == OS_ERR_NONE) {
if (OSRunning == OS_TRUE) { /* Find highest priority task if multitasking has started */
OS_Sched();
}
} else {
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others */
OS_EXIT_CRITICAL();
}
return (err);
}
OS_EXIT_CRITICAL();
return (OS_ERR_PRIO_EXIST);
}
#endif
注意:在os_cfg.h文件的任務管理中需要使能“創(chuàng)建任務”
即需要配置:
#define OS_TASK_CREATE_EN 1u /* Include code for OSTaskCreate() 創(chuàng)建任務 */[!--empirenews.page--]
在主函數中創(chuàng)建任務start_task(開始任務),后面的一些關于應用所需的初始化都是在start_task下面創(chuàng)建的,子任務也是基于該函數創(chuàng)建的。
OSStart()開啟任務
該函數體位于os_core.c文件中。在操作系統(tǒng)初始化、任務創(chuàng)建完成后,調用OSStart就可以開啟并執(zhí)行任務了。
該函數屬于內核級,由系統(tǒng)調用,主要包含:
1.查找最高優(yōu)先級任務,使其進入就緒;
2.將當前優(yōu)先級指向就緒任務的最高優(yōu)先級;
3.執(zhí)行目標代碼,開始任務(OSRunning = OS_TRUE)。
void OSStart (void)
{
if (OSRunning == OS_FALSE) {/*若運行狀態(tài)未開始,執(zhí)行下面代碼,開始運行多任務*/
OS_SchedNew(); /* Find highest priority's task priority number查找最高優(yōu)先級任務進入就緒*/
OSPrioCur = OSPrioHighRdy; /*當前優(yōu)先級指向就緒任務最高優(yōu)先級*/
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run指向最高優(yōu)先級*/
OSTCBCur = OSTCBHighRdy; /*當前TCB指向最高優(yōu)先級就緒的TCB*/
OSStartHighRdy(); /* Execute target specific code to start task執(zhí)行目標代碼,開始任務OSRunning=OS_TRUE*/
}
}