STM32移植FreeRTOS————STM32F103C8T6实现
目录
前言
一、FreeRTOS
二、下载FreeRTOS
1.进入官网
2.点击下载
3.下载FreeRTOS202212.01
三、移植FreeRTOS
1.解压
2.新建FreeRTOS
3.在FreeRTOS下新建inc、src、port
4.移植FreeRTOS头文件
5.移植配置文件
6.移植源文件
7.移植内存管理单元
8.移植port.c和portmacro.h
四、keil工程添加FreeRTOS
1.新建分组“FreeRTOS”
2.添加头文件路径
五、运行FreeRTOS
1.添加宏
2.注释SVC_Handler、PendSV_Handler、SysTick_Handler
3.勾选C99 Mode
4. 代码编写
标准库FreeRTOS工程下载链接
补充
总结
前言
本文是教你如何将FreeRTOS移植到自己搭建的标准库工程当中。你需要准备一块STM32系列的板子一块( 本文使用的是STM32F103c8t6 )和已经搭建好的标准库工程一个,然后就只需要跟着本文做就可以了。
文章末尾附有源工程(2024.11.11更新后)
一、FreeRTOS
在移植FreeRTOS前,先来认识认识FreeRTOS。
FreeRTOS是一个迷你的实时操作系统内核。作为一个轻量级的操作系统,功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程等,可基本满足较小系统的需要。
由于RTOS需占用一定的系统资源(尤其是RAM资源),只有μC/OS-II、embOS、salvo、FreeRTOS等少数实时操作系统能在小RAM单片机上运行。相对μC/OS-II、embOS等商业操作系统,FreeRTOS操作系统是完全免费的操作系统,具有源码公开、可移植、可裁减、调度策略灵活的特点,可以方便地移植到各种单片机上运行,其最新版本为11.0.0版。
在此就不再过多的介绍FreeRTOS,感兴趣的朋友可以自行百科。
二、下载FreeRTOS
你可以直接通过下方链接下载也可以根据后面的步骤去官网下载
百度网盘链接FreeRTOS202212.01
1.进入官网
点击下面的链接进入FreeRTOS官网
FreeRTOS官网网址
2.点击下载
在官网首页点击 “Download” 进入下载选项
图2-1
3.下载FreeRTOS202212.01
选择并且点击下载202212.01版本的FreeRTOS
图2-2
三、移植FreeRTOS
在移植FreeRTOS前还需要准备一个标准库搭建的工程,你可以通过下方第一个链接直接下载一个标准库工程,也可以跟着第二个链接自己搭建一个标准库工程。
工程链接
标准库工程(阿里云盘)
搭建链接
标准库搭建工程链接
1.解压
首先解压FreeRTOS202212.01压缩包,里面的文件如下图所示
图3-1
我们只关注FreeRTOS文件,因为这个FreeRTOS文件里面包含了移植FreeRTOS实时操作系统所需要的所有文件。
接下来开始移植FreeRTOS。
2.新建FreeRTOS
在搭建好的工程中新建FreeRTOS文件
图3-2
3.在FreeRTOS下新建inc、src、port
然后在FreeRTOS文件中新建inc、src、port三个文件
图3-3
inc 头文件
src源文件
port移植层
4.移植FreeRTOS头文件
将解压后的FreeRTOS的
…\FreeRTOSv202212.01\FreeRTOS\Source\include
路径下的所有文件复制到工程的FreeRTOS的inc
图3-4
5.移植配置文件
移植对应芯片的配置文件
将解压后的FreeRTOS的
…\FreeRTOSv202212.01\FreeRTOS\Demo\CORTEX_STM32F103_Keil
路径下的FreeRTOSConfig.h复制到工程的FreeRTOS的inc
图3-5
于是工程的FreeRTOS的inc文件内容如下(未截取完整)
图3-6
6.移植源文件
移植FreeRTOS源文件
将解压后的FreeRTOS的
…\FreeRTOSv202212.01\FreeRTOS\Source
路径下的所有.c文件复制到工程的FreeRTOS的src
图3-7
于是工程的FreeRTOS的src内容如下
图3-8
7.移植内存管理单元
移植内存管理单元(Memory Management Unit)
将解压后的FreeRTOS的
…\FreeRTOSv202212.01\FreeRTOS\Source\portable
路径下的MemMang复制到工程的FreeRTOS的portable
图3-9
8.移植port.c和portmacro.h
将对应芯片的port.c和portmacro.h移植到工程的port中
将解压后的FreeRTOS的
…\FreeRTOSv202212.01\FreeRTOS\Source\portable\RVDS\ARM_CM3
路径下的所有文件复制到工程的FreeRTOS的portable
图3-10
于是工程的FreeRTOS的port内容如下
图3-11
四、keil工程添加FreeRTOS
1.新建分组“FreeRTOS”
在工程树中新建分组“FreeRTOS”
首先将工程中的FreeRTOS下的src中的所有文件加入FreeRTOS分组中
再将工程中的FreeRTOS下的port中的port.c文件加入FreeRTOS分组中
最后将工程中的FreeRTOS下的port中的MenMang文件下的heap_4.c加入FreeRTOS分组中(为什么选择heap_4.c,你可以搜索 “ FreeRTOS内存管理 ”)
图4-1
2.添加头文件路径
图4-2
五、运行FreeRTOS
1.添加宏
为了让FreeRTOS正常工作还需在FreeRTOSConfig.h和stm32f10x_it.c两个文件中添加如下
3行宏定义
//code 01
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler
#define xPortSysTickHandler SysTick_Handler
图5-1
图5-2
2.注释SVC_Handler、PendSV_Handler、SysTick_Handler
注释掉stm32f10x_it.c下的SVC_Handler、PendSV_Handler、SysTick_Handler这3个函数。
图5-3
为什么要添加那3个宏呢?为什么又要注释掉stm32f10x_it.c下的SVC_Handler、PendSV_Handler、SysTick_Handler这3个函数?
首先解释第二个问题,stm32f10x_it.c文件中,SVC_Handler、PendSV_Handler和SysTick_Handler是标准库中三个关键的内核级中断服务例程
SVC_Handler通常处理来自操作系统的系统调用或异常情况
PendSV_Handler处理任务切换请求,即任务上下文的保存和恢复
SysTick_Handler是系统定时器的中断,用于时间管理,如调度周期性的任务
在FreeRTOS中已经重新声明和定义,如下图
图5-4
因此注释掉stm32f10x_it.c文件中,SVC_Handler、PendSV_Handler和SysTick_Handler三个中断服务例程是为了避免FreeRTOS与STM32标准库中的定义冲突。
其次在FreeRTOS的配置文件FreeRTOSconfig.h中,通过宏定义将FreeRTOS的中断服务函数映射到标准库的中断向量表中。例如,vProtSVC_Handler被映射到SVC_Handler,xProtPendSVHandler被映射到PendSV_Handler,xProtSysTickHandler被映射到SysTick_Handler。
因此现在对于第一个问题就显而易见了。
因此不注释掉这些函数,编译器会检测到重复定义的错误,导致编译失败。通过注释掉这些函数,可以避免编译错误,并确保FreeRTOS的中断服务函数能够正确执行。
3.勾选C99 Mode
Options for Target ——>C/C++——>C99 Mode
图5-5
4. 代码编写
最后用下面的代码直接替换main.c中的所有代码,代码如下
//code 02
#include "stm32f10x.h" // Device header
#include "FreeRTOS.h"
#include "task.h"
TaskHandle_t app_task1_handle = NULL;
TaskHandle_t app_task2_handle = NULL;
void App_Task1(void* pvParamenters);
void App_Task2(void* pvParamenters);
int main(void)
{
//将全部优先级设为抢占优先级
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
//创建任务
xTaskCreate((TaskFunction_t)App_Task1, //任务入口函数
(const char *)"App_Task1", //任务名字
(uint16_t)configMINIMAL_STACK_SIZE, //任务栈大小
(void*)NULL, //任务入口函数参数
(UBaseType_t)1, //任务优先级
(TaskHandle_t*)&app_task1_handle); //任务句柄
//创建任务
xTaskCreate((TaskFunction_t)App_Task2, //任务入口函数
(const char *)"App_Task2", //任务名字
(uint16_t)configMINIMAL_STACK_SIZE, //任务栈大小
(void*)NULL, //任务入口函数参数
(UBaseType_t)1, //任务优先级
(TaskHandle_t*)&app_task2_handle); //任务句柄
//开启任务调度器
vTaskStartScheduler();
}
void LED_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//使能C端口时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50Mhz
GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化GPIOC
}
void App_Task1(void *pvParameters)
{
LED_Init();
for(;;)
{
GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);
vTaskDelay(500);
GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
vTaskDelay(500);
}
}
void App_Task2(void *pvParameters)
{
for(;;)
{
}
}
调试下载后现象是LED灯闪亮。为了验证任务2也可以执行,还需要将任务1中的内容和任务2中的内容交换。交换后LED灯依旧闪亮,则移植成功。
标准库FreeRTOS工程下载链接
标准库FreeRTOS工程模板
补充
有个小问题,我的一位朋友在复制main.c代码的时候,使用手机阅读的,于是用手机复制的,再传到电脑上使用,会报错。可能是文本的转换出了问题,因此推荐大家使用电脑复制
总结
关于将FreeRTOS的移植到自己的标准库工程中
首先,需要在工程中创建FreeRTOS文件,并在FreeRTOS文件中新建inc、src、port三个子文件
其次,就是将官方给出的FreeRTOS移植到自己的工程中
最后,就是将FreeRTOS添加进自己的keil工程中,并在FreeRTOSConfig.h和stm32f10x_it.c这2个文件中添加宏定义和注释掉stm32f10x_it.c文件中的SVC_Handler、PendSV_Handler、SysTick_Handler这3个函数
作者:落魄理想