1、源码准备
首先准备好我们下载好的FreeRTOS源码以及STM32F407的工程模板(这里以原子的F4跑马灯工程为例,可去原子的开源论坛自行下载),源码下载及参考请参考我的上一篇博客。
2、创建FreeRTOS文件夹
在工程中创建FreeRTOS文件夹,将FreeRTOS源码全部复制到该文件夹下

打开portable文件夹,删除没用的文件,留下如下文件即可

3、在工程中添加FreeRTOS源码
打开工程,在工程中新建FreeRTOS_CORE和FreeRTOS_PORTABLE,然后向着两个组中添加对应的文件,如下图所示:

FreeRTOS_CORE的文件打开FreeRTOS就可看到,port.c是RVDS文件夹下的ARM_CM4F中的,因为STM32F407是Cortex-M4内核并且带FPU。Heap_4.c是MemMang文件夹中,这里有5个文件,是5个不同的内存管理方法,为什么选择第4个,因为FreeRTOS内存管理所决定。
4、添加对应的头文件路径

5、编译及错误解决
5.1 找不到FreeRTOSConfig.h文件
完成后编译一下,会出现如下错误

很明显是没有FreeRTOSConfig.h这个文件,那我们就把它添加进去,具体位置在FreeRTOS的DEMO中找到CORTEX_M4F_STM32F407ZG-SK文件,如下图所示

至于放到哪个位置自己随意,一般是放在FreeRTOS的include里面,而这个文件是FreeRTOS的配置文件,一般操作系统都有裁剪、配置功能,而这些都是通过一个文件内的宏定义来完成。
5.2 SystemCoreClock未定义
接着上面的步骤再编译一次,还会出现以下错误,意思是SystemCoreClock未定义

解决办法:修改条件编译

5.3 重复定义
接着再编译一下,发现还有错误,这次的错误是重复定义

解决办法:
屏蔽掉stm32f4xx_it.c中的PendSV_Handler(),SVC_Handler(),SysTick_Handler()这三个函数,

5.4 钩子函数未定义
继续编译一次,还是会有错,这次的错是函数未定义,他们都是Hook结尾的,称为钩子函数。

解决办法:
去FreeRTOSConfig.h中关闭这些钩子函数,他们都是宏定义决定,这里将configUSE_IDLE_HOOK、configUSE_TICK_HOOK、configUSE_MALLOC_FAILED_HOOK和configUSE_FOR_STACK_OVERFLOW定义为0.

再编译一下应该就没错了。
6、修改SYSTEM文件
因为原子的SYSTEM文件夹是针对UCOS编写的,所以要进行对应的修改
6.1 修改sys.h文件
把宏定义改为1即可,要支持OS,UCOS也一样的

6.2 修改usart.c文件
修改头文件为

修改串口中断服务函数为:

6.3 修改delay.c文件
同样先修改宏定义的头文件

接着修改systick中断服务函数为

在滴答定时器中断服务函数中调用FreeRTOS的API函数xPortSysTickHandler();
在修改delay_init()函数,如下:

接下来就是延时函数的修改

修改完后再编译一下,会出现重复定义的错误,如下图:

解决办法:屏蔽FreeRTOSConfig.h掉底部的#define xPortSysTickHandler SysTick_Handler

7、修改main.c进行功能验证
主函数主要是实现实时系统多任务的创建,具体如下
#include “sys.h”
#include “delay.h”
#include “usart.h”
#include “led.h”
#include “FreeRTOS.h”
#include “task.h”
#define START_TASK_PRIO 1
#define START_STK_SIZE 120
void start_task(void * pvParameters); //任务函数
TaskHandle_t StartTask_Handler; //任务句柄
#define TASK1_TASK_PRIO 2
#define TASK1_STK_SIZE 120
void task1_task(void * pvParameters);
TaskHandle_t Task1Task_Handler; //任务句柄
#define TASK2_TASK_PRIO 3
#define TASK2_STK_SIZE 120
void task2_task(void * pvParameters);
TaskHandle_t Task2Task_Handler; //任务句柄
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init(168); //初始化延时函数
LED_Init(); //初始化LED
uart_init(115200); //初始化串口
xTaskCreate((TaskFunction_t ) start_task,
(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)
{
//创建Task1
xTaskCreate((TaskFunction_t ) task1_task,
(char* ) “task1_task”,
(uint16_t ) TASK1_STK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK1_TASK_PRIO,
(TaskHandle_t* ) &Task1Task_Handler);
//创建Task2
xTaskCreate((TaskFunction_t ) task2_task,
(char* ) “task2_task”,
(uint16_t ) TASK1_STK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK2_TASK_PRIO,
(TaskHandle_t* ) &Task2Task_Handler);
vTaskDelete(StartTask_Handler); //NULL
}
void task1_task(void * pvParameters)
{
char task1_num=0;
while(1)
{
task1_num++;
LED0 = ~LED0;
printf(“Task1 Runing %d !rn”,task1_num);
vTaskDelay(1000);
}
}
void task2_task(void * pvParameters)
{
char task2_num=0;
while(1)
{
task2_num++;
LED1 = ~LED1;
printf(“Task2 Runing %d!rn”,task2_num);
vTaskDelay(500);
}
}
实验现象;
开发板上LED0和LED1进行不同状态的闪烁,串口也会打印任务执行次数,很明显任务二的速度是任务一的两倍。

我这里使用的是STM32F407VET6,原理都差不多,用那块板子都一样。至此,FreeRTOS移植和任务创建成功。
1、源码准备
首先准备好我们下载好的FreeRTOS源码以及STM32F407的工程模板(这里以原子的F4跑马灯工程为例,可去原子的开源论坛自行下载),源码下载及参考请参考我的上一篇博客。
2、创建FreeRTOS文件夹
在工程中创建FreeRTOS文件夹,将FreeRTOS源码全部复制到该文件夹下

打开portable文件夹,删除没用的文件,留下如下文件即可

3、在工程中添加FreeRTOS源码
打开工程,在工程中新建FreeRTOS_CORE和FreeRTOS_PORTABLE,然后向着两个组中添加对应的文件,如下图所示:

FreeRTOS_CORE的文件打开FreeRTOS就可看到,port.c是RVDS文件夹下的ARM_CM4F中的,因为STM32F407是Cortex-M4内核并且带FPU。Heap_4.c是MemMang文件夹中,这里有5个文件,是5个不同的内存管理方法,为什么选择第4个,因为FreeRTOS内存管理所决定。
4、添加对应的头文件路径

5、编译及错误解决
5.1 找不到FreeRTOSConfig.h文件
完成后编译一下,会出现如下错误

很明显是没有FreeRTOSConfig.h这个文件,那我们就把它添加进去,具体位置在FreeRTOS的DEMO中找到CORTEX_M4F_STM32F407ZG-SK文件,如下图所示

至于放到哪个位置自己随意,一般是放在FreeRTOS的include里面,而这个文件是FreeRTOS的配置文件,一般操作系统都有裁剪、配置功能,而这些都是通过一个文件内的宏定义来完成。
5.2 SystemCoreClock未定义
接着上面的步骤再编译一次,还会出现以下错误,意思是SystemCoreClock未定义

解决办法:修改条件编译

5.3 重复定义
接着再编译一下,发现还有错误,这次的错误是重复定义

解决办法:
屏蔽掉stm32f4xx_it.c中的PendSV_Handler(),SVC_Handler(),SysTick_Handler()这三个函数,

5.4 钩子函数未定义
继续编译一次,还是会有错,这次的错是函数未定义,他们都是Hook结尾的,称为钩子函数。

解决办法:
去FreeRTOSConfig.h中关闭这些钩子函数,他们都是宏定义决定,这里将configUSE_IDLE_HOOK、configUSE_TICK_HOOK、configUSE_MALLOC_FAILED_HOOK和configUSE_FOR_STACK_OVERFLOW定义为0.

再编译一下应该就没错了。
6、修改SYSTEM文件
因为原子的SYSTEM文件夹是针对UCOS编写的,所以要进行对应的修改
6.1 修改sys.h文件
把宏定义改为1即可,要支持OS,UCOS也一样的

6.2 修改usart.c文件
修改头文件为

修改串口中断服务函数为:

6.3 修改delay.c文件
同样先修改宏定义的头文件

接着修改systick中断服务函数为

在滴答定时器中断服务函数中调用FreeRTOS的API函数xPortSysTickHandler();
在修改delay_init()函数,如下:

接下来就是延时函数的修改

修改完后再编译一下,会出现重复定义的错误,如下图:

解决办法:屏蔽FreeRTOSConfig.h掉底部的#define xPortSysTickHandler SysTick_Handler

7、修改main.c进行功能验证
主函数主要是实现实时系统多任务的创建,具体如下
#include “sys.h”
#include “delay.h”
#include “usart.h”
#include “led.h”
#include “FreeRTOS.h”
#include “task.h”
#define START_TASK_PRIO 1
#define START_STK_SIZE 120
void start_task(void * pvParameters); //任务函数
TaskHandle_t StartTask_Handler; //任务句柄
#define TASK1_TASK_PRIO 2
#define TASK1_STK_SIZE 120
void task1_task(void * pvParameters);
TaskHandle_t Task1Task_Handler; //任务句柄
#define TASK2_TASK_PRIO 3
#define TASK2_STK_SIZE 120
void task2_task(void * pvParameters);
TaskHandle_t Task2Task_Handler; //任务句柄
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init(168); //初始化延时函数
LED_Init(); //初始化LED
uart_init(115200); //初始化串口
xTaskCreate((TaskFunction_t ) start_task,
(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)
{
//创建Task1
xTaskCreate((TaskFunction_t ) task1_task,
(char* ) “task1_task”,
(uint16_t ) TASK1_STK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK1_TASK_PRIO,
(TaskHandle_t* ) &Task1Task_Handler);
//创建Task2
xTaskCreate((TaskFunction_t ) task2_task,
(char* ) “task2_task”,
(uint16_t ) TASK1_STK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK2_TASK_PRIO,
(TaskHandle_t* ) &Task2Task_Handler);
vTaskDelete(StartTask_Handler); //NULL
}
void task1_task(void * pvParameters)
{
char task1_num=0;
while(1)
{
task1_num++;
LED0 = ~LED0;
printf(“Task1 Runing %d !rn”,task1_num);
vTaskDelay(1000);
}
}
void task2_task(void * pvParameters)
{
char task2_num=0;
while(1)
{
task2_num++;
LED1 = ~LED1;
printf(“Task2 Runing %d!rn”,task2_num);
vTaskDelay(500);
}
}
实验现象;
开发板上LED0和LED1进行不同状态的闪烁,串口也会打印任务执行次数,很明显任务二的速度是任务一的两倍。

我这里使用的是STM32F407VET6,原理都差不多,用那块板子都一样。至此,FreeRTOS移植和任务创建成功。
举报