1. 程式人生 > >UCOSIII 系統內部任務

UCOSIII 系統內部任務

UCOSII 中有兩個系統任務:統計任務和空閒任務,在但是UCOSIII中系統內部任務擴充套件到了5  。

空閒任務、時鐘節拍任務、統計任務定時任務中斷服務管理任務鉤子函式 。


1.空閒任務:

OS_IdleTask(),在os_core.c 檔案中定義。
呼叫 OS_Init()初始化UCOS 的時候就會被建立。 OS_Init() 中 調 用 了 函 數OS_IdleTaskInit()
void OS_IdleTaskInit (OS_ERR *p_err)
{
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
OSIdleTaskCtr = (OS_IDLE_CTR)0;

(1)
OSTaskCreate((OS_TCB * )&OSIdleTaskTCB,
(CPU_CHAR * )((void *)"uC/OS-III Idle Task"),
(OS_TASK_PTR )OS_IdleTask,
(void * )0,
(OS_PRIO )(OS_CFG_PRIO_MAX - 1u),
(CPU_STK * )OSCfg_IdleTaskStkBasePtr,
(CPU_STK_SIZE )OSCfg_IdleTaskStkLimit,
(CPU_STK_SIZE )OSCfg_IdleTaskStkSize,
(OS_MSG_QTY )0u,
(OS_TICK )0u,
(void * )0,
(OS_OPT )(OS_OPT_TASK_STK_CHK | \
OS_OPT_TASK_STK_CLR | OS_OPT_TASK_NO_TLS),
(OS_ERR * )p_err);
}

任 務 優 先 級 為 OS_CFG_PRIO_MAX – 1OS_CFG_PRIO_MAX 是一個巨集,在檔案 os_cfg.h 中定義,OS_CFG_PRIO_MAX 定義了 UCOSIII可用的任務數。 

預設情況下 OS_CFG_PRIO_MAX64。空閒任務優先順序為OS_CFG_PRIO_MAX-1,說明空閒任務的優先順序為最低的。
空閒任務堆疊大小為
OSCfg_IdleTaskStkSizeOSCfg_IdleTaskStkSize 也是一個巨集,在os_cfg_app.c檔案中定義,預設為 128,則空閒任務堆疊預設為128*4=512 位元組。

空閒任務的任務函式為任務函式為
OS_IdleTask()OS_IdleTask()函式程式碼如下:

void OS_IdleTask (void *p_arg)
{
CPU_SR_ALLOC();
p_arg = p_arg;
while (DEF_ON) {
CPU_CRITICAL_ENTER();
(1)
OSIdleTaskCtr++; (2)
#if OS_CFG_STAT_TASK_EN > 0u (3)
OSStatTaskCtr++; (4)
#endif
CPU_CRITICAL_EXIT();
(5)
OSIdleTaskHook(); (6)
}
}
(1)
(5)、臨界段程式碼保護
(2)OSIdleTaskCtr加一,每進入一次空閒任務, OSIdleTaskCtr就加一。我們可以通過檢視 OSIdleTaskCtr變數的遞增速度來判斷 CPU 執行應用任務的繁忙程度,如果遞增的快的話說明應用任務花費時間少,很快就執行完了。
(3)、巨集 OS_CFG_STAT_TASK_EN大於 0 說明開啟了統計任務。
(4)OSStatTaskCtr預設也是一個 32 位的無符號整形變數,在檔案 os.h 中定義。這裡將OSStatTaskCtr 加一,統計任務中用到 OSStatTaskCtr,用來統計CPU 的使用率。(6)OSIdleTaskHook()叫做鉤子函式,我們可以在鉤子函式中幹一些其他的事情。 

2.時鐘節拍任務
OS_Ticktask(),在 OS_Init()中呼叫了一個函式OS_TickTaskInit(),函式程式碼如下: 

void OS_TickTaskInit (OS_ERR *p_err)
{
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
OSTickCtr = (OS_TICK)0u;
OSTickTaskTimeMax = (CPU_TS)0u;


OS_TickListInit();
if (OSCfg_TickTaskStkBasePtr == (CPU_STK *)0) {
*p_err = OS_ERR_TICK_STK_INVALID;
return;
}
if (OSCfg_TickTaskStkSize < OSCfg_StkSizeMin) {
*p_err = OS_ERR_TICK_STK_SIZE_INVALID;
return;
}
if (OSCfg_TickTaskPrio >= (OS_CFG_PRIO_MAX - 1u)) {
*p_err = OS_ERR_TICK_PRIO_INVALID;
return;
}
OSTaskCreate((OS_TCB * )&OSTickTaskTCB,
(CPU_CHAR* )((void *)"uC/OS-III Tick Task"),
(OS_TASK_PTR )OS_TickTask,
(void* )0,
(OS_PRIO )OSCfg_TickTaskPrio,
(CPU_STK* )OSCfg_TickTaskStkBasePtr,
(CPU_STK_SIZE )OSCfg_TickTaskStkLimit,
(CPU_STK_SIZE )OSCfg_TickTaskStkSize,
(OS_MSG_QTY )0u,
(OS_TICK )0u,
(void* )0,
(OS_OPT )(OS_OPT_TASK_STK_CHK |\
OS_OPT_TASK_STK_CLR | OS_OPT_TASK_NO_TLS),
(OS_ERR *)p_err);
}

時鐘節拍任務的優先順序儘可能的高一點 ,時鐘節拍任務的作用是跟蹤正在延時的任務,以及在指定時間內等待某個核心物件的任務,OS_TickTask()任務函式程式碼如下:  void OS_TickTask (void *p_arg)
{
OS_ERR err;
CPU_TS ts;

p_arg = p_arg;
while (DEF_ON) {
(void)OSTaskSemPend((OS_TICK )0,
(1)
(OS_OPT )OS_OPT_PEND_BLOCKING,
(CPU_TS * )&ts,
(OS_ERR * )&err);
if (err == OS_ERR_NONE) {
if (OSRunning == OS_STATE_OS_RUNNING) {
OS_TickListUpdate();
(2)
}
}
}
}

(1)、請求訊號量, OSTaskSemPend()是請求任務內建訊號量的,訊號量會在 OSTimeTick() POST,這裡的訊號量是用來做任務同步的 。OSTimeTick()會在滴答定時器中斷服務函式中呼叫。
(2)、訊號量請求成功的話就呼叫函式 OS_TickListUpdate()函式。 時鐘節拍列表是由一個數據表 OSCfg_TickWheel(os_cfg_app.c 中定義)和一個計數器
OSTickCtr 組 成 , 表 OSCfg_TickWheel 是 一 個 數 組 , 數 組 元 素 個 數 由 巨集OS_CFG_TICK_WHEEL_SIZE 定義,巨集 OS_CFG_TICK_WHEEL_SIZE os_cfg_app.h 中定義了。表 OSCfg_TickWheel 中的元素為 os_tick_spoke 型別的, os_tick_spoke 是一個結構體,結構體定義如下:
struct os_tick_spoke {
OS_TCB *FirstPtr;
OS_OBJ_QTY NbrEntries;
OS_OBJ_QTY NbrEntriesMax;
};
FirstPtr: 指標變數,在表頭上並屬於該表。
NbrEntries: 表示在該表項上等待的任務的數目。
NbrEntriesMax: 表示在該表項上等待的任務的最大數目。
在使用時鐘節拍列表時需要先初始化時鐘節拍列表,在
OS_TickTaskInit()函式中會呼叫OS_TickListInit 來初始化時鐘節拍列表 。
3.統計任務  UCOSIII 中統計任務可用來統計 CPU 的使用率、各個任務的 CPU 使用率和各任務的堆疊使用情況,預設情況下統計任務是不會建立的,如果要使能統計任務的話需要將巨集
OS_CFG_STAT_TASK_EN 1,巨集 OS_CFG_STAT_TASK_EN os_cfg.h 檔案中有定義。

OS_StatTaskInit() 函 數 用 來 創 建 統 計 任 務 , 統 計 任 務 的 優 先 級 通 過 巨集OS_CFG_STAT_TASK_PRIO 設 置  。 如果要使用統計任務的話就需要在 main()函式建立的第一個也是唯一一個應用任務中呼叫OSStatTaskCPUUsageInit()函式。  #if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err); //統計任務
#endif
建立其他任務只能在
OSStatTaskCPUUsageInit()函式之後。CPU 的總的使用率會儲存在變數 OSStatTaskCPUUsage 中,我們可以通過讀取這個值來獲取 CPU 的使用率。

V3.03.00 版本起, CPU 的使用率 0~10000 之間的整數 。在這之前的版本,CPU 使用率是 0~100 之間的整數表示。  4.定時任務
UCOSIII 提供軟體定時器功能,定時任務是可選的,將巨集 OS_CFG_TMR_EN 設定為 1 就會使能定時任務,在 OSInit()中將會呼叫函式 OS_TmrInit()來建立定時任務。定時任務的優先順序通過巨集 OS_CFG_TMR_TASK_PRIO 定義。 5.中斷服務管理任務
當把 os_cfg.h 檔案中的巨集 OS_CFG_ISR_POST_DEFERRED_EN 1 就會使能中斷服務管理任務, UCOSIII 會建立一個名為 OS_IntQTask()的任務,該任務負責“延遲”在 ISR 中呼叫的系統 post 服務函式的行為。中斷服務管理任務的任務優先順序永遠是最高的,為 0  ISR(中斷服務函式)呼叫 UCOSIII 提供的“ post”函式時,要傳送的資料和傳送的目的地都會存入一個特別的緩衝佇列中,當所有巢狀的 ISR 都執行完成以後 UCOSIII 會做任務切換,執行中斷服務管理任務,該任務會把快取佇列中存放的資訊重發給相應的任務。這樣做的好處就是可以減少中斷關閉的時間,否則,在 ISR 中還需要把任務從等待列表中刪除,並把任務放入就緒表,以及做一些其他的耗時操作。