轉自:https://www.jianshu.com/p/d4c53f63c686
內容目錄
一、FreeRTOS 源碼的獲取
二、移植 FreeRTOS
參考文獻
一、FreeRTOS 源碼的獲取
圖 1-1 FreeRTOS 官方網站.png
點擊左邊的【Download Source】,選擇相應的方式下載源碼:
圖 1- 2 FreeRTOS 下載.png
【Latest News】顯示的是當前 FreeRTOS 的版本信息和支持的一些芯片信息,點擊【Download Source Code and Projects】後,稍等一會就會自動下載官方的 .exe 文件:FreeRTOSv10.1.1.exe,雙擊運行,選擇安裝目錄,等待完成,目錄結構如下:
圖 1- 3 FreeRTOS 目錄結構.png
① FreeRTOS : 主要存放的是 OS 的源碼和 DEMO;
② FreeRTOS-Plus : 主要存放的是 OS 的一些擴展功能,比如 TCP/IP;
我們目前要使用的是 FreeRTOS 目錄的內容:
圖 1- 4 FreeRTOS 目錄結構.png
① DEMO :FreeRTOS 給各個廠商開發的例程文件;
② License : 裏面存放了 license 說明文檔;
③ Source : 內核代碼文件,移植主要用到的文件都在這裏面;
圖 1- 5 Source 目錄結構.png
① include : 存放的事通用的頭文件
② portable : 與編譯器有關的代碼,裏面存放着不同編譯器的工程文件;
這時候我們需要的文件目錄大概就是:
① Source 目錄下的文件
② Source 目錄下的 include 文件夾
③ Source 目錄下的 portable 文件夾下面的MemMang 和 RVDS
④ Demo 目錄下的例程裏面的FreeRTOSConfig.h 文件
二、移植 FreeRTOS
基於裸板的 Driver 的工程已經完成,現在就把 FreeRTOS 移植過來,在工程目錄新建文件夾:
① src : 把 FreeRTOS 目錄下的源文件都放進來,除了 include 文件夾和 portable 文件夾
② include : 把 FreeRTOS 目錄下的 include 文件夾複製過來
③ portable : 把 RVDS 文件夾和 Memmang 文件夾複製過來
圖 2- 1 src 文件夾.png
圖 2- 2 include 文件夾.png
圖 2- 3 portable 文件夾.png
在工程裏面添加組,並把相應文件都添加進來:
① freertos/src :把所有 src 文件夾裏面的源文件都添加進來
② freertos/portable : 把 MemMang 文件夾的 heap_4.c 和 RVDS/ ARM_CM4F/port.c 添加進來
③ app : 把Demo 裏面的CORTEX_M4F_STM32F407ZG-SK 的FreeRTOSConfig.h 複製到 app 文件夾
圖 2- 4 工程組結構.png
圖 2- 5 設置 FreeRTOS 頭文件路徑.png
圖 2- 6 添加 FreeRTOS 頭文件.png
先進行一次編譯,發現報錯:
圖 2- 7 首次編譯報錯.png
從報錯的內容看,都是缺少定義後綴爲 Hook 的函數,這些函數都是鉤子函數,我們在提示錯誤的源文件裏面都能找到相應的函數聲明:
圖 2- 8 缺少定義的鉤子函數.png
因爲我們在 FreeRTOSConfig.h 裏面打開了一些宏定義,這些宏定義打開後,源文件會使用這些鉤子函數,這裏我們只要把這些鉤子函數定義一下就行了,在 main.c 我們把這幾個鉤子函數都定義出來:
/* hook function,no using,avoid compiler indicate error */
void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName )
{}
void vApplicationTickHook( void )
{}
void vApplicationIdleHook( void )
{}
void vApplicationMallocFailedHook( void )
{}
添加定義完成後,我們再次編譯,
圖 2- 9 缺少SystemCoreClock 定義.png
修改 FreeRTOSConfig.h
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 1
#define configCPU_CLOCK_HZ ( 80000000UL ) //( SystemCoreClock )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 75 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 10 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_MALLOC_FAILED_HOOK 1
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configGENERATE_RUN_TIME_STATS 0
再次編譯,發現編譯已經能正常通過了:
圖 2- 10 添加鉤子函數後編譯通過.png
至此,FreeRTOS 相應的文件已經都添加進來了,點擊編譯,能正常編譯通過,但是系統還不能工作,因爲 FreeRTOS 需要一個定時器作爲系統的心跳,cortex-m4 內核提供了一個 systick 系統定時器,做爲嵌入式操作系統的心跳,我們參考清華大學出版社出版的《ARM Cortex-M3與Cortex-M4權威指南》和 《Cortex-M3權威指南》來配置 systick 定時器。
配置完 systick 定時器,只是開啓了定時以及中斷使能,但是中斷優先級還沒有設置,cortex-m4 內核有一個系統控制塊單元 SBC,System Control Block 的 SHR 寄存器可以配置系統中斷的優先級:
最終寄存器配置:
unsigned int SysTick_Config(unsigned int ticks)
{
SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
SCB->SHP[(((uint32_t)-1) & 0xFUL)-4UL] = (uint8_t)((((1UL << 4) - 1UL) << (8U - 4)) & (uint32_t)0xFFUL);
SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
SysTick->CTRL = (1<<2) |
(1<<1) |
(1<<0); /* Enable SysTick IRQ and SysTick Timer */
return (0UL); /* Function successful */
}
配置完 systick ,main.c 也需要修改,FreeRTOS 需要建立任務才能執行:
void systick_init(void)
{
SysTick_Config(80000);
}
int main(void)
{
bsp_init();
systick_init();
/* Create the queue. */
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( unsigned long ) );
xTaskCreate((TaskFunction_t )AppTask,
(const char* )"AppTask",
(uint16_t )512,
(void* )NULL,
(UBaseType_t )5,
(TaskHandle_t* )&AppTask_Handle);
xTaskCreate( UartQueueReceiveTask, "RX", 128, NULL, 2, NULL );
xTaskCreate( UartQueueSendTask, "TX", 128, NULL, 3, NULL );
vTaskStartScheduler();
while(1);
}
在主函數初始化 systick 後,利用 FreeRTOS 系統提供的接口 xTaskCreate 創建名字爲 “App” 的任務,點擊編譯:
圖 2- 11 堆棧空間不足.png
從提示中可以看到,錯誤提示的是 head_4.c 的 bss 段沒有空間存放了,這時候看 FreeRTOSConfig.h 裏面的配置:
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 1
#define configCPU_CLOCK_HZ ( 48000000UL ) //( SystemCoreClock )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 75 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 10 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_MALLOC_FAILED_HOOK 1
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configGENERATE_RUN_TIME_STATS 0
堆棧目前設定的大小是 75*1024,太大了,設置小一點 :
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 1
#define configCPU_CLOCK_HZ ( 48000000UL ) //( SystemCoreClock )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) 8192 ) //( ( size_t ) ( 75 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 10 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_MALLOC_FAILED_HOOK 1
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configGENERATE_RUN_TIME_STATS 0
這時候編譯就通過了。把程序下載到 EVM 板子上,就可以看到藍色的小燈不停的閃爍,這說明移植過來的 FreeRTOS 能工作了,到此, 整個移植流程已經完成了。
參考文獻
《ARM Cortex-M3與Cortex-M4權威指南》
《CM3權威指南》
代碼路徑:
鏈接: https://pan.baidu.com/s/1O45iXaZ1RMdszz1_Y3NiOA 提取碼: xevj
作者:Depthkernelcore
鏈接:https://www.jianshu.com/p/d4c53f63c686
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。