You are on page 1of 28

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.

tw
或來電(02)2705-5066

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw
或來電(02)2705-5066


眾所皆知,把計算機系統嵌入多媒體設備、洗衣機、照相機、冷氣機、飛機、
汽車等中,會使它們的自動化程度大為提高,並使之在功用上發生革命性的飛躍,
這無疑會給人們帶來不可抗拒的誘惑。
也因此引發了關於什麼是嵌入式系統,嵌入式系統具有什麼樣的特點以及如何
在相關的專業教學系統中引入嵌入式系統教學內容的討論。
嵌入式系統仍然屬於計算機系統,只是具有應用上的一些特點,以及為適應嵌
入式應用而在微處理器結構及其軟體上與通用計算機相比較有某種變化的計算機系
統。面對嵌入式系統的廣泛應用,需要應立即對計算機教學體系進行必要的改變,
以適應產業界的需要。
在對大專院校相關專業的課程體系及課程內容進行仔細分析,並與同行進行了
廣泛的討論之後,作者認為在以下三方面對現有課程體系及課程內容進行適當的改
變,就足以滿足嵌入式系統教學的需要:
•改變計算機硬體課程內容。目前,嵌入式處理器在硬體功能上已經比較接近
通用處理器晶片了。因此,對資訊、資工、電機專業來說,在現有的計算機
硬體課程的基礎上,增加嵌入式處理器的內容為完全可行;對於自動控制機
電、電子等非資工、資訊、電機專業,則可以把以前的單片機課程改為以嵌
入式處理器(系統)為主要內容的課程,而把現在應用面仍然很廣且適合低
端嵌入式應用的單片機(單片機也是嵌入式應用)的內容進行適當壓縮,作
為輔助內容讓學生自修。
•根據嵌入式系統的開發特點,增設一門以介紹即時系統、交叉編譯及代碼優
化等與嵌入式系統軟件開發技術方面為主的課程。
•改變計算機操作系統課程。
本書共 10 章,參加本書編寫的作者有潘樹林、房紅征和任哲,由任哲擔任主編
並負責全書的統稿工作。
在本書的策劃和編寫過程中,得到了很多同事的關心、指導和幫助。特別是在
本書的第 10 章關於 μC/OS-II 在 ARM 上移植中使用了周立功先生的方法和程序代
碼,在部分章節還使用了 Jean J. Labrosse 先生的部分例題代碼。在編寫本書的過

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw
或來電(02)2705-5066

程中,作者還參閱了大量的參考書籍,並在本書中引用了這些書籍的一些文字和插
圖。為此,本書作者向為本書作出貢獻的人們表示最誠摯的謝意!
在《即時嵌入式系統 μC/OS-II》出版之際,想說明如下二點:
1. 對於尖端軟體設計的人才,學習操作系統有意義嗎?
太有意義了,因為你設計的軟體在運行時,操作系統是你的應用程式的一部分
(只不過不是你設計的罷了)。如果你對使用的操作系統不了解,那你知道它為你做
了些什麼你不需要的工作?你用什麼向客戶說明你的軟體是安全的?你用什麼來保
證當系統升級時,你的軟體是兼容的?
2. 對於硬體研究的人才,學習操作系統有意義嗎?
現在硬體研究人才沒有辦法不接觸軟體的。試想,要設計一個硬體驅動程式,
你能夠不了解操作系統的設備管理嗎?尤其是在嵌入式系統應用如此廣泛的今天,
你具備嵌入式操作系統的運用、裁剪及改造能力嗎?你能成為一個合格的嵌入式工
程師嗎?
本書無論是在教學內容的選取編排上,還是對於難點、重點的講解上,一定
會有很多不足甚至是錯誤,在此誠摯希望讀者能提出批評指正。作者的電子信箱:
renzhe71@sina.com。

作者 任哲

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw
或來電(02)2705-5066

目 錄

1

2

1

即時嵌入式系統 μC/OS-II 及其任務

1

1.1 何謂 μC/OS-II

2

1.2 μC/OS-II 的任務

8

1.3 μC/OS-II 任務的儲存結構

9

1.4 μC/OS-II 任務的狀態

11

1.5 μC/OS-II 任務的優先順序別

12

1.6 任務控制塊

13

1.7 任務堆疊

17

1.8 系統任務

22

1.9 臨界區

24

μC/OS-II 的任務管理

25

2.1 就緒任務的管理

26

2.2 任務的創造

32

2.3 任務的掛起和恢復

40

2.4 其他任務管理函數

43

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw
或來電(02)2705-5066

3
4
5
6

μC/OS-II 的任務調度

49

3.1 調度器 OSSched( ) 的任務調度部分

50

3.2 調度器 OSSched( ) 的任務切換部分

52

μC/OS-II 的初始化和啟動

59

4.1 μC/OS-II 的初始化

60

4.2 μC/OS-II 的啟動

63

μC/OS-II 的中斷與時序

77

5.1 μC/OS-II 的中斷

78

5.2 μC/OS-II 的時序

85

5.3 μC/OS-II 的時間管理

88

任務的同步與通訊
6.1 任務間的同步和事件控制塊

93
94

6.2 訊號量及其操作

116

6.3 任務優先順序反轉和互斥型訊號量

128

6.4 消息郵件及其操作

138

6.5 消息佇列及其操作

146

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw
或來電(02)2705-5066

7
8
9
10

訊號量集

159

7.1 訊號量集的結構

160

7.2 訊號量集的操作

166

μC/OS-II 其他相關問題

171

8.1 記憶體控制塊

172

8.2 記憶體的管理

175

訊號量集

183

9.1 關於 μC/OS-II 的幾個問題

184

9.2 μC/OS-II 在 PC 機上的測試台

184

9.3 μC/OS-II 在 PC 機上的移植

186

基於 ARM 的 μC/OS-II

197

10.1 移植規劃

198

10.2 移植

198

10.3 移植 μC/OS-II 到 LPC2000

216

參考文獻

221

索引

223

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw
或來電(02)2705-5066

1
即時嵌入式系統
μC/OS-II 及其任務
μC/OS-II 是一種小型的嵌入式作業系統,提供了任務管理、任務的通訊同步
和簡單的儲存管理三項基本服務。

學 習 重 點
1.1 何謂 μC/OS-II
1.2 μC/OS-II 的任務
1.3 μC/OS-II 任務的儲存結構
1.4 μC/OS-II 任務的狀態
1.5 μC/OS-II 任務的優先順序別
1.6 任務控制塊
1.7 任務堆疊
1.8 系統任務
1.9 臨界區

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw
或來電(02)2705-5066

1. 即時嵌入式系統 μC/OS–II 及其任務

1.1 何謂 μC/OS-II
在所有的嵌入式作業系統的軟體中,μC/OS-II 是規模最小的系統之一,它事
實上就是一個微內核(micro core),為了要提高 μC/OS-II 的可攜性,除了與硬體
關係極為緊密的軟體模組不得不使用組合語言編寫之外,μC/OS-II 的決大多數代
碼都是使用 C 語言。

1. μC/OS-II 的特點
μC/OS-II 的開發者是 Jean Labrosse,他於 1 年推出了叫做 μC/OS 的第一
個版本,後來,在此一基礎上經過修改和擴充之後又推出了第二版,稱為 μC/
OS-II,此一版本以其精巧、實用而廣泛的受到了業界及教育界的歡迎。
μC/OS-II 的體系結構如圖 1-1 所示,μC/OS-II 為一個微內核,只對電腦的處
理器和硬體時鐘進行了抽象和封裝,而沒有提供其他的硬體外接部份。

用戶應用程序
與處理器無關的代碼


應用程序相關的代碼

與處理器相關代碼
(移植時需要修改)
定時器

圖 1-1 是 μC/OS-II 體系結構

主要原因是 μC/OS-II 的開發者認為,做為一個嵌入式系統,在不同的應用
中,主物件具有差異極大的硬體結構,它們的硬體部分只能由硬體供應商或者是
目標系統的開發者提供或者開發。而做為嵌入式作業系統的開發者是沒有辦法,
也沒有必要提供所有的硬體外接部份。正因為此一原因,使得 μC/OS-II 具有了 

本試閱檔為五南所有。如欲購買此書,請至五南網站
www.wunan.com.tw
或來電(02)2705-5066

1.1 何謂 μC/OS–II
較強的可攜性,也就是說,在移動 μC/OS-II 時,主要工作就是根據具體硬體,
置換一個或者添加一個硬體外接部份就可以了,而需要添加的硬體外接部份與
μC/OS-II 之間的關係,如圖 1- 陰影部分所示。

用戶應用程序

應用程序相關的代碼

與處理器無關的代碼

需要添加的
硬件抽象層

與處理器相關代碼
(移植時需要修改)
定時器

系統的其他
硬件

圖 1-2 μC/OS-II 需要添加的其他硬件抽象層

由於 μC/OS-II 是植基於優先順序的可內核,系統中的所有任務都有一個並
且唯一的優先順序別,適合應用在即時性要求較強的場合。此外,μC/OS-II 的另
一個特點是它區分用戶空間和系統空間,所以也很適合在比較簡單的處理器上應
用。當然,系統和用戶共用一個空間會由於用戶應用程式與系統服務模組之間聯
繫過於緊密,而使得系統的安全性變差。但是,由於嵌入式應用的封閉性,從而
使系統和用戶共用一個空間並不會成為一個很嚴重的問題,而且在某些時候還會
給用戶帶來某種方便。

2. μC/OS-II 的檔結構
(1) 與應用程式相關的檔
(a) INCLUDES.H
INCLUDES.H 是 μC/OS-II 的主檔頭,在每個 .C 檔中都要包含這個檔,
亦即在 .C 文件的檔頭部要有如下的語句:

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw 
或來電(02)2705-5066

1. 即時嵌入式系統 μC/OS–II 及其任務
#include "includes.h"

INCLUDES.H 檔的內容為:
#include

<stdio.h>

#include

<string.h>

#include

<ctype.h>

#include

<stdlib.h>

#include

<conio.h>

#include

<dos.h>

#include

<setjmp.h>

#include

"\software\ucos-ii\ix86l\bc31\os_cpu.h"

// 與應用程式相關

#include

"os_cfg.h"

// 與應用程式相關

#include

"\software\ucos-ii\source\ucos_ii.h"

// 與應用程式相關

#include

"\software\blocks\pc\bc31\pc.h"

// 與應用程式相關

從檔的內容中可以看到,把工程項目中應該包含的檔頭都加以集中,使
得專案開發者無需費神再去考慮專案中的每一個檔,究竟應該需要或者
不需要哪些檔頭了。
(b) OS_CFG.H
是一個配置檔,μC/OS-II 是依賴編譯時的條件編譯,完成軟體系統的刪
減性。亦即把用戶可以刪減的代碼段寫在 #if 和 #endif 預編譯指令之間,
在編譯時根據 #if 預編譯指令後面常數的值,以確定該代碼段是否需要
進行編譯。例如:
#if OS_TASK_CREATE_EXT_EN
  ......// 可刪減的代碼段
#endif

如果工程需要這個代碼段,則需要在配置檔中將常數 OS_TASK_CREATE_ 

本試閱檔為五南所有。如欲購買此書,請至五南網站
www.wunan.com.tw
或來電(02)2705-5066

1.1 何謂 μC/OS–II
EXT_ EN 的值置為 1;否則置為 0。
除此之外,配置檔 OS_CFG.H 還包括與項目有關其他一些常數的設置,就
是為用戶設置以上所說的這些常數值的檔。當然,在這個檔中對所有的配置常數
事先都預置一些預設值,用戶可以根據實際的需要對這些預設值進行修改。
配置檔 OS_CFG.H 的部分內容如下:
#define OS_MAX_EVENTS

2

// 系統中事件的總數

#define OS_MAX_FLAGS

5

// 系統中訊號量集的總數

#define OS_MAX_MEM_PART

5

// 系統中記憶體塊的總數

#define OS_MAX_QS

2

// 系統中消息佇列的總數

#define OS_MAX_TASKS

50

// 系統中任務的總數

#define OS_LOWEST_PRIO

52

// 系統中用戶任務的總數

#define OS_TASK_IDLE_STK_SIZE

512 // 空閒任務的堆疊長度

......
#define OS_TASK_CHANGE_PRIO_EN

1

// 是否使用修改優先順序別功能

#define OS_TASK_CREATE_EN

1

// 是否使用任務創造功能

......

() 與電腦硬體相關的檔
(a) OS_CPU.H 文件
這是一個與電腦硬體相關的檔,其中有些內容在系統移植時,要根據工
程項目實際使用的處理器進行修改,有些則無需修改。無需修改的部
分,為資料類型的定義部分,內容如下
typedef unsigned

char

BOOLEAN;

typedef unsigned

char

INT8U;

typedef signed

char

INT8S;

typedef unsigned

int

INT16U;

typedef signed

int

INT16S;

typedef unsigned

long

INT32U;

typedef signed

long

INT32S;

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw 
或來電(02)2705-5066

1. 即時嵌入式系統 μC/OS–II 及其任務
typedef float

FP32;

typedef double

FP64;

typedef unsigned

int

OS_STK;

typedef unsigned

short

OS_CPU_SR;

#define BYTE

INT8S

#define UBYTE

INT8U

#define WORD

INT16S

#define UWORD

INT16U

#define LONG

INT32S

#define ULONG

INT32U

可以看到,為了系統移植的方便,μC/OS-II 對一些已有的資料類型也做
了重新定義。除此之外,在這個檔中還定義了一些與處理器相關的常數
和巨集,例如 μC/OS-II 應用在 0x 處理器上時,部分內容說明如下
#define OS_CRITICAL_METHOD
#if

2

OS_CRITICAL_METHOD = = 1

#define OS_ENTER_CRITICAL( )

asm CLI

#define OS_EXIT_CRITICAL( )

asm STI

#endif
#if

OS_CRITICAL_METHOD = = 2

#define OS_ENTER_CRITICAL( )

asm {PUSHF; CLI}

#define OS_EXIT_CRITICAL( )

asm POPF

#endif
#if

OS_CRITICAL_METHOD = = 3

#define OS_ENTER_CRITICAL( )

(cpu_sr = OSCPUSaveSR())

#define OS_EXIT_CRITICAL( )

(OSCPURestoreSR(cpu_sr))

#endif 

本試閱檔為五南所有。如欲購買此書,請至五南網站
www.wunan.com.tw
或來電(02)2705-5066

1.1 何謂 μC/OS–II
(b) OS_CPU_A.ASM 文件
在文件 OS_CPU_A.ASM 中,集中了所有與處理器相關的組合語言代碼
模組,也是專案開發者要根據實際使用的處理器必需進行移植的檔。
(c) OS_CPU_C.C 文件
在文件 OS_CPU_C.C 中,集中了所有與處理器相關的 C 語言代碼模組,
也是專案開發者要根據實際使用的處理器必需進行移植的檔。
() 系統內核的各種服務檔
μC/OS-II 內核是以 C 函數的形式提供各種服務的,這些功能模組都是與處
理器硬體無關的,亦即在不同的處理器之間移植時,是無需修改的,μC/OS-II 將
這些服務模組分門別類地組成的如下這些檔:
OS_CORE.C

// 核心服務模組檔

OS_FLAG.C

// 訊號量集服務模組檔

OS_MBOX.C

// 消息郵箱服務模組檔

OS_MEM.C

// 儲存管理服務模組檔

OS_MUTEX.C

// 互斥型訊號量服務模組檔

OS_Q.C

// 消息佇列服務模組檔

OS_SEM.C

// 訊號量服務模組檔

OS_TASK.C

// 任務管理服務模組檔

OS_TIME.C

// 時間管理服務模組檔

uCOS_II.C
uCOS_II.H

// 與應用相關的配置檔

3. μC/OS-II 可刪減性
μC/OS-II 的可刪減性是經由條件編譯完成的,μC/OS-II 為用戶提供了一個配
置檔 OS_CFG.H,該檔中提供了一些用戶可以定義的配置常數,用戶可以經由為
這些常數內定值的方法,選用或刪除 μC/OS-II 的一些程式。
【例題 1-1】 如果用戶在配置檔 OS_CFG.H 中,定義了 OS_TASK_CREATE_
EXT_EN=1 和 if OS_TASK_DEL_EN=0,那麼以下代碼中的粗體字就會被編譯器

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw 
或來電(02)2705-5066

1. 即時嵌入式系統 μC/OS–II 及其任務
所編譯;而其它的字部分代碼就不會被編譯,不能生成目標代碼,或者說是被刪
減了。
typedef struct os_tcb {
OS_STK

*OSTCBStkPtr;

#if OS_TASK_CREATE_EXT_EN

void

*OSTCBExtPtr;

OS_STK

*OSTCBStkBottom;

INT32U

OSTCBStkSize;

INT16U

OSTCBOpt;

INT16U

OSTCBId;

#endif

struct os_tcb

*OSTCBNext;

struct os_tcb

*OSTCBPrev;

......
#if OS_TASK_DEL_EN
BOOLEAN

OSTCBDelReq;

#endif
} OS_TCB;

1.2 μC/OS-II 的任務
在小型應用中,通常一個嵌入式系統中的所有程式模組同是一個統一的任
務—對主物件進行控制。因此,認為在嵌入式系統中只有一個程序,而把這個
程序進行分解之後的那些小程式模組,由於它們沒有自己的記憶體空間,在 μC/
OS-II 中,習慣上把這樣的小程式模組叫做任務,或者叫做即時任務。即時系統
中任務的執行,大多數都是由外部事件觸發的,也就是說,即時操作系統的主要 

本試閱檔為五南所有。如欲購買此書,請至五南網站
www.wunan.com.tw
或來電(02)2705-5066

1.3 μ C/OS-II 任務的儲存結構
工作就是要回應並處理各種外部事件。
從外部事件的形式來看,主要有三種形式:非同步事件;週期性事件及非同
步事件與週期事件的組合。因此,做為即時系統,對於每一個事件都應該對應一
個處理此一事件的程式模組,這些程式模組就是任務。例如,鍵盤上的每一個鍵
被按下時,都應該對應有一個鍵處理任務。再如,程序控制中的定時檢測系統,
就需要在一個硬體或者軟體的計時器的控制之下,定時和週期地啟動相對應的即
時任務。所以,在 μC/OS-II 中,任務的代碼就是以下形式的一個 C 函數。
void uCosTask(void *pdata)
{
  for (;;)
  {
    任務代碼;
  }
}

由於 μC/OS-II 是一種內核,所以,只要沒有更高優先級別的任務搶奪當前
任務的處理器使用權時,當前任務就會一直佔用處理器,就是 for (;;) 語句的無
限迴圈代碼。
在以後的章節中可以看到,正在佔用處理器的任務也可以在適當的時機,主
動放棄處理器的使用權。

1.3 μC/OS-II任務的儲存結構
從應用程式設計的角度來看,μC/OS-II 的任務就是一個用來解決用戶問題的
C 函數和與之相關聯的一些資料結構而構成的一個實體。
從任務的儲存結構如圖 1-(a) 所示,有的三個組成部分:任務程式碼、任務
堆疊和任務控制塊。其中,任務控制塊是用來保存任務屬性,任務堆疊是用來保
存任務工作環境,而任務程式碼是任務的執行部分。
任務控制塊存放了指向任務執行代碼的指標和存放任務私有資料的儲存區。

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw 
或來電(02)2705-5066

1. 即時嵌入式系統 μC/OS–II 及其任務
所以,任務控制塊是系統管理任務的依據。換句話說,系統只要掌握了一個任
務的任務控制塊,那麼經由任務控制塊就能找到它的可執行代碼,也可以找到儲
存這個任務私有資料的儲存區。為了便於管理,當系統中存在多個任務時,系統
經由這些任務,各自的任務控制塊的中的兩個指標,將任務控制塊鏈結成如圖
1-(b) 所示的一個鏈表。
任務控制塊
前一個任務控制塊的指針
後一個任務控制塊的指針
指向任務的指針

任務的代碼

指向任務堆棧的指針
任務的優先級別

任務堆棧

任務

(a)任務的儲存結構

任務
控制塊

任務
代碼

任務
控制塊

任務
控制塊

任務
堆棧

任務
堆棧
任務1

任務
代碼

任務

任務
代碼

任務
控制塊

任務
堆棧
任務

任務
代碼
任務
堆棧

任務n

(b)多個任務形成了一個鏈表

圖 1-3 μC/OS-II 的任務在丙存中的結構

10
本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw

或來電(02)2705-5066

1.4  μC/OS-II 任務的狀態

1.4 μC/OS-II 任務的狀態
由於嵌入式系統中只有一個處理器,所以在一個時刻只能允許一個任務佔用
處理器。表 1-1 所示的是任務是否佔用處理器,以及是否處於被中斷及等待等情
況狀態列表。
表 1-1 任務的五種狀態
任務的狀態

說 明

睡眠狀態

任務只是以代碼的形式駐留在程式空間(ROM 或者 RAM),還沒有交給作
業系統管理時的情況叫做睡眠狀態。亦即任務在沒有被配備任務控制塊或被
剝奪了任務控制塊時的狀態,此時稱為睡眠狀態。

就緒狀態

如果系統為任務配備了任務控制塊,並且在任務就緒表中進行了就緒登記,
則任務就具備了運行的充分條件,此時稱為就緒狀態。

運行狀態

處於就緒狀態的任務如果經調度器判斷,獲得了處理器的使用權,則任務就
進入執行狀態。任何時刻只能有一個任務處於運行狀態,就緒的任務只有當
所有優先順序高於本任務的任務都轉為等待狀態時,才能進入執行狀態。

等待狀態

正在執行的任務,需要等待一段時間或需要等待一個事件發生再運行時,該
任務就會將處理器的使用權讓給別的任務,而使任務進入等待狀態。

中斷服務狀態

一個正在執行的任務,一旦回應中斷申請,就會中止運行而執行中斷服務程
式,此時稱為中斷服務狀態。

任務在系統和應用程式的控制下,會根據實際的情況改變自己的狀態,此一
改變稱為任務狀態的轉移,不同狀態之間的轉換如圖 1- 所示。

等待狀態

中斷

睡眠狀態

就緒狀態

運行狀態

中斷服務
狀態

任務的CPU
使用權被剝奪

圖 1-4 任務的狀態及轉換

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw 11
或來電(02)2705-5066

1. 即時嵌入式系統 μC/OS–II 及其任務
系統為了能有效地對系統中的任務進行協調管理,所以必需要隨時瞭解任務
的當前狀態,亦即任務有責任向系統提供本任務的當前狀態。所以,在所有任務
的任務控制塊中都有一個專門儲存任務當前狀態資訊的欄位,以供系統和用戶查
詢。

1.5 μC/OS_II 任務的優先順序別
前面提過 μC/OS_II 是依照所支援的硬體任務而設計的,因此,μC/OS_II 中
的每一個任務都必須具有一個惟一的優先順序別,表示該任務在安排處理器時,
它所具有的優先權力。
μC/OS_II 將任務的優先權分為  個優先順序別,每一個級別都用一個數
字表示,數位 0 表示任務的優先順序別最高,數字越大則表示任務的優先順序
別越低。此外,μC/OS_II 規定,一個應用程式的任務數最多可以有  個,但
是在實際應用中,為了節省記憶體,用戶可以根據應用程式的需要,在配置
檔 OS_CFG.H 中,經由對常數 OS_LOWEST_PRIO 給與定值的方法,說明應用
程式中任務優先級別的數目。同時,常數 OS_LOWEST_PRIO 還有另外一個意
義,可以用來表示系統中任務的最低優先順序別。該常數一旦被定義,則意味著
系統中可供使用的優先順序別共有 OS_LOWEST_PRIO+1 個,分別是:0,1, 
,......,OS_LOWEST_PRIO,同時也意味著系統中任務的總數最多不能超過
OS_LOWEST_PRIO+1 個。
而其中系統總是把最低優先順序別 OS_LOWEST_PRIO 自動的給系統創造
一個任務 : 空閒任務。如果應用程式中還使用了統計任務,則系統會把優先順序
別 OS_LOWEST_PRIO-1 自動的給與統計任務,因此用戶任務可以使用的優先順
序別是:0,1,......OS_LOWEST_PRIO-,共有 OS_LOWEST_PRIO-1 個。
【例題 1-2】 如果希望應用程式中任務的優先順序別為  個,則表示最低優
先級別的常數 OS_LOWEST_PRIO 值應該是多少?如果應用程式中使用了系統
提供的空閒任務和統計任務,則該應用程式最多可以安排多少個任務?
解:表示最低優先級別的常數 OS_LOWEST_PRIO 值應該為 ,優先順序別
12
本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw

或來電(02)2705-5066

1.6 任務控制塊
分別為 0,1,,,......,。由於系統空閒任務佔用了優先順序別 ,
統計任務佔用了優先順序別 ,則應用程式中最多可以安排優先順序別
分別為 0,1,,...... 的  個任務。

1.6 任務控制塊
用來記錄任務的堆疊指標、任務的當前狀態、任務的優先順序別等一些與任
務管理有關的屬性動作就稱為任務控制塊,也稱為程序控制塊。任務控制塊相當
於是一個任務在系統中的檔案,沒有任務控制塊的任務是不能被系統承認和管理
的,為了管理系統中的多個任務,μC/OS-II 將系統所有任務的控制塊鏈結為兩條
鏈表。

1. 任務控制塊的結構
在 μC/OS-II 中,當用戶應用程式呼叫系統函數 OSTaskCreate( ),創造一個
用戶任務時,此一函數就會把該任務的所有相關資料,給與任務控制塊中的對應
成員,並停留在 RAM 中。而任務控制塊結構的定義為
typedef struct os_tcb {
OS_STK *OSTCBStkPtr;

// 指向任務堆疊棧頂的指標

#if OS_TASK_CREATE_EXT_EN
void

*OSTCBExtPtr;

// 指向任務控制塊擴展的指標

OS_STK

*OSTCBStkBottom;

// 指向任務堆疊棧底的指標

INT32U

OSTCBStkSize;

// 任務堆疊的長度

INT16U

OSTCBOpt;

// 創建任務時的選擇項

INT16U

OSTCBId;

// 目前,該區域未被使用

#endif
struct os_tcb

*OSTCBNext;

// 指向後一個任務控制塊的指標

struct os_tcb

*OSTCBPrev;

// 指向前一個任務控制塊的指標

#if (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_MBOX_EN || OS_Sem_EN
OS_EVENT

*OSTCBEventPtr; // 指向事件控制塊的指標

#endif

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw 13
或來電(02)2705-5066

1. 即時嵌入式系統 μC/OS–II 及其任務
#if (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_MBOX_EN
void

*OSTCBMsg;

// 指向傳遞給任務消息的指標

OSTCBDly;

// 任務等待的時限(節拍數)

#endif

INT16U
INT8U

OSTCBStat;

// 任務的當前狀態標誌

INT8U

OSTCBPrio;

// 任務的優先順序別

INT8U

OSTCBX;

// 用於快速訪問就緒表的資料

INT8U

OSTCBY;

// 用於快速訪問就緒表的資料

INT8U

OSTCBBitX;

// 用於快速訪問就緒表的資料

INT8U

OSTCBBitY;

// 用於快速訪問就緒表的資料

#if OS_TASK_DEL_EN
BOOLEAN

OSTCBDelReq;

// 請求刪除任務時用到的標誌

#endif
} OS_TCB;

其中 OSTCBStat 用來存放任務的當前狀態,變數的說明如表 1- 所示。
表 1-2 OSTCBStat 可能的值

說 明

OS_STAT_RDY

任務處於就緒狀態

OS_STAT_SEM

任務處於等待訊號量狀態

OS_STAT_MBOX

任務處於等待消息郵件狀態

OS_STAT_Q

任務處於等待消息佇列狀態

OS_STAT_SUSPEND

任務處於被掛起狀態

OS_STAT_MUTEX

任務處於等待互斥型訊號量狀態

如果仔細閱讀任務控制塊,就會發現在 TCB 的結構中並沒有圖 1-(a) 中的
指向任務代碼的指標,那麼系統如何根據任務控制塊而獲得任務的代碼呢?其
實,系統在運行一個任務時,是先按照任務的優先順序別找到任務控制塊,然後
14
本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw

或來電(02)2705-5066

1.6 任務控制塊
在任務堆疊中再獲得任務代碼的指針的。為了不混淆現在的學習,讀者可先暫時
認為任務的控制塊中有這樣一個指向任務代碼的指標,待以後學習任務切換時,
再將問題弄清楚。

2. 任務控制塊鏈表
μC/OS-II 用兩條鏈表來管理任務控制塊,一條是空任務塊鏈表(其中的所有
任務控制塊還沒有分配給任務),另一條是任務塊鏈表(其中的所有任務控制塊
已經分配給任務了)。
空任務塊鏈表是 μC/OS-II 的全局資料結構,是在應用程式呼叫函數 OSInit( )
對 μC/OS-II 系統進行初始化時所建立並且初始化的,而任務控制塊鏈表則是在
系統呼叫系統函數 OSTaskCreate( ) 創造任務時所建立的。
函數 OSInit( ) 創造空任務控制塊鏈表的步驟為:先在 RAM 中建立一個
OS_TCB 結構類型的陣列 OSTCBTbl[ ],使陣列的每個元素都是一個任務控制
塊,然後利用 OS_TCB 結構中的兩個指標 OSTCBNext 和 OSTCBPrev,再把這
些控制塊鏈結成一個如圖 1- 所示的鏈表。由於鏈表中的這些控制塊還沒有與具
體任務相關聯,或者說還未把它們分配給任務,所以這個鏈表就稱為空任務塊鏈
表。
從圖 1- 中可以看到,μC/OS-II 初始化時建立的空任務鏈表一共有 OS_MAX
_ TASKS+OS_N_SYS_TASKS 個 元 素。 其 中,OS_MAX_TASKS 是 配 置 檔
OS_CFG.H 中用來表示用戶任務總數的一個常數;而 OS_N_SYS_TASKS 是定義
在檔 UCOS_II.H 中,用來指明系統任務總數的常數(值為 :一個空閒任務,一
個統計任務),這兩個常數都需要在進行系統配置時,由用戶根據需要而指定。

圖 1-5 μC/OS-II 初始化時創建一個空的任務控制塊鏈表

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw 15
或來電(02)2705-5066

1. 即時嵌入式系統 μC/OS–II 及其任務
每當應用程式創造一個任務,以及在呼叫系統函數 OSTaskCreate( ) 或者
OSTaskCreateExt( ) 時,系統就會從鏈表的頭部(指標 OSTCBFreeList 指向的任
務控制塊)摘取一個空任務控制塊分配給該任務,並且將它加入到任務控制塊鏈
表中,注意在加入之前要給任務控制塊中的各個成員給定數值。

保存控制塊
指針的數組
正在運行任務
控制塊的指針

圖 1-6 μC/OS-II 任務控制塊鏈表和 OST CBPrio Tbl 數組及變量 OSTCB Cur

圖 1- 是在圖 1- 所示空任務控制塊鏈表基礎上,應用程式創造了兩個用戶
任務。並且使用了兩個系統任務(空閒任務和統計任務)的情況時,空任務塊鏈
表和任務塊鏈表的結構示意圖(圖中有陰影的為任務塊鏈表)。
簡單地說,如果將任務控制塊看作任務在系統中的檔案的話,那麼這兩條鏈
表就相當於設立了兩個裝有檔案的檔案櫃,一個用來裝空白檔案,另一個用來裝
已經存有任務資訊的檔案。
由過去的經驗得知,在這種型態的鏈表中查尋一個元素,有時是很費時的,
而且查尋時間還與目標元素在鏈表中的位置有關,有相當大的不確定性,這兩種
情況都是即時系統所忌諱的。所以,為了加快對任務控制塊的執行速度,除了任

16
本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw

或來電(02)2705-5066

1.7 任務堆疊
務控制塊鏈表被創造為雙向鏈表之外,μC/OS-II 在 uCOS_II.H 檔中還定義了一
個資料類型為 OS_TCB* 的陣列 OSTCBTbl[ ],專門用來存放指向各個任務控制
塊的指標,並且按照任務的優先順序別為順序,將這些指標存放陣列的各個元素
裏。這樣,在執行某一個任務的任務控制塊時,就可以按照任務的優先順序別,
直接從陣列 OSTCBTbl[ ] 的對應元素中,獲得該任務控制塊的指標,並經由它直
接找到該任務控制塊了。
陣列 OSTCBTbl[ ] 與任務控制塊鏈表中各個任務控制塊之間的關係,如圖 
- 所示。可以得知在所有的任務控制塊中,系統交互作用最頻繁的,一定是當
前正在運行任務的控制塊,所以為了能更快地執行正在運行任務的任務控制塊,
μC/OS-II 還定義了一個 OS_TCB* 類型的總體變數 OSTCBCur,專門存放當前正
在運行的任務的任務控制塊指標,如圖 1- 中的 OSTCBCur。
所以當系統一旦選定一個要運行的任務時,就先按照任務的優先順序別(例
如, 優 先 順 序 別 為 ), 將 陣 列 OSTCBTbl 的 對 應 元 素( 例 如 OSTCBTbl[])
中的數值傳入 OSTCBCur,於是系統再對這個任務的任務控制塊進行執行時,
就快捷的多了。如果正在執行的是任務優先順序別為  的任務,那麼指標變數
OSTCBCur 的指向就如圖 1- 所示。
μC/OS-II 允許用函數 OSTaskDel( ) 刪除一個任務,刪除一個任務,實質上
就是把該任務的任務控制塊從任務控制塊鏈表中加以刪除,並且歸還給空任務控
制塊鏈表。這樣,μC/OS-II 對這個沒有任務控制塊的任務就不會再理會了,因為
系統「認為」它不存在了。但要要注意,任務的代碼還仍然在記憶體中沒有被刪
除,只不過是沒有檔案罷了,如果需要的話,該任務還是可以被重新創造。

1.7 任務堆疊
所謂堆疊就是在記憶體中按照資料「後進先出(Last in, First out)」的原理
的儲存空間,為了滿足任務切換和回應中斷時,保存處理器暫存器中的內容及儲
存任務私有資料的需要,每個任務都應該配有自己的堆疊,這個堆疊就叫做任務
堆疊,它是任務的重要的組成部分。

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw 17
或來電(02)2705-5066

1. 即時嵌入式系統 μC/OS–II 及其任務

1. 任務堆疊的創建
為 方 便 定 義 任 務 堆 疊, 在 OS_CPU.H 檔 中, 專 門 定 義 了 一 個 資 料 類 型
OS_STK:
typedef unsigned int OS_STK;

// 該類型長度為 16 位

這樣,在記憶體中劃分一個任務堆疊的棧區就非常簡單,亦即在應用程式中
定義一個 OS_STK 類型的一個陣列就可以了。例如:
#define

TASK_STK_SIZE

512

OS_STK TaskStk[TASK_STK_SIZE];

// 定義堆疊的長度(1024 位元組)
// 定義一個陣列來作為任務堆疊

當呼叫任務創造函數 OSTaskCreate( ) 創造一個任務時,此時會將陣列的指
標傳遞給函數 OSTaskCreate( ) 中的堆疊棧頂參數 ptos,在函數的內部會將這個
參數傳入任務控制塊的指標變數 OSTCBStkPtr,就可以將該陣列與任務相連結而
成為該任務所佔用的資料區了。在這個任務獲得處理器而執行的前夕,系統會從
任務控制塊中取出指標,並且將它傳到處理器的堆疊指標暫存器內,於是這個資
料區就成為這個任務的任務堆疊,任務堆疊的形成過程如圖 1- 所示。

任務控制塊
處理器

任務運行前

創建任務時

圖 1-7 任務堆棧的形成過程示意圖

18
本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw

或來電(02)2705-5066

1.7 任務堆疊
【例題 1-3】 創造任務函數 OSTaskCreate( ) 的原型為
INT8U OSTaskCreate (
void (*task)(void *pd),

// 指向任務的指標

void *pdata,

// 傳遞給任務的參數

OS_STK *ptos,

// 任務堆疊棧頂的指標

INT8U prio

// 指定任務優先級別的參數

);

創造一個任務,堆疊的長度為 1 位元組,優先順序別為 0,任務參數
pdata 的碼為 MyTaskAgu,試寫出需要的代碼。
答:
#define MyTaskStk

N

64

OS_STK MyTaskStk[MyTaskStkN];

void main(void)
{
......
OSTaskCreate(
MyTask,

// 任務的指針

&MyTaskAgu,

// 傳遞給任務的參數

& MyTaskStk[MyTaskStkN-1],

// 任務堆疊棧頂位址

20

// 任務的優先順序別

);
......
}

需要注意的是堆疊的增長方向是隨系統所使用的處理器不同而不同的,有的
處理器要求堆疊的增長方向是向上的,而另一些處理器要求堆疊的增長方向是向
下的,如圖 1- 所示。因此在使用函數 OSTaskCreate( ) 創造任務時,一定要注意
所使用的處理器對堆疊增長方向的支援是向上的還是向下的。

本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw 19
或來電(02)2705-5066

1. 即時嵌入式系統 μC/OS–II 及其任務
低地址

堆棧增長的方向

堆棧增長的方向

高地址

增長方向為向下的堆棧

增長方向為向上的堆棧

圖 1-8 堆棧的不同增長方向

前面的例中指出,在假設使用了支援堆疊向下增長方式的處理器的條件下,
設置的函數參數 ptos。如果使用的處理器支援堆疊的增長方向是向上的,則對於
呼叫函數 OSTaskCreate( ) 創造任務時,應該寫成
OSTaskCreate(MyTask, &MyTaskAgu, & MyTaskStk[0], 20);

為了提高應用程式的可攜性,在編寫程式時也可以將兩種代碼都編寫出來,
利用 OS_CFG.H 檔中的常數 OS_STK_GROWTH 做為選擇開關,使用戶可以經
由定義常數的數值選擇相應的代碼段,以適應不同的堆疊增長方式的需要,以下
列出一個可能的代碼段範例
#define MyTaskStk

N

64

OS_STK MyTaskStk[MyTaskStkN];

void main(void)
{
......
#if OS_STK_GROWTH = = 1

20
本試閱檔為五南所有。如欲購買此書,請至五南網站 www.wunan.com.tw

或來電(02)2705-5066

即時嵌入式系統 μC/OS-II/任哲, 樊生文編
著. -- 初版. -- 臺北市 : 五南, 2012.12
   面;  公分.
ISBN 978-957-11-6915-6(平裝)
1.作業系統
312.54

101023037

5DG1

即時嵌入式系統 μC/OS-II

Real-time μC/OS-II in Embedded System

者 ─ 任哲 樊生文

訂 ─ 溫坤禮

發 行 人 ─ 楊榮川
編 編 輯 ─ 王翠華
主  編 ─ 穆文娟
責任編輯 ─ 楊景涵
文字編輯 ─ 林秋芬
封面設計 ─ 簡愷立
出 版 者 ─ 五南圖書出版股份有限公司
地  址:106台 北 市 大 安 區 和 平 東 路 二 段 3 3 9 號 4 樓
電  話:(02)2705-5066  傳  真:(02)2706-6100
網  址:http://www.wunan.com.tw
電子郵件:wunan@wunan.com.tw
劃撥帳號:0 1 0 6 8 9 5 3
戶  名:五南圖書出版股份有限公司
台中市駐區辦公室/台中市中區中山路6號
電  話:(04)2223-0891  傳  真:(04)2223-3549
高雄市駐區辦公室/高雄市新興區中山一路290號
電  話:(07)2358-702   傳  真:(07)2350-236
法律顧問 元貞聯合法律事務所 張澤平律師
出版日期 2 0 1 2 年 1 2 月 初 版 一 刷
©2011,北京航空航天大學出版社,版權所有
※本書中文繁體字版由北京航空航天大學出版社
獨家授權出版發行※

定  價 新 臺 幣 3 5 0 元

※版本試閱檔為五南所有。如欲購買此書,請至五南網站
權所有.欲利用本書內容,必須徵求本公司同意※

或來電(02)2705-5066

www.wunan.com.tw