從0開始搭建基於ARM GCC的軟件系統04——移植FreeRTOS

一、獲取FreeRTOS源碼

    進入FreeRTOS官網:https://www.freertos.org/a00104.html

  

點擊Download下載源碼文件。我下載的是“FreeRTOSv10.2.1_191129.exe”,其它版本也可以。

解壓後:

先不用看Labs和Plus兩個文件夾(後面熟悉了之後再看)。直接進入到FreeRTOS目錄:

Demo:一些演示工程。
License:許可。
Source:源碼目錄。我們所需要的文件都在這裏面。

進入到Source目錄:

如圖所示,就是FreeRTOS的源代碼了。將其移植到我們的系統中即可。

 

二、移植FreeRTOS

在我們的系統工程中創建一個目錄用於存放FreeRTOS源碼。

我創建目錄結構:OS\FreeRTOSv10.2.1\Source。

將以下文件都從剛下載的源碼包中拷貝過來。

Source\*.c   (源碼c文件)

Source\include\*.h (源碼頭文件)

Source\portable\GCC\ARM_CM4F\port.c (這裏與硬件相關,請根據自己的硬件平臺選擇。我使用的STM32L4VGT6平臺,編譯器用的ARM GCC,所以選擇了GCC目錄下CM4)

Source\portable\GCC\ARM_CM4F\protmacro.h

Source\portable\MemMang\heap_3.c (具體選用哪個可參考https://www.freertos.org/a00111.html)

特別注意:在選擇port.c時,一定要選擇與硬件對應的目錄,否則即使編譯通過了,也可能會跑不起來。

文件移植完成後,可以嘗試編譯看看,不過編譯過程中可能會報一些錯誤。

常用錯誤是啓動文件中的中斷響應函數需要做一些修改。

三、修改啓動文件

啓動文件中會用到port.c中的三個中斷函數。

vPortSVCHandler
xPortPendSVHandler
xPortSysTickHandler

這裏爲了保持啓動文件的一致性,我們不修改啓動文件,來修改port.c中的函數名:

vPortSVCHandler         修改爲:SVC_Handler
xPortPendSVHandler      修改爲:PendSV_Handler
xPortSysTickHandler     修改爲:SysTick_Handler

這個函數在stm32l4xx_it.c也有定義,所以需要將其註釋掉。

四、修改系統時鐘頻率

根據實際情況修改系統時鐘頻率:configCPU_CLOCK_HZ。

我的系統中使用SystemCoreClock定義的系統頻率。

在FreeRTOSConfig.h中修改如下:

#if 1//def __ICCARM__
    #include <stdint.h>
    extern uint32_t SystemCoreClock;
#endif

#define configUSE_PREEMPTION            1
#define configUSE_IDLE_HOOK                0
#define configUSE_TICK_HOOK                0
#define configCPU_CLOCK_HZ                ( SystemCoreClock )
#define configTICK_RATE_HZ                ( ( TickType_t ) 1000 )

我這裏通過前面這些步驟的修改,代碼已經順利編譯通過。若還有遇到編譯問題,可逐一排除(不清楚的可百度解決^_^)。

五、寫測試代碼

本例測試GPIOB6以1秒的頻率閃爍。

#include "main.h"

// FreeRTOS head file, add here.
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "list.h"
#include "portable.h"
#include "FreeRTOSConfig.h"


void taskMain(void *pvParameters)

{
    GPIO_InitTypeDef  GPIO_InitStruct;
    
    pvParameters = pvParameters;

    //初始化硬件
    HAL_Init();

    //打開GPIOB的時鐘
    __HAL_RCC_GPIOB_CLK_ENABLE();

    //初始化GPIOB6爲輸出
    GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull  = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    while(1)
    {
        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_6);
        vTaskDelay(1000/portTICK_RATE_MS);
    }
}

int main(void)
{
    //創建任務taskMain
    xTaskCreate( taskMain, "taskMain", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+2, NULL );

    // 啓動任務調度
    vTaskStartScheduler();

    return 0;
}

比較幸運……

編譯後直接跑起來了……

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