2012年3月12日 星期一

FreeRTOS簡介


FreeRTOS簡介

由於最近手邊拿到兩塊開發版 NXP LPC1114(Cortex M0),TI  LM3S748(Cortex M3),板子所附的範例程式中便有FreeRTOS,正好利用這個機會好好研究一下這個作業系統FreeRTOS。


NXP LPC1114(Cortex M0)

TI LM3S748(Cortex M3)

FreeRTOS 定義 FreeRTOS是一個輕量級的即時作業系統。

所謂即時作業系統(Real-time operating system, RTOS)又稱實時作業系統,它會按照排序執行、管理系統資源,並為開發應用程式提供一致的基礎。通常都會有最基礎的內核,以及外加上去的模組,像是檔案系統、網路協定堆疊和應用、裝置驅動程式…等模組。
比較有名的有以下幾個作業系統。


由於 FreeRTOS 是 embedded system 常用的一個作業系統,因此有許多組織幫忙實作其擴充模組,構成一個完整的嵌入式系統開發環境。關於各類型的擴充組織可以參考 http://www.freertos.org/FreeRTOS-Plus/index.shtml
FreeRTOS 支援平台

  • ARM、
  • MSP430、
  • AVR、
  • PIC、
  • C8051F



FreeRTOS 功能限制

FreeRTOS 本身並沒有內建 GUI, TCP/IP, FileSystem等功能,若需要這些功能則需要再與第三方的程式結合。但是如果使用第三方提供的開發版作實驗,許多廠商都已經將這些功能統整好了。我們只要會用就行了。


FreeRTOS 移植 


FreeRTOS 針對不同的硬體架構收集了各種 demo project,實際的移植工作則是由各個IC設計廠商完成,例如我手邊的兩張板子為 ARM cortex M0 與 cortex M3,其對應的下載位置如下:
a. 開發版 TI ek-lm3s3748 (cortex M3), http://www.ti.com/tool/ekc-lm3s3748
b. 開發版 NXP LPC1114 (cortex M0), http://ics.nxp.com/support/lpcxpresso/zip/examples.freertos.lpc1114.zip
  
以 lm3s3748 Cortex M3 為例,所下載的FreeRTOS檔案名稱為FreeRTOS_V4.8.1_Stellaris.zip,裡面已經包含了 TCP/IP 以及一個簡單的 HTTP Server,執行後便可以當成一個簡單的web server。若有需要用到版子上的LCD,則可以使用開發版隨版子所附的開發程式,裡面已經有 GUI 的範例可以直接使用。


FreeRTOS 原始碼分析

    FreeRTOS 原始碼可以從這裡下載,下面介紹的部分乃是參考版本 7.1.0。

    解開FreeRTOS.zip之後,將會包含以下四個目錄:
  • FreeRTOS/Source 包含 kernel 相關的檔案,主要有五個檔案, tasks.c, queue.c, list.c, croutine.c 和 timer.c
  • FreeRTOS/Source/Portable 包含了移植到不同MCU或不同編譯器時,需要修改的檔案
  • FreeRTOS/Source/include 包含了相關的標頭檔
  • FreeRTOS/Demo 則是包含了已經移植成功的範例程式,以前述的FreeRTOS_V4.8.1_Stellaris.zip為例,裡面的Demo便是CORTEX_LM3Sxxxx_IAR_Keil,
  • 適用於 MCU CortexM3 與編譯器 Keil 的 FreeRTOS。

    第一個應該要看的檔案是 FreeRTOS/Source/include/FreeRTOS.h,裏頭包含幾個內容

  • FreeRTOSConfig.h 
  • 此設定檔會放置在對應的 demo目錄內,其定義了作業系統的基本設定,如:是否支援preemptive,CPU Clock,Stack size,Heap size,Task Priority的設定等等。
  • portable.h  
  • 此檔會放置在對應的 portable 目錄內,會根據使用的編譯器而載入不同的編譯器定義檔案。例如:型別定義,是否支援Byte Alignment,記憶體管理,工作排程等等... 下例是一個GCC編譯器的基本型別定義
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE unsigned portLONG
#define portBASE_TYPE long
  • 定義每個 Task 的進入函數 (entry function)
typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
  • 定義 Task, Queue, Timer 的操作,如:Create, Play, Resume, Stop, Delete等等


     接著來看看看Kernel 主要的幾個檔案,task,timer,list,coroutine

  • task.c/task.h:用來建立或刪除 Task,啟動或停止 Task Scheduler,設定或更改Task可以存取的資源權限,執行/暫停/停止 Task。並且可以查詢系統目前的狀態,例如:StackHighWaterMark、FreeStackSpace、GetRunTimeStats(此Task被執行的總時間)。此處定義 Task 的生命週期會有四種狀態:
  • blocked ('B'), 
  • ready ('R'), 
  • deleted ('D'),
  • suspended ('S').
  • timer.c:
  • 提供基本的Timer操作。值得注意的是使用timer之前,需要先設定系統 timer  的類型,有以下分類可以設定。
  • #define TIMER_CFG_32_BIT_OS     0x00000001  // 32-bit one-shot timer
  • #define TIMER_CFG_32_BIT_OS_UP  0x00000011  // 32-bit one-shot up-count timer
  • #define TIMER_CFG_32_BIT_PER    0x00000002  // 32-bit periodic timer
  • #define TIMER_CFG_32_BIT_PER_UP 0x00000012  // 32-bit periodic up-count timer
  • #define TIMER_CFG_32_RTC        0x01000000  // 32-bit RTC timer
  • #define TIMER_CFG_16_BIT_PAIR   0x04000000  // Two 16-bit timers
  • #define TIMER_CFG_A_ONE_SHOT    0x00000001  // Timer A one-shot timer
  • #define TIMER_CFG_A_ONE_SHOT_UP 0x00000011  // Timer A one-shot up-count timer
  • #define TIMER_CFG_A_PERIODIC    0x00000002  // Timer A periodic timer
  • #define TIMER_CFG_A_PERIODIC_UP 0x00000012  // Timer A periodic up-count timer
  • #define TIMER_CFG_A_CAP_COUNT   0x00000003  // Timer A event counter
  • #define TIMER_CFG_A_CAP_TIME    0x00000007  // Timer A event timer
  • #define TIMER_CFG_A_PWM         0x0000000A  // Timer A PWM output
  • #define TIMER_CFG_B_ONE_SHOT    0x00000100  // Timer B one-shot timer
  • #define TIMER_CFG_B_ONE_SHOT_UP 0x00001100  // Timer B one-shot up-count timer
  • #define TIMER_CFG_B_PERIODIC    0x00000200  // Timer B periodic timer
  • #define TIMER_CFG_B_PERIODIC_UP 0x00001200  // Timer B periodic up-count timer
  • #define TIMER_CFG_B_CAP_COUNT   0x00000300  // Timer B event counter
  • #define TIMER_CFG_B_CAP_TIME    0x00000700  // Timer B event timer
  • #define TIMER_CFG_B_PWM         0x00000A00  // Timer B PWM output
  • list/queue:
  • 都是屬於 doubly linked list 的資料結構,系統使用這些資料結構來配置資源,例如:list 用來建立 Task schedule並進行工作排程,queue可以儲存中斷向量的服務程序(ISR)。開發應用程式的人也可以直接使用此資料結構。

  • Coroutine:
  • coroutine就是產生多個程序,並允許這些程序可以分別暫停與執行,利用程式語言技巧達到多工的實作技術 。而一般我們所指的 multi-thread 是交由系統直接幫忙執行多工。這部分的解釋請參考 Jserv's blog

參考資料

  1. 官方 http://www.freertos.org/
  2. 原始碼下載 http://sourceforge.net/projects/freertos/files/FreeRTOS/V7.1.0/ 
  3. 中文介紹 http://www.freertos.net/
  4. 中文電子書 http://www.61ic.com/code/viewthread.php?tid=75144&extra=page%3D1