五、從睡眠態到就緒態
睡眠態到就緒態呼叫ostaskcreate()或者ostaskcreateext()建立乙個任務,在多任務排程前 (也就是呼叫osstart()) 必須要建立乙個應用任務(除去空閒任務和統計任務)。
任務建立過程:
(1)首先對ostaskcreate((void(*task))(void *pd),void *pdate,os_stk *ptos,int8u prio)引數賦值!
*task(指向任務**起始位址的指標)
*pdate(給task(*pdata)傳遞的引數的指標)
*ptos(起始棧頂位置,如果堆疊屬於從高位址向低位址方向增長的,那麼*ptos應該等於&taskstack[task_stack_size-1].如果是從低位址向高位址方向增長,那麼*ptos的值等於&taskstack[0].)
prio(該任務的優先順序)
(2)判斷設定的優先順序是否已經存在。
ostcbpriotbl[prio]= =(os_tcb*)0 :這就表明該優先順序的任務還不存在
解釋:ostcbpriotbl是乙個指標陣列,作用例如ostcbpriotbl[2],他代表的是指向任務優先順序為2的任務的任務控制塊,而ostcbpriotbl[prio]= =(os_tcb*)0代表的是指向優先順序prio的指標為空,沒有指向任務快,這就表明該優先順序的任務還不存在。
(3)為任務分配任務堆疊並初始化,呼叫函式ostaskinit(task,pdata,ptos,0)
ptos初始棧頂位置,這樣就知道該任務堆疊在記憶體的位置。然後將task(指向任務**起始位址 ) pdate(給task(*pdata)傳遞的引數值)壓入堆疊,還有r14—r0也要入堆疊。然後將現在的堆疊棧頂指標返回給變數psp。
(4)為任務分配tcb並初始化。呼叫函式os_tcbinit( prio,psp,(void*)0,0,0,(void*)0,0)
將優先順序和(psp)棧頂位置傳給os_tcbinit,用來建立tcb..
(5)然後呼叫os_sched()。 注:我認為只要某個函式裡面有對優先順序改變的,都要用到os_sched(),因為uc/osii屬於搶占式作業系統,因此cpu總是為優先順序最高的任務服務,那麼當每次改變任務優先順序後,都要os_sched()用檢查有沒有新的最高優先順序任務出現,如果有的話就將cpu分配給該任務。
ostaskcreateext()與上面類似。
六、從就緒態到執行狀態 以及從執行態都就緒態。
就緒態到執行狀態呼叫到的 函式os_sched(void)相當於乙個任務排程器。
os_sched(void)操作就兩大塊,
第一是從就緒表中osrdygrp和osrdytbl[ ]找到最高優先順序的任務。所以通過
y=osunmaptbl[osrdygrp]
x= osunmaptbl[osrdytbl[y]]
最大prio=int((y<<3)+x)
第二步就是將cpu分配給該任務。
ostcbhighrdy= ostcbpriotbl[prio]//ostcbhighrdy指向高優先順序的任務。
然後呼叫os_task_sw( )函式將cpu的暫存器狀態壓入低優先順序任務,並將ostcbcur= ostcbhighrdy 也就是將ostcbcur指向高優先順序的任務(ostcbcur總是指向正在執行的任務),然後將高優先順序任務的堆疊內容賦給cpu的暫存器,然後該任務執行。
從執行態都就緒態
同樣是是是函式os_sched(void),當有乙個新最高端的任務出現在就緒佇列中,那麼正在執行的任務將會被取代,轉而進人就緒態。
七、從執行態到等待狀態
從執行態到等待狀態,分為三種:
第一種是掛起函式,ostasksupend(),任務掛起是乙個附加功能,把任務從就緒表中移除,進入等待狀態。
第二種是ostimedly()函式,它是將任務本身延時一定時間,這個函式其實就是對tcb中的ostcbdly變數進行賦值且把任務從就緒表中移除,進入等待狀態。然後通過用ostimetick()對每個tcb的ostcbdly(非0值的)每過隔乙個接拍就減一,直至為0,表明延時結束,然後將該任務恢復到就緒態。
第三種是等待某一事件的發生時,呼叫以下幾個函式:osflagpend()、ossempend(),osmutexpend()、osmboxpend(),如果該事件發生了,那麼該任務繼續執行,如果該事件沒有發生,那麼將自身掛起,因而處於等待或掛起態。
與上面不同,不僅要從就緒表中移除該任務,還要將任務新增到相應事件ecb的等待列表osevengrp和 oseventbl[ ]中(就像就緒表一樣,等待列表允許多個任務,也就是可能有多個任務同時等待乙個事件發生)。
所有的通訊訊號都被看成乙個事件。
事件分為:訊號量、互斥訊號量,訊息郵箱、佇列訊息。每乙個訊號量、互斥訊號量,訊息郵箱、訊息佇列都會分配到乙個事件控制塊ecb.
ecb的結構如下
typedef struct{
void *oseventptr //指向訊號的指標
int8u oseventcnt //計數器,用於事件是訊號量。
int8u oseventtype //事件的型別(如訊號量,互斥訊號量,佇列訊息等)
int8u oseventgrp //等待任務組
int8u oseventtbl[ ] //等待任務列表 }
每個ecb都會有 事件的等待列表osevengrp和 oseventbl[ ] ,它與就緒表中osrdygrp和osrdytbl[ ]極為相似。
uC OSii 的學習筆記 2
五 從睡眠態到就緒態 睡眠態到就緒態呼叫ostaskcreate 或者ostaskcreateext 建立乙個任務,在多任務排程前 也就是呼叫osstart 必須要建立乙個應用任務 除去空閒任務和統計任務 任務建立過程 1 首先對ostaskcreate void task void pd void...
ucosII學習筆記
以前很少接觸過嵌入式作業系統,這次因為要嘗試研究ucosii這個嵌入式作業系統,看看自己能不能盡快的會使用它,查詢了不少資料。ucosii學習筆記。以下是nathan.yu的 ucosii學習筆記 整理的不錯,自己先借鑑。ucosii學習筆記 by nathan.yu ucos ii特性 l 可剝奪...
UCOS II學習筆記
1.標頭檔案的配置 include stm32f10x.h include stm32f10x conf.h include ucos ii.h 2.任務堆疊配置 os stk led0 task stk 64 os stk led1 task stk 64 定義兩個任務的堆疊陣列 3.對硬體的配置...