uC/OS-II之系統函數

原文地址:博客園

任務管理

1 OSTaskCreate()

建立一個新任務。任務的建立可以在多任務環境啓動之前,也可以在正在運行的任務中建立。中斷處理程序中不能
建立任務。一個任務可以爲無限循環的結構。

函數原型:INT8U OSTaskCreate(void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio);

參數說明:task 是指向任務代碼首地址的指針。

pdata 指向一個數據結構,該結構用來在建立任務時向任務傳遞參數。

ptos is a pointer to the task’s top of stack. If the configuration constant OS_STK_GROWTH is
set to 1, the stack is assumed to grow downward (i.e. from high memory to low memory). ‘pstk’ will thus
point to the highest (valid) memory location of the stack. If OS_STK_GROWTH is set to 0, ‘pstk’ will
point to the lowest memory location of the stack and the stack will grow with increasing memory
locations.

prio is the task’s priority. A unique priority MUST be assigned to each task and the lower the
number, the higher the priority.

返回值:

OSTaskCreate() 的返回值爲下述之一:

  • OS_NO_ERR:函數調用成功。

  • OS_PRIO_EXIST:具有該優先級的任務已經存在。

  • OS_PRIO_INVALID:參數指定的優先級大於OS_LOWEST_PRIO。

  • OS_NO_MORE_TCB:系統中沒有OS_TCB可以分配給任務了。

2 OSTaskSuspend()

無條件掛起一個任務。調用此函數的任務也可以傳遞參數 OS_PRIO_SELF,掛起調用任務本身。當前任務掛起後,
只有其他任務才能喚醒被掛起的任務。任務掛起後,系統會重新進行任務調度,運行下一個優先級最高的就緒任務。喚
醒掛起任務需要調用函數OSTaskResume()。

任務的掛起是可以疊加到其他操作上的。例如,任務被掛起時正在進行延時操作,那麼任務的喚醒就需要兩個條件
:延時的結束以及其他任務的喚醒操作。又如,任務被掛起時正在等待信號量,當任務從信號量的等待對列中清除後也
不能立即運行,而必須等到被喚醒後。

函數原型:INT8U OSTaskSuspend(INT8U prio);

參數說明:prio爲指定要獲取掛起的任務優先級,也可以指定參數 OS_PRIO_SELF,掛起任務本身。此時,下一個優先
級最高的就緒任務將運行。

返回值:

OSTaskSuspend() 的返回值爲下述之一:

  • OS_NO_ERR:函數調用成功。

  • OS_TASK_SUSPEND_IDLE:試圖掛起μC/OS-II中的空閒任務(Idle task)。此爲非法操作。

  • OS_PRIO_INVALID:參數指定的優先級大於 OS_LOWEST_PRIO 或沒有設定 OS_PRIO_SELF 的值。

  • OS_TASK_SUSPEND_PRIO:要掛起的任務不存在。

3 OSTaskResume()

喚醒一個用 OSTaskSuspend() 函數掛起的任務。OSTaskResume() 也是唯一能“解掛”掛起任務的函數。

函數原型:INT8U OSTaskResume(INT8U prio);

參數說明:prio指定要喚醒任務的優先級。

返回值:

OSTaskResume() 的返回值爲下述之一:

  • OS_NO_ERR:函數調用成功。

  • OS_TASK_RESUME_PRIO:要喚醒的任務不存在。

  • OS_TASK_NOT_SUSPENDED:要喚醒的任務不在掛起狀態。

  • OS_PRIO_INVALID:參數指定的優先級大於或等於OS_LOWEST_PRIO。

信號量

1 OSSemCreate()

該函數建立並初始化一個信號量,信號量的作用如下:

  • 允許一個任務和其他任務或者中斷同步

  • 取得設備的使用權

  • 標誌事件的發生

函數原型:OS_EVENT *OSSemCreate(INT16U value);

參數說明:value 參數是所建立的信號量的初始值,可以取0到65535之間的任何值。

返回值:

OSSemCreate() 函數返回指向分配給所建立的信號量的控制塊的指針。如果沒有可用的控制塊,OSSemCreate() 函數返
回空指針。

2 OSSemPend()

該函數用於任務試圖取得設備的使用權、任務需要和其他任務或中斷同步、任務需要等待特定事件的發生的場合。
如果任務調用OSSemPend() 函數時,信號量的值大於零,OSSemPend() 函數遞減該值並返回該值。如果調用時信號量值
等於零,OSSemPend() 函數將任務加入該信號量的等待隊列。OSSemPend() 函數掛起當前任務直到其他的任務或中斷設
置信號量或超出等待的預期時間。如果在預期的時鐘節拍內信號量被設置,μC/OS-Ⅱ默認讓最高優先級的任務取得信
號量並回到就緒狀態。一個被OSTaskSuspend() 函數掛起的任務也可以接受信號量,但這個任務將一直保持掛起狀態直
到通過調用OSTaskResume() 函數恢復該任務的運行。

函數原型:void OSSemPend ( OS_EVNNT *pevent, INT16U timeout, int8u *err );

參數說明:pevent 是指向信號量的指針。該指針的值在建立該信號量時可以得到。(參考OSSemCreate() 函數)。

timeout 允許一個任務在經過了指定數目的時鐘節拍後還沒有得到需要的信號量時恢復就緒狀態。如果該值
爲零表示任務將持續地等待信號量,最大的等待時間爲65535個時鐘節拍。這個時間長度並不是非常嚴格的,可能存在
一個時鐘節拍的誤差。

err 是指向包含錯誤碼的變量的指針,返回的錯誤碼可能爲下述幾種:

  • OS_NO_ERR :信號量不爲零。

  • OS_TIMEOUT :信號量沒有在指定數目的時鐘週期內被設置。

  • OS_ERR_PEND_ISR :從中斷調用該函數。雖然規定了不允許從中斷調用該函數,但μC/OS-Ⅱ仍然包含
    了檢測這種情況的功能。

  • OS_ERR_EVENT_TYPE :pevent 不是指向信號量的指針。

返回值:無

3 OSSemPost()

該函數用於設置指定的信號量。如果指定的信號量是零或大於零,OSSemPost() 函數遞增該信號量的值並返回。如
果有任何任務在等待該信號量,則最高優先級的任務將得到信號量並進入就緒狀態。任務調度函數將進行任務調度,決
定當前運行的任務是否仍然爲最高優先級的就緒任務。

函數原型:INT8U OSSemPost(OS_EVENT *pevent);

參數說明:pevent 是指向信號量的指針。該指針的值在建立該信號量時可以得到。(參考OSSemCreate() 函數)。

返回值:

OSSemPost() 函數的返回值爲下述之一:

  • OS_NO_ERR :信號量被成功地設置

  • OS_SEM_OVF :信號量的值溢出

  • OS_ERR_EVENT_TYPE :pevent 不是指向信號量的指針

時間

1 OSTimeDly()

該函數用於將一個任務延時若干個時鐘節拍。如果延時時間大於0,系統將立即進行任務調度。延時時間的長度可
從0到65535個時鐘節拍。延時時間0表示不進行延時,函數將立即返回調用者。延時的具體時間依賴於系統每秒鐘有多
少個時鐘節拍(由文件OS_CFG.H中的OS_TICKS_PER_SEC宏來設定)。

函數原型:void OSTimeDly (INT16U ticks);

參數說明:ticks 爲要延時的時鐘節拍數。

返回值:無

2 OSTimeDlyHMSM()

該函數用於將一個任務延時若干時間。延時的單位是小時、分、秒、毫秒。調用 OSTimeDlyHMSM() 後,如果延時
時間不爲0,系統將立即進行任務調度。

函數原型: INT8U OSTimeDlyHMSM (INT8U hours,INT8U minutes,INT8U seconds,INT16U milli);

參數說明:hours 爲延時小時數,範圍從0-255。

minutes 爲延時分鐘數,範圍從0-59。

seconds 爲延時秒數,範圍從0-59

milli 爲延時毫秒數,範圍從0-999。

需要說明的是,操作系統在處理延時操作時都是以時鐘節拍爲單位的,實際的延時時間是時鐘節拍的整數倍。如果
系統時鐘節拍的間隔是10ms,而設定延時爲5ms的話,則不會產生延時操作;而如果設定延時爲15ms,則實際的延時是
兩個時鐘節拍,也就是20ms。

返回值:

OSTimeDlyHMSM() 的返回值爲下述之一:

  • OS_NO_ERR:函數調用成功。

  • OS_TIME_INVALID_MINUTES:參數錯誤,分鐘數大於59。

  • OS_TIME_INVALID_SECONDS:參數錯誤,秒數大於59。

  • OS_TIME_INVALID_MILLI:參數錯誤,毫秒數大於999。

  • OS_TIME_ZERO_DLY:四個參數全爲0。

內存管理

1 OSMemCreate()

該函數建立並初始化一個用於動態內存分配的區域,該內存區域包含指定數目的、大小確定的內存塊。應用可以動
態申請這些內存塊並在用完後將其釋放回這個內存區域。該函數的返回值就是指向這個內存區域控制塊的指針,並作爲
OSMemGet(),OSMemPut(),OSMemQuery() 等相關調用的參數。

函數原型:OS_MEM *OSMemCreate( void *addr, INT32U nblks, INT32U blksize, INT8U *err );

參數說明:addr 建立的內存區域的起始地址。可以使用靜態數組或在系統初始化時使用 malloc() 函數來分配這個區
域的空間。

nblks 內存塊的數目。每一個內存區域最少需要定義兩個內存塊。

blksize 每個內存塊的大小,最小應該能夠容納一個指針變量。

err 是指向包含錯誤碼的變量的指針。Err可能是如下幾種情況:

  • OS_NO_ERR :成功建立內存區域。

  • OS_MEM_INVALID_ADDR :非法地址,即地址爲空指針。

  • OS_MEM_INVALID_PART :沒有空閒的內存區域。

  • OS_MEM_INVALID_BLKS :沒有爲內存區域建立至少兩個內存塊。

  • OS_MEM_INVALID_SIZE :內存塊大小不足以容納一個指針變量。

返回值:

OSMemCreate() 函數返回指向所創建的內存區域控制塊的指針。如果創建失敗,函數返回空指針。

2 OSMemGet()

該函數用於從內存區域分配一個內存塊。用戶程序必須知道所建立的內存塊的大小,並必須在使用完內存塊後釋放
它。可以多次調用 OSMemGet() 函數。它的返回值就是指向所分配內存塊的指針,並作爲 OSMemPut() 函數的參數。

函數原型:void *OSMemGet(OS_MEM *pmem, INT8U *err);

參數說明:pmem 是指向內存區域控制塊的指針,可以從 OSMemCreate() 函數的返回值中得到。

err 是指向包含錯誤碼的變量的指針。Err可能是如下情況:

  • OS_NO_ERR :成功得到一個內存塊。

  • OS_MEM_NO_FREE_BLKS :內存區域中已經沒有足夠的內存塊。

返回值:

OSMemGet() 函數返回指向所分配內存塊的指針。如果沒有可分配的內存塊,OSMemGet() 函數返回空指針。

3 OSMemPut()

該函數用於釋放一個內存塊,內存塊必須釋放回它原先所在的內存區域,否則會造成系統錯誤。

函數原型:INT8U OSMemPut (OS_MEM *pmem, void *pblk);

參數說明:pmem 是指向內存區域控制塊的指針,可以從 OSMemCreate() 函數的返回值中得到。

pblk 是指向將被釋放的內存塊的指針。

返回值:

OSMemPut() 函數的返回值爲下述之一:

  • OS_NO_ERR :成功釋放內存塊

  • OS_MEM_FULL :內存區域已滿,不能再接受更多釋放的內存塊。這種情況說明用戶程序出現了錯誤,釋放了多於用
    OSMemGet() 函數得到的內存塊。

4 OSMemQuery()

該函數用於得到內存區域的信息。

函數原型:INT8U OSMemQuery(OS_MEM *pmem, OS_MEM_DATA *pdata);

參數說明:pmem 是指向內存區域控制塊的指針,可以從 OSMemCreate() 函數的返回值中得到。

pdata 是一個指向 OS_MEM_DATA 數據結構的指針,該數據結構包含了以下的域:

void OSAddr; /* 指向內存區域起始地址的指針 */

void OSFreeList; /* 指向空閒內存塊列表起始地址的指針 */

INT32U OSBlkSize; /* 每個內存塊的大小 */

INT32U OSNBlks; /* 該內存區域中的內存塊總數 */

INT32U OSNFree; /* 空閒的內存塊數目 */

INT32U OSNUsed; /* 已使用的內存塊數目 */

消息隊列

1 OSQCreate()

該函數用於建立一個消息隊列。任務或中斷可以通過消息隊列向一個或多個任務發送消息。消息的含義是和具體的
應用密切相關的。

函數原型:OS_EVENT *OSQCreate (void **start, INT8U size);

參數說明:start 是消息內存區的首地址,消息內存區是一個指針數組。

size 是消息內存區的大小。

返回值:

OSQCreate() 函數返回一個指向消息隊列控制塊的指針。如果沒有空閒的控制塊,OSQCreate() 函數返回空指針。

2 OSQPend()

該函數用於任務等待消息。消息通過中斷或任務發送給需要的任務。消息是一個指針變量,在不同的應用中消息的
具體含義不同。如果調用 OSQPend() 函數時隊列中已經存在消息,那麼該消息被返回給 OSQPend() 函數的調用者,該
消息同時從隊列中清除。如果調用 OSQPend() 函數時隊列中沒有消息,OSQPend() 函數掛起調用任務直到得到消息或
超出定義的超時時間。如果同時有多個任務等待同一個消息,μC/OS-Ⅱ默認最高優先級的任務取得消息。一個由
OSTaskSuspend() 函數掛起的任務也可以接受消息,但這個任務將一直保持掛起狀態直到通過調用 OSTaskResume() 函
數恢復任務的運行。

函數原型:void *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err);

參數說明:pevent 是指向消息隊列的指針,該指針的值在建立該隊列時可以得到。(參考 OSQCreate() 函數)。

timeout 允許一個任務以指定數目的時鐘節拍等待消息。超時後如果還沒有得到消息則恢復成就緒狀態。如
果該值設置成零則表示任務將持續地等待消息,最大的等待時間爲65535個時鐘節拍。這個時間長度並不是非常嚴格的
,可能存在一個時鐘節拍的誤差。

err 是指向包含錯誤碼的變量的指針。OSQPend() 函數返回的錯誤碼可能爲下述幾種:

  • OS_NO_ERR :消息被正確地接受。

  • OS_TIMEOUT :消息沒有在指定的時鐘週期數內接收到消息。

  • OS_ERR_PEND_ISR :從中斷調用該函數。雖然規定了不允許從中斷中調用該函數,但μC/OS-Ⅱ仍然包
    含了檢測這種情況的功能。

  • OS_ERR_EVENT_TYPE :pevent 不是指向消息隊列的指針。

返回值:

OSQPend() 函數返回取得的消息並將 *err 置爲 OS_NO_ERR。如果沒有在指定數目的時鐘節拍內接受到消息,OSQPend
() 函數返回空指針並將 *err 設置爲 OS_TIMEOUT。

3 OSQPostFront()

該函數用於向消息隊列發送消息。OSQPostFront() 函數和 OSQPost() 函數非常相似,不同之處在於
OSQPostFront() 函數將發送的消息插到消息隊列的最前端。也就是說,OSQPostFront() 函數使得消息隊列按照後入先
出(LIFO)的方式工作,而不是先入先出(FIFO)。消息是一個指針長度的變量,在不同的應用中消息的含義也可能不
同。如果隊列中已經存滿消息,則此調用將返回錯誤碼。OSQPost() 函數也是如此。在調用此函數時如果有任何任務在
等待隊列中的消息,則最高優先級的任務將得到這個消息。如果等待消息的任務優先級比發送消息的任務優先級高,那
麼高優先級的任務在得到消息後將立即搶佔當前任務執行,也就是說,將發生一次任務切換。

函數原型:INT8U OSQPostFront(OS_EVENT *pevent, void *msg);

參數說明:pevent 是指向即將接收消息的消息隊列的指針。該指針的值在建立隊列時可以得到。(參考 OSQCreate()
函數)。

msg 是即將發送的消息的指針。不允許傳遞一個空指針。

返回值:

OSQPostFront() 函數的返回值爲下述之一:

  • OS_NO_ERR :消息成功地放到消息隊列中。

  • OS_Q_FULL :消息隊列已滿。

  • OS_ERR_EVENT_TYPE :pevent 不是指向消息隊列的指針。

4 OSQPost()

該函數用於向消息隊列發送消息。消息是一個指針長度的變量,在不同的應用中消息的含義也可能不同。如果隊列
中已經存滿消息,則此調用返回錯誤碼。如果有任何任務在等待隊列中的消息,則最高優先級的任務將得到這個消息。
如果等待消息的任務優先級比發送消息的任務優先級高,那麼高優先級的任務將在得到消息後立即搶佔當前任務執行,
也就是說,將發生一次任務切換。消息是以先入先出(FIFO)方式進入隊列的,即先進入隊列的消息先被傳遞給任務。

函數原型:INT8U OSQPost(OS_EVENT *pevent, void *msg);

參數說明:pevent 是指向即將接受消息的消息隊列的指針。該指針的值在建立隊列時可以得到。(參考 OSQCreate()
函數)。

msg 是即將發送給隊列的消息。不允許傳遞一個空指針。

返回值:

OSQPost() 函數的返回值爲下述之一:

  • OS_NO_ERR :消息成功地放到消息隊列中。

  • OS_Q_FULL :消息隊列已滿。

  • OS_ERR_EVENT_TYPE :pevent 不是指向消息隊列的指針。

5 OSQFlush()

該函數用於清空消息隊列。

函數原型:INT8U *OSQFlush(OS_EVENT *pevent);

參數說明:pevent 是指向消息隊列的指針。該指針的值在建立隊列時可以得到。(參考 OSQCreate() 函數)。

返回值:

OSQFlush() 函數的返回值爲下述之一:

  • OS_NO_ERR :消息隊列被成功清空

  • OS_ERR_EVENT_TYPE :試圖清除不是消息隊列的對象

6 OSQQuery()

該函數用來取得消息隊列的信息。用戶程序必須建立一個 OS_Q_DATA 的數據結構,該結構用來保存從消息隊列的
控制塊得到的數據。通過調用該函數可以知道是否有任務在等待消息、有多少個任務在等待消息、隊列中有多少消息以
及消息隊列可以容納的消息數。OSQQuery() 函數還可以得到即將被傳遞給任務的消息。

函數原型:INT8U OSQQuery(OS_EVENT *pevent, OS_Q_DATA *pdata);

參數說明:pevent 是指向消息隊列的指針。該指針的值在建立消息隊列時可以得到。(參考 OSQCreate() 函數)。

pdata 是指向 OS_Q_DATA 數據結構的指針,該數據結構包含下述成員:

void OSMsg; / 下一個可用的消息 */

INT16U OSNMsgs; /* 隊列中的消息數目 */

INT16U OSQSize; /* 消息隊列的大小 */

INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* 消息隊列的等待隊列 */

INT8U OSEventGrp;

返回值:

OSQQuery() 函數的返回值爲下述之一:

  • OS_NO_ERR :調用成功

  • OS_ERR_EVENT_TYPE :pevent 不是指向消息隊列的指針。

7 OSQDel()

該函數用於刪除指定的消息隊列。

系統管理函數:

1.OSStatInit();

/* Determine CPU capacity after systick start,before other tasks be created */

使能任務統計功能,OSStatInit()要在建立的第一個,並且只有一個任務的時候調用,這樣做是因爲統計任務計算CPU利
用率的需要, 調用這個函數要注意,主要原因就是因爲在OSStatInit()中調用OSTimeDly發生了任務的調度,所以做嵌入
式應用時,用戶必須在第一個任務中打開時鐘節拍中斷,即after systick start
CPU利用率的計算由μC/OS-II 中的OSStatTask()函數來完成,這個任務每秒執行一次。而當OSStatRdy置爲TRUE表示μ
C/OS-II將統計CPU的利用率。

2.OSSchedLock();###

作用:調度上鎖函數
描述:阻止再次調度發生,它讓你準備執行任務切換的時候才進行任務切換
參數:無

因爲任務調度時一般都是通過OSTIMEDLY()來實現。在這個函數中會對當前的任務執行掛起。同時查看任務調度表中是否有優先級合適的就緒任務。如果當前任務運行時調用OSSchedLock()給調度器上鎖,這樣再調用OSTIMEDLY()時就會把當前任務掛起。但由於調度器上鎖而不能使其他任務得到CPU的使用權。這樣除了中斷意外就沒有任務可以運行了。除非中斷中對這種情況有處理。
必須調用OSSchedLock() and OSSchedUnlock()必須成對出現

3.SysTick_Config(SystemCoreClock/1000);

這個函數打開了SysTick的中斷,同時也設置了Systick的重裝載寄存器。

SystemCoreClock/1000既是系通時鐘頻率的千分之一。也就是說每秒鐘,Systick寄存器會裝滿1000次,每次1ms。這就
是計時的基礎單位了。當重裝載寄存器裝滿時,就會產生Systick中斷,之後我們就在中斷函數中處理:在文件
stm32F4xx_it.c中添加一點Systick的中斷處理函數SysTick Handler 滴答定時器,爲(配置)操作系統內核時鐘

//ucosii時鐘頻率200hz,即1m 200個ticks時鐘節拍
//延時2個ticks,也就是2/200=10ms
OSTimeDly(2); /* Synchronize with clock tick */

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章