准备工作
我这里是基于STM32F407平台移植FreeRTOS,准备资料如下:
- 已经移植STM32F407标准库的工程;
- FreeRTOSv10.2.1_191129内核源码;(前面有文章说过如何下载FreeRTOS内核源码)
FreeRTOS详细的移植步骤
-
解压FreeRTOS就能得到这个目录(
FreeRTOS\FreeRTOSv10.2.1_191129\FreeRTOS\Source
)
这个目录下的源码都是需要拷贝到你的Keil项目里面的。但是portable需要我们筛选一下。
-
如何客制化portable目录
下面的截图是FreeRTOS官网的提示,必须包含的文件:
compiler我使用的是Keil,所以就来到了portable/Keil目录,但是它是空的并且提示See-also-the-RVDS-directory
,所以我们最终需要的port.c在RVDS目录下:
MemMang是内存管理需要包含的部分,根据FreeRTOS官网的提示我这里选择了heap_4.c
,它会合并相邻的空闲块以避免碎片化。
-
最终添加它们到工程
如下截图是最终添加到里面的文件,并且相关的头文件也需要拷贝过来。
以上就是所有移植过程。
FreeRTOS Demo
这个Demo code里面只是简单的创建了2个Task,循环的去执行。这么编写code之后,发现编译没有报错,但是2个Task好像并没有跑起来。
#include "main.h"
#include "./usart/bsp_debug_usart1.h"
#include "./led/bsp_led.h"
#include "./systick/bsp_systick.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "list.h"
static TaskHandle_t xHandleTask1 = NULL;
static TaskHandle_t xHandleTask2 = NULL;
void AppTask1(void *pvParameters);
void AppTask2(void *pvParameters);
int main(void)
{
// init led
LED_GPIO_Config();
LED2(ON);
LED3(ON);
// init uart
Debug_USART1_Config();
printf("starting up!!!\r\n");
// init systick
//SysTick_Init();
xTaskCreate(AppTask1,"Task1",512,NULL, 2,&xHandleTask1);
xTaskCreate(AppTask2,"Task2",512,NULL, 2,&xHandleTask2);
vTaskStartScheduler();
while(1){
//Delay_ms(1000);
//printf("main runing!!!\r\n");
}
//return 0;
}
void AppTask1(void *pvParameters)
{
static uint32_t count = 0;
while(1)
{
count++;
printf("Task1=%d\r\n",count);
vTaskDelay( 1000 );
}
}
void AppTask2(void *pvParameters)
{
static uint32_t count = 0;
while(1)
{
count++;
printf("Task2=%d\r\n",count);
vTaskDelay( 1000 );
}
}
经过百度之后发现,有一个关键的Systick没有客制化,在FreeRTOSConfig.h
里面添加如下代码:
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
(NOTE: 在stm32f4xx_it.c中有定义这些函数,需要屏蔽掉,否则会重复定义。)
到这里重新编译验证OK,UART打印如下:
移植过程中出现的错误
-
错误1
..\FreeRTOS\inc\FreeRTOS.h(56): error: #5: cannot open source input file "FreeRTOSConfig.h": No such file or directory
解决方法:
FreeRTOSConfig.h这个头文件用来配置FreeRTOS的功能,最开始并不知道需要配置哪些宏,可以在FreeRTOS的源码包里面Demo Code拷贝一个过来,并且修改一下配置参数。例如:FreeRTOS\FreeRTOSv10.2.1_191129\FreeRTOS\Demo\CORTEX_STM32F103_Keil\FreeRTOSConfig.h
// STM32F407主频为168M #define configCPU_CLOCK_HZ ( ( unsigned long ) 168000000 )
-
错误2
..\Output\stm32f407.axf: Error: L6218E: Undefined symbol xTaskGetCurrentTaskHandle (referred from stream_buffer.o).
解决办法:
因为文件用到了xTaskGetCurrentTaskHandle,但是没有被定义,所以这里报错。在文件FreeRTOSConfig.h中,宏INCLUDE_xTaskGetCurrentTaskHandle必须设置为1,此函数才有效。#define INCLUDE_xTaskGetCurrentTaskHandle 1
完整的工程代码
https://gitee.com/dianqi0901zc/stm32_project.git
(在这里仓库下的 stm32f407_freertos_base目录就是本次移植的完整的工程代码)