1. 程式人生 > >第一節:FreeRTOS (MDK)系統移植 (詳細)

第一節:FreeRTOS (MDK)系統移植 (詳細)

移植總結:

第一步準備素材:如何在官網上下載原始檔

第二步移植程式碼:包括兩步:①從原始碼中提需需要的檔案②將程式碼新增到工程中

第三步修改程式碼:最關鍵的一步使程式碼能夠執行起來。

移植例程程式碼DEMO https://download.csdn.net/download/zennaiheqiao/10661276

 

第一步:準備素材(原始碼的下載)

(1)首先在FreeRTOS的網站官方可以下載到最新版的FreeRTOS的包。 

(2)解壓下載的檔案(瞭解檔案大概內容)

1,下載包根目錄下包含兩個子目錄:FreeRTOS的和FreeRTOS的-PLUS其中,FreeRTOS的加資料夾中包含一些FreeRTOS的+元件和演示例程(元件大都收費),我們不對這個資料夾下的內容多做了解,重點說一下FreeRTOS資料夾.freeRTOS和freeRTOS都是放置原始碼的,加上只是配置更強大了。包含了CLI FAT Trace一些擴充套件例程

 

2,FreeRTOS資料夾介紹下包含三個子目錄:Demo,License,Source。

其中,演示包含演示例程的工程檔案,原始碼包含實時作業系統原始碼檔案。

其中Demo資料夾包含了各類處理器的Demo程式。其中包括407和103的程式,FreeRTOSConfig.h檔案就是裡面複製出來的。

 

Source原始碼:包括include和porttable。(包括是一些標頭檔案,porttable是操作硬體的一些封裝。)

 

(3)提取源中的原始檔(移植用)

FreeRTOS的實時作業系統核心僅包含三個必要檔案,此外還有三個可選檔案.RTOS核心程式碼位於三個原始檔中,分別是tasks.c,queue.c和list.c.這三個檔案位於FreeRTOS作業系統/源目錄下,在同一目錄下還有3個可選的檔案,叫做timers.c,event_groups.c和croutine.c,分別用於軟體定時器,事件組和協程。

Keil資料夾是必須的,但是開啟後發現需要去拷貝RVDS的檔案,“參見-RVDS目錄”,即檔案複用

MemMang是資料夾跟記憶體相關的。

對於支援的處理器架構,RTOS需要一些與處理器架構相關的程式碼。可以稱之為RTOS硬體介面層,它們位於FreeRTOS/Source/Portable/[相應編譯器]/[相應處理器架構]資料夾下。我們這次要移植到Cortex-M3微控制,使用Keil MDK編譯器,所以需要的RTOS硬體介面程式碼位於:FreeRTOS\Source\portable\RVDS\ARM_CM3資料夾下。

MemMang裡面有5中記憶體的管理方式,都可以用各有優缺點後面會研究,選第四種使用。

堆疊分配也是屬於硬體介面層(移植層),在FreeRTOS/Source/portable/MemMang資料夾下具有各種型別的堆疊分配方案。這裡我們使用heap_1.c提供的堆疊分配方案。關於FreeRTOS的記憶體管理,後續《FreeRTOS記憶體管理》一文中會詳細介紹FreeRTOS記憶體管理的特性和用法,《FreeRTOS記憶體管理分析》一文會從原始碼級別分析FreeRTOS記憶體管理的具體實現,這裡不用多糾結,

問價準備齊了。準備幹活FreeRTOS

 

 

 

 

 

 

第二步:移植程式碼

準備移植的檔案

新建一個FreeRTOS資料夾,將Source 資料夾內容全copy過來

portable刪除無關的檔案,資料準備完全。

 

工程新增移植檔案

 在工程中新增如下檔案。並設定路徑。

編譯後

去官方的STM32F103中COPY一個FreeRTOSConfig.h  

再次編譯,無錯誤。

修改程式碼

①新建一個FreeRTOS資料夾,將Source 資料夾內容全copy過來

②掛接中斷

注意工程內不能有 SysTick,PendSV 和 SVC 三個系統中斷的使用,因為 FreeRTOS 系統要使用這三個中斷

有的話遮蔽就好了

在Cortex-M3硬體下,FreeRTOS使用SysTick作為系統節拍時鐘,使用SVC和PendSVC進行上下文切換。異常中斷服務程式碼位於…\FreeRTOS\Source\portable\IAR\ARM_CM3\port.c檔案中,FreeRTOS已經為各種構架的CPU寫好了這些程式碼,可以直接拿來用,需要做的是將這些異常中斷的入口地址掛接到啟動程式碼中。在 FreeRTOSConfig.h 新增如下定義:

#define xPortPendSVHandler  PendSV_Handler
#define vPortSVCHandler     SVC_Handler
#define xPortSysTickHandler SysTick_Handler

 

編譯後無錯誤。

新增任務:

需要包含標頭檔案 "FreeRTOS.h""task.h" "timers.h" "croutine.h"

/* 包含標頭檔案 ----------------------------------------------------------------*/
#include "stm32f10x.h"
#include "bsp/usart/bsp_debug_usart.h"
#include "includes.h"
/* 私有型別定義 --------------------------------------------------------------*/
/* 私有巨集定義 ----------------------------------------------------------------*/
/* 私有變數 ------------------------------------------------------------------*/
/* 擴充套件變數 ------------------------------------------------------------------*/
/* 私有函式原形 --------------------------------------------------------------*/
/* 函式體 --------------------------------------------------------------------*/

/**
  * 函式功能: 主函式.
  * 輸入引數: 無
  * 返 回 值: 無
  * 說    明: 無
  */
	




//任務優先順序
#define START_TASK_PRIO		1
//任務堆疊大小	
#define START_STK_SIZE 		128  
//任務控制代碼
TaskHandle_t StartTask_Handler;
//任務函式
void start_task(void *pvParameters);

//任務優先順序
#define LED0_TASK_PRIO		2
//任務堆疊大小	
#define LED0_STK_SIZE 		50  
//任務控制代碼
TaskHandle_t LED0Task_Handler;
//任務函式
void led0_task(void *pvParameters);

//任務優先順序
#define LED1_TASK_PRIO		3
//任務堆疊大小	
#define LED1_STK_SIZE 		50  
//任務控制代碼
TaskHandle_t LED1Task_Handler;
//任務函式
void led1_task(void *pvParameters);









	
	
	
int main(void)
{  
  char str[20];
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//設定系統中斷優先順序分組4	 	
  DEBUG_USART_Init();   /* 除錯串列埠初始化配置,115200-N-8-1.使能串列埠傳送和接受 */
  printf("FreeRTOS DEMO !");
  
  	//建立開始任務
    xTaskCreate((TaskFunction_t )start_task,            //任務函式
                (const char*    )"start_task",          //任務名稱
                (uint16_t       )START_STK_SIZE,        //任務堆疊大小
                (void*          )NULL,                  //傳遞給任務函式的引數
                (UBaseType_t    )START_TASK_PRIO,       //任務優先順序
                (TaskHandle_t*  )&StartTask_Handler);   //任務控制代碼              
    vTaskStartScheduler();          //開啟任務排程
}

//開始任務任務函式
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //進入臨界區
    //建立LED0任務
    xTaskCreate((TaskFunction_t )led0_task,     	
                (const char*    )"led0_task",   	
                (uint16_t       )LED0_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )LED0_TASK_PRIO,	
                (TaskHandle_t*  )&LED0Task_Handler);   
    //建立LED1任務
    xTaskCreate((TaskFunction_t )led1_task,     
                (const char*    )"led1_task",   
                (uint16_t       )LED1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LED1_TASK_PRIO,
                (TaskHandle_t*  )&LED1Task_Handler);         
    vTaskDelete(StartTask_Handler); //刪除開始任務
    taskEXIT_CRITICAL();            //退出臨界區
}

//LED0任務函式 
void led0_task(void *pvParameters)
{
    while(1)
    {
       printf(" Task 1 \r\n");
        vTaskDelay(500);
    }
}   

//LED1任務函式
void led1_task(void *pvParameters)
{
    while(1)
    {
         printf(" Task 2_1 \r\n");
        vTaskDelay(200);
         printf(" Task 2_2 \r\n");
        vTaskDelay(800);
    }
}

/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式開發團隊 *****END OF FILE****/

總結:FreeRTOS 移植難度不大

①下載原始碼是在官網上下載的最新版本,移植時候沒有版本限制。

②移植原始碼後,工程少一個FreeRTOSConfig.h檔案這個直接在 DEMO例程裡面複製.

③掛接中斷,程式中有掛接中斷這個環節,這個需要注意。然後新增程式就可以運行了。

後續要搞懂的問題是如何修改嘀嗒定時器,和一些內部執行 的機制。

 

https://blog.csdn.net/zhzht19861011/article/details/50072033

關於配置節拍

這裡我們使用SysTick定時器作為系統的節拍時鐘,設定每隔10ms產生一次節拍中斷。由於FreeRTOS對移植做了非常多的工作,以至於我們只需要在FreeRTOSConfig.h中配置好以下兩個巨集定義即可:

 

  1. configCPU_CLOCK_HZ     (/*你的硬體平臺CPU系統時鐘,Fcclk*/)
  2. configTICK_RATE_HZ       ((portTickType)100)         

 

      第一個巨集定義CPU系統時鐘,也就是CPU執行時的頻率。第二個巨集定義FreeRTOS的時間片頻率,這裡定義為100,表明RTOS一秒鐘可以切換100次任務,也就是每個時間片為10ms。

      在prot.c中,函式vPortSetupTimerInterrupt()設定節拍時鐘該函式根據上面的兩個巨集定義的引數,計算系統定時器定時器的重灌載數值暫存器,然後設定系統定時器定時器的控制及狀態暫存器,設定如下:使用核心時鐘源,使能中斷,使能系統定時器定時器。另外,函式vPortSetupTimerInterrupt()由函式vTaskStartScheduler()呼叫,這個函式用於啟動排程器。