前言
本文是在Windows10环境下,以VSCode+arm交叉编译工具链为开发环境,将FreeRTOS移植到STM32F103系列单片机的说明。其实不叫移植,叫做拷贝,大家都叫移植,那就这样叫了。
工程基于你自己的一个能运行的裸机工程。并且我用的是标准固件库。
为啥搭建这个环境,首先是喜欢用VSCode编辑,还有一个重要原因是,用到的所有工具都是开源的,不用担心版权问题。没钱买有些正版工具,又不想用盗版的人最后的倔强(笑死)。当然付费的有付费的优势,买了服务嘛!有时候免费的才是最贵的,遇到问题只能自己苦逼到处寻找解决方案哈哈!
先看第七节附录,或许对你有帮助!
上述工具中,前3项是必须的。CMake可以帮助我们生成Makefile文件,如果你自己写Makefile可以不用;OpenOCD是片上调试工具,可以下载和调试,当然你也可以生成二进制文件,用串口下载,不是必须。
这里就不再赘述工具的安装,未配置好环境的读者,可以参考其他文章,先将工具安装好。
直接在FreeRTOS官网下载最新的即可,我这里下载的普通版,没有下载长期支持版。官网下载地址
一个能跑的裸机工程,最好带串口驱动的。
在准备好的裸机工程根目录中创建FreeRTOS文件夹,用于存放系统源码。
新的根目录:
解压刚刚下载的FreeRTOS的压缩包,并将路径\FreeRTOSv202212.01\FreeRTOS\Source
下的所有文件拷贝到上一步创建的freertos文件夹下,拷贝后,如下图。
进入FreeRTOSv202212.01\FreeRTOS\Demo\CORTEX_STM32F103_Primer_GCC
,将main.c
以及FreeRTOSConfig.h
复制到你自己的用户代码文件夹下面。
进入\Demo\freertos\portable
文件夹,如下图。留下GCC和MemMang,其余的全部删除。
删除后:
我这里用的CMakeLists.txt,故只给出CMakeLists.txt的修改。就是在CMakeLists.txt中增加源文件以及头文件的包含路径。
根据你自己文件结构的情况修改即可。
以前的:
在FreeRTOSConfig.h文件最后加上如下三句宏定义,意思是使用FreeRTOS给我们写好的这三个中断的处理函数,不用自己写了。这样加的好处是,我们不用去修改启动文件中的中断函数名,直接用裸机的启动文件就可以,有些历程中是将启动文件中对应的三个中断向量名给改了。
二选一,要么改启动文件,就不需要宏定义了,要么宏定义,就不需要改启动文件。我觉得宏定义更方便,所以选择宏定义。
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
还要删除包含的头文件#include "stm32f10x_lib.h"
,并将#define configUSE_TICK_HOOK 0
定义为0,默认为1的。
说明:链接文件也不需要动
通常标准库的例程下,都配有专门放中断处理函数的一个文件,即stm32f10x_it.c
,我们需要注释掉或者删掉上一步中所提到的三个中断处理函数,避免和FreeRTOS中的冲突,导致重定义。
或者直接删掉存放中断处理函数的源文件和头文件也行。
安装如下,两个插件,并配置c_cpp_properties.json
中的编译器路径。全部配置如下:
{
"configurations": [
{
"name": "arm_gcc",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE",
"STM32F10X_HD",
"USE_STDPERIPH_DRIVER"
],
"cStandard": "c99",
"cppStandard": "c++98",
"intelliSenseMode": "gcc-arm",
"compilerPath": "E:\\stm32_toolchain\\gcc-arm-none-eabi-10.3-2021.10\\bin\\arm-none-eabi-gcc.exe",
"configurationProvider": "ms-vscode.cmake-tools"
}
],
"version": 4
}
当然,你也可以直接用命令行完成,这样配置为VSCode的任务,是更加方便快捷,不一定都得配置。
这些工具使用的命令参数这些,大家就参考着根据自己的文件结构改一下,这里不多说工具的使用。
配置文件task.json
内容如下:
{
"version": "2.0.0",
"tasks": [
{
"label": "cmake",
"type": "shell",
"command":"cmake",
"args": [
"-B",
"build/",
"-G",
"Unix Makefiles",
"-DCMAKE_BUILD_TYPE=Debug"
],
"group": "build"
},
{
"label": "build",
"type": "shell",
"command":"make",
"args": [
"-j4",
"-C",
"build/"
],
"group": "build"
},
{
"label": "download",
"type": "shell",
"command":"openocd",
"args": [
"-f",
"interface/cmsis-dap.cfg",
"-f",
"target/stm32f1x.cfg",
"-c",
"program build/vscodeSTM32.elf verify reset exit"
],
"group": "build"
}
]
}
调试任务的文件是launch.json
,如下:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug With OpenOCD",
"cwd": "${workspaceRoot}",
"executable": "build/vscodeSTM32.elf",
"request": "launch",
"type": "cortex-debug",
"servertype": "openocd",
"configFiles": [
"interface/cmsis-dap.cfg",
"target/stm32f1x.cfg"
],
"searchDir": [],
"runToEntryPoint": "main",
"showDevDebugOutput": "none",
"svdFile": "./STM32F10x.svd"
}
]
}
如果没有配置第4步的,可以直接参考其内容中每个命令,用命令行工具构建。
以下使用配置的VSCode任务来快速构建。
在终端中选择运行生成任务,或者用你的快捷键。
到目前为止,编译链接成功,说明我们的工程和配置文件没有问题。
我打算用最常见最简单的两个功能来演示,点灯和串口打印。
#include "bsp_usart.h"
static void GPIO_LED_Conf(void);
void Task1_LED(void *param)
{
GPIO_LED_Conf();
const TickType_t xTickstoWait = pdMS_TO_TICKS(500);
while (1)
{
GPIO_WriteBit(GPIOE, GPIO_Pin_5, Bit_RESET);
vTaskDelay(xTickstoWait);
GPIO_WriteBit(GPIOE, GPIO_Pin_5, Bit_SET);
vTaskDelay(xTickstoWait);
}
}
void Task2_Print(void *param)
{
USART_Conf();
const TickType_t xTickstoWait = pdMS_TO_TICKS(1000);
while (1)
{
printf("Print Task is runing every 1 second...\n");
vTaskDelay(xTickstoWait);
}
}
xTaskCreate(Task1_LED, "Task1_LED", 100, NULL, 1, NULL);
xTaskCreate(Task2_Print, "Task2_Print", 100, NULL, 1, NULL);
static void GPIO_LED_Conf(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIO_InitStructure);
}
到此为止,FreeRTOS算是成功移植到了STM32F103上面了。收工!
GitHub仓库
视频教程