1. 程式人生 > >FreeRTOS系列第3篇---FreeRTOS移植指南

FreeRTOS系列第3篇---FreeRTOS移植指南

 FreeRTOS下載包中已經包含很多演示例程- 每一個例程都是針對於:

  1. 特定的微控制器;
  2. 特定的開發工具(編譯器、偵錯程式等等);
  3. 特定的硬體平臺(樣機或評估板)。

      可以在官方網站首頁左側的樹形選單 'Supported Devices' 中找到這些例程介紹。 

      可惜的是不可能為所有微控制器、編譯器和評估板提供演示例程。因此,官方提供的演示例程可能不完全符合你正在使用的開發平臺。本章描述如何通過修改或合併官方提供的演示例程,來滿足自己的開發平臺需求(包括微處理器和編譯器)。

      修改一個現有的評估板例程,使之執行到另一個同類評估板上,通常是比較簡單的,稍微複雜些的是跨編譯器移植。本文介紹這兩情況下的修改,只是對相似的平臺有效。然而,將FreeRTOS移植到一個全新的平臺、未支援的處理器架構,並不是件簡單的事情。本文不討論如何將FreeRTOS移植到一個全新平臺。

1.修改例程使之執行到不同評估板

      本節描述如何通過修改一個官方提供的演示例程,使之執行到另一個評估板,這裡兩個評估板使用同系列微處理器,使用相同編譯器。在這個例子中,將運行於SAM7S-EK硬體開發板上的IAR SAM7S演示例程,修改使之執行到Olimex SAM7-P64開發板。(注:兩塊開發板都是使用ATMEL公司的ARM7微處理器,前者使用AT91SAM7S256,後者使用AT91SAM7S64)

1.1初始編譯

      作為修改練習的起點,被修改的演示例程是要能使用的。因此,在未做任何修改之前,首先檢查下載的演示例程能否被正確的編譯。絕大多數情況下,演示例程編譯後是沒有任何錯誤和警告的。

1.2修改LED IO埠

       LED燈是用來指示演示例程執行的最簡單方法,因此點亮新硬體平臺上的LED燈通常是最容易的。

      兩個不同評估板上的LED連線到相同的IO埠通常是不太可能的,因此,一些小幅度修改是必須的。

      在partest.c檔案中的vParTestInitialise() 函式包含IO埠的模式和方向配置。在main.c檔案中的prvSetupHardware()函式包含更多的硬體初始化(比如,使能IO外設的時鐘模組),可能需要根據不同的使用進行一些修改。

      根據目標評估板的硬體,在上面兩個函式中做必要的修改,然後寫一段簡單程式,來檢查硬體LED是否完好。這個簡單程式不使用FreeRTOS,只是為了確保硬體LED能夠正常工作。因此,註釋掉之前的main()函式,使用下面的例子代替:

    int main( void ) 
    { 
        volatile unsigned long ul;   /* 禁止編譯器優化此變數 */ 
        /* 初始化LED IO為輸出-注:prvSetupHardware()也可能會被呼叫*/ 
        vParTestInitialise(); 
        /*不斷開啟LED */ 
        for( ;; ) 
        { 
            /* 我們暫時不使用RTOS,這裡只是使用一個非常粗糙的延時*/ 
            for( ul = 0; ul < 0xfffff; ul++ ) 
            { 
            } 
            /* 開啟4個LED */ 
            vParTestToggleLED( 0 ); 
            vParTestToggleLED( 1 ); 
            vParTestToggleLED( 2 ); 
            vParTestToggleLED( 3 ); 
        } 
        return 0; 
    }

1.3 RTOS排程器簡介

      一旦確定硬體LED可以正常工作,就可以恢復原來的main()函式。

      作為入門級的多工應用程式應該儘量的簡單,LED閃爍測試程式常常擔任這樣的角色,可以堪比經典的“Hello Wold”。這個任務幾乎在所有演示例程中都能看到,在main()函式中呼叫vStartLEDFlashTasks() (使用協程版本時呼叫vStartFlashCoRoutines())來實現。如果你使用的演示例程main()函式中並沒有呼叫vStartLEDFlashTasks()(或vStartFlashCoRoutines()),那麼需要你將FreeRTOS/Demo/Common/Minimal/Flash.c檔案新增到你的工程,並在main()函式手動的增加vStartLEDFlashTasks()函式。

      除了呼叫vStartLEDFlashTasks()外,註釋掉所有用於啟動一個或多個演示任務的函式。最後的main()函式僅呼叫三個函式:prvSetupHardware()、vStartLEDFlashTasks()和vTaskStartScheduler()。例如(基於典型的main()函式):

    int main( void ) 
    { 
        /* 設定用於演示的微控制器硬體 */ 
        prvSetupHardware(); 
        /* 留下這個函式 */ 
        vCreateFlashTasks();  
        /* 所有的其它建立任務的函式統統註釋掉        
            vCreatePollQTasks();
            vCreateComTestTasks();
            //等等…
            xTaskCreate( vCheckTask,"check", STACK_SIZE, NULL, TASK_PRIORITY, NULL );
        */ 
        /*啟動RTOS排程器. */ 
        vTaskStartScheduler(); 
        /* 永遠不會執行到這裡! */ 
        return 0; 
    }

      這是一個非常簡單的應用程式,正確執行後,LED0~2(包括2)或分別按照不同的頻率閃爍。

1.4 收尾工作

      一旦簡單的LED閃爍例程正確執行後,你可以恢復之前註釋掉的所有的演示任務。

      以下要點需牢記:

  • 如果你使用的演示例程最初並沒有呼叫vTaskCreateFlashTasks()函式,而是手動的增加了這個函式,那麼應該再手動的刪除掉這個函式。主要有兩個方面的原因:第一是這個LED閃爍任務用到的IO可能也被演示例程的其它任務使用,第二是演示例程可能已經佔用了所有的RAM,已經沒有空餘RAM用來增加新的任務。
  • 標準的“通訊測試(comtest)”(如果演示例程中有的話)任務使用到微控制器的一個UART外設。檢測硬體是可用的。
  • 有些外設不進行修改就想用於任何不同的硬體或介面是不可能的,比如LCD。

2.合併或修改官方演示工程

      本節主要描述如何修改一個現存的工程或者按照需求合併兩個現存的工程。比如,你希望使用GCC編譯器建立一個STR9演示工程(demo project),並且你下載的FreeRTOS軟體包中並沒有GCC版本的STR9演示例程,但是FreeRTOS下載包中有IAR版本的STR9演示例程和GCC版本的STR75x演示例程。則可以通過這兩個現存的工程來創       建GCC版本的STR9演示工程。可以有兩種方式完成:

      使用GCC版本的STR75x演示工程,修改使之符合指定的微處理器(STR9評估板上的微處理器)。

      使用GCC建立一個新的工程。從IAR版本的STR9演示工程中獲取檔案和配置資訊,使之符合GCC編譯器需求。

2.1識別用於特定微控制器的FreeRTOS核心檔案

      對於一個特定平臺,大多數(不是全部)硬體介面程式碼包含在一個叫做FreeRTOS/source/portable/[編譯器]/[微控制器/port.c的檔案中,和它對應的標頭檔案是FreeRTOS/source/portable/[編譯器]/[微控制器]/portmacro.h。

     對於一些編譯器來說,port.c和portmacro.h就是所需要的全部硬體介面程式碼。另一些還需要一些彙編檔案,這些檔案叫做portasm.s或者portasm.asm。

     最後,僅對於ARM7 GCC移植,同樣存在一個類似的硬體介面檔案:portISR.c,portISR.c是從port.c中分離出來的,這些程式碼必須在ARM模式下編譯,port.c中剩餘的程式碼既可以在ARM模式下編譯,也可在THUMB模式下編譯。

2.2識別用於特定編譯器的檔案

      編譯器可以為嵌入式系統提供某些特定的C語言擴充套件。比如某個特定關鍵字可以標識出一個函式是中斷處理服務函式。

      擴充套件的C語言部分,是不屬於標準C語言規範的。因此,編譯器與編譯器之間是有差別的。FreeRTOS的檔案中就包含類似的非標準C語言語法,在資料夾FreeRTOS/source/portable中(上文中提到的特定微控制器硬體介面程式碼也在這個檔案中)。此外,一些演示例程會使用到中斷服務程式,這些中斷服務程式並不屬於FreeRTOS的一部分,並且如何定義和使用這些中斷服務程式也是編譯器所特定的。

2.3硬體底層檔案

      C啟動檔案和連結指令碼都屬於處理器和編譯器特定的。不推薦嘗試從無到有的建立這些檔案,應該到FreeRTOS演示工程中尋找一個合適的來修改。

      要特別小心ARM7啟動檔案。它必須將IRQ中斷服務程式入口地址配置到快速中斷處理向量表或者普通中斷向量表中。這兩種情況,演示工程都提供了例子。

      連結指令碼必須正確的描述當前使用處理器的記憶體對映。

2.4工程設定

      每一個工程通常都會定義一些巨集,這些預處理巨集定義了一些要被編譯的特定的硬體介面程式碼。要包含portmacro.h檔案才能識別這些巨集。比如,當使用GCC編譯MegaAVR硬體介面程式碼時,巨集GCC_MEGA_AVR必須被定義;當使用IAR編譯MegaAVR硬體介面程式碼時,巨集IAR_MEGA_AVR必須被定義等等。參考演示例程工程以及FreeRTOS/source/include/portable.h檔案可以查詢當前工程定義了那些巨集。如果預處理巨集未定義,那麼portmacro.h檔案所在目錄的路徑必須被包含到前處理器的搜尋路徑中。

      其它的編譯器設定,比如優化選項,也是很關鍵的。可以參考提供的演示工程。

具有IDE的編譯器通常具有目標微控制器選項並將它作為工程設定的一部分,所以新的工程也必須適應新的目標微控制器,同樣的,如果使用到makefile檔案,則makefile檔案也必須更新以符合新的目標微控制器。

2.5配置系統節拍時鐘中斷

      呼叫函式prvSetupTimerInterrupt()來配置系統節拍中斷,這個函式可以在以下路徑的檔案中找到:FreeRTOS/source/portable/[compiler]/[microcontroller]/port.c

2.6 RAM和ROM的使用

      FreeRTOS記憶體管理一章中描述了FreeRTOS如何使用RAM,並且描述了RAM是如何分配給RTOS核心的。

      如果你要將演示例程移植到一個RAM稍小的微處理器上,那麼你可能需要減少configTOTAL_HEAP_SIZE的值(位於FreeRTOSConfig.h),並且減少演示例程的任務個數。可以通過簡單的註釋掉不需要的任務來實現。

      如果你要將演示例程移植到一個ROM較小的微處理器中,那麼你可能需要減少應用例程的檔案數目,他們位於FreeRTOS/Demo/common資料夾目錄下。同時你還要刪除main函式中對他們的呼叫函式。

注:可能你是通過搜尋引擎找到這篇文章,滿懷希望的點進來,以為能解決自己移植的所有問題,但是看完後卻發現本文站的角度太高,並不是特別適合對移植一無所知的你。先別急著以為本文是標題黨而點踩,可能有一篇文章適合你,這篇文章以Cortex-M3硬體平臺為例,詳細的介紹移植過程,請點選這裡