STM32F103C8T6移植FreeRTOS(标准库版)
前言本次基于标准库方式介绍一下STM32移植FreeRTOS的方法步骤本次移植的FreeRTOS版本是FreeRTOSv202212.01。本次实验需要的硬件1STM32F103C8T6最小系统板2STLink下载器注当然STM32板子不一定必须是最小系统板因为最终仅使用LED测试现象因此只要方便测试即可。一、基于标准库的FreeRTOS移植1、准备STM32标准库工程模板我这里是直接使用了江协科技STM32教程的STM32工程模板大家可以自己搭建或者使用其他标准库工程模板均可并不影响使用。2、空目录准备在工程根目录下新建文件夹FreeRTOS进入FreeRTOS目录同级目录下继续新建include、portable、source文件夹。3、获取FreeRTOS源码直接浏览器搜索freertos即可进入FreeRTOS官网。下图就是FreeRTOS官网主页进入后会自动变成中文模式对中国访问比较友好。单击【查看文档】进入文档页面后往下翻看见【下载FreeRTOS】点击进入。然后点击【各个库存储库的链接】进入后继续点击【FreeRTOS GitHub组织】进入后继续点击【FreeRTOS】仓库中。进入FreeRTOS仓库后看向右边栏有一项是【Releases】点击进入。这里列出了除了LTS版本的其他FreeRTOS版本我们使用 FreeRTOSv202212.01 版本。所以点击跳转到该位置。接着如下图所示单击zip文件即可下载FreeRTOSv202212.01 版本的完整源码。下载好后在本地目录下解压缩即可然后进入源码文件夹如下图所示。4、移植FreeRTOS文件进入FreeRTOS源码文件夹后继续进入FreeRTOS/Source/include目录然后复制里面全部的头文件。4.1 补充FreeRTOS/include内容接着粘贴到模板工程中的include文件夹中。4.2 补充FreeRTOS/portable内容接着进入FreeRTOSv202212.01\FreeRTOS\Source\portable\RVDS\ARM_CM3目录下复制里面的两个文件。并粘贴到自己工程目录中的FreeRTOS/portable文件夹中。然后进入FreeRTOSv202212.01\FreeRTOS\Source\portable\MemMang目录下复制【heap_4.c】文件也是粘贴到自己工程的FreeRTOS/portable文件夹中。4.3 补充FreeRTOS/source内容接着进入FreeRTOS源码文件夹的 FreeRTOSv202212.01\FreeRTOS\Source 目录中复制下图文件并粘贴到自己工程的FreeRTOS/source目录下。4.4 补充FreeRTOS目录的内容接着进入FreeRTOSv202212.01\FreeRTOS\Demo\CORTEX_STM32F103_Keil文件夹中复制【FreeRTOSConfig.h】文件并粘贴到自己工程的FreeRTOS文件夹下即可。4.5 将移植文件添加到keil工程目录在keil中打开自己的工程将刚才增加的文件全部添加至keil工程目录中如下图所示。接着进入【魔法棒】包含头文件路径。到这里FreeRTOS移植需要的文件就移植完成了。5、适配FreeRTOSFreeRTOS移植到工程中后并非马上就可以直接使用还需要给STM32程序与FreeRTOS在一些函数上做一下适配。5.1 注释掉SVC_Handler和PendSV_Handler首先打开STM32的中断文件如下图所示。接着找到void SVC_Handler(void)并注释掉。继续找到void PendSV_Handler(void)也注释掉。这两个注释掉的原因是FreeRTOS中使用了这两个中断函数这里若继续定义则会报错重复定义。接着进入FreeRTOSConfg.h文件中。新增几个宏定义。这里宏定义分为两部分。第一部分是对于函数名称的宏替换因为·FreeRTOS定义过PendSV_Handler和SVC_Handler两个中断函数但是使用的名称不一样FreeRTOS有自己的一套命名规范。所以为了保持STM32中这俩函数的命名与FreeRTOS统一所以在FreeRTOSConfig.h中补充两个宏使用FreeRTOS的函数命名替换一下STM32中的函数名即可。第二部分是功能的开启。FreeRTOSConfig.h文件又称为FreeRTOS的裁剪文件。所谓的“裁剪”实际上就是对于其功能的裁剪。用户可以通过在该文件中设置宏来开启和关闭FreeRTOS的各种功能实现需要就开、不需要不开的目的节省CPU的空间。因此第二部分这个宏定义是用于开启一个调度器功能后续进行任务创建等都需要使用到调度器所以这里先开启。5.2 补充SysTick_Handler函数体接着继续回到stm32的中断处理文件找到SysTick_Handler函数然后在函数体中添加下面代码。if (xTaskGetSchedulerState() ! taskSCHEDULER_NOT_STARTED) { xPortSysTickHandler(); }接着在文件顶部添加需要调用的头文件以及一个外部函数声明。#include FreeRTOS.h #include task.h extern void xPortSysTickHandler(void);这样添加的内容就不会报错了。5.3 将SysTick_Handler函数放到main.c中最后我习惯将SysTick_Handler函数直接放到main.c中所以将上一步添加的头文件和外部函数声明以及SysTick_Handler整体都移到main.c中如下图所示。注这一步是笔者个人习惯大家可选哈。最后编译一下工程。可以看见编译可以通过没有问题基本说明我们FreeRTOS移植成功了。6、测试效果最后我们使用一个简单的点灯程序测试一下移植效果。直接在main函数中编写下面代码即可测试。#include stm32f10x.h // Device header // 添加FreeRTOS必要的头文件 #include FreeRTOS.h #include task.h extern void xPortSysTickHandler(void); TaskHandle_t task1_Handler; void task1(void *pvParameters); int main(void) { GPIO_InitTypeDef gpio_init_struct {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); gpio_init_struct.GPIO_Pin GPIO_Pin_13; gpio_init_struct.GPIO_Mode GPIO_Mode_Out_PP; gpio_init_struct.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOC, gpio_init_struct); GPIO_SetBits(GPIOC, GPIO_Pin_13); xTaskCreate((TaskFunction_t)task1, (char *)task1, (configSTACK_DEPTH_TYPE)128, (void *)NULL, (UBaseType_t)2, (TaskHandle_t *)task1_Handler); vTaskStartScheduler(); while (1) { } } void task1(void *pvParameters) { while(1) { GPIO_ResetBits(GPIOC, GPIO_Pin_13); vTaskDelay(500); GPIO_SetBits(GPIOC, GPIO_Pin_13); vTaskDelay(500); } } /** * brief This function handles SysTick Handler. * param None * retval None */ void SysTick_Handler(void) { if (xTaskGetSchedulerState() ! taskSCHEDULER_NOT_STARTED) { xPortSysTickHandler(); } }编译一下没有问题。最后烧录到单片机中此时你的STM32最小系统板上的板载LED将会以500ms的周期进行闪烁说明本次FreeRTOS的移植成功了恭喜你