使用Clion开发STM32——移植FreeRTOS

FreeRTOS版本:202212.01
STM32型号:STM32H743VIT6
使用工具:Clion

其实在STM32cubeMX中就可以直接配置FreeRTOS,rtthread等操作系统,而且使用接口封装过的,很方便。
但我还是想手动一直一遍,肯定有不一样的收获。

1.下载FreeRTOS源码

FreeRTOS官网https://www.freertos.org/
源码如下
在这里插入图片描述

FreeRTOS文件夹

FreeRTOS是内核源码还有一些Demo
在这里插入图片描述

FreeRTOS-Plus文件夹

FreeRTOS-Plus是一个包含扩展功能的文件夹
在这里插入图片描述
它提供了一些额外的组件和库,这些组件和库并非FreeRTOS内核的一部分,但可以增强系统的功能或提供额外的支持。具体内容包括但不限于:

FreeRTOS-Plus-CLI:一个命令行接口库,允许用户通过串口或其他通信接口与系统进行交互,执行命令和获取信息。
FreeRTOS-Plus-TCP:一个TCP/IP协议栈,为嵌入式系统提供网络通信能力,支持标准的网络协议如TCP、UDP、ICMP等。
FreeRTOS-Plus-FAT:一个文件系统库,支持FAT文件系统,使得嵌入式设备能够读写标准的FAT格式的存储介质,如SD卡或USB闪存驱动器。
FreeRTOS-Plus-IO:一个输入输出库,提供了一套统一的接口来管理不同硬件平台的输入输出设备,简化了设备驱动程序的开发。
FreeRTOS-Plus-Trace:一个跟踪和调试工具,帮助开发者监控和分析系统的运行状态,特别是任务调度和资源使用情况。
【参考文章:二、FreeRTOS目录结构与配置选项讲解

tools文件夹

tools文件夹是一些工具脚本

所以我们移植FreeRTOS与学习它的内核的话,只看FreeRTOS这个文件夹即可。

2.FreeRTOS源码文件

Demo文件夹

FreeRTOS/Demo文件夹中,包含各种演示应用程序,展示了如何在不同的硬件平台上使用 FreeRTOS。每个子文件夹对应一个特定的硬件平台或开发板
在这里插入图片描述
移植时要参考和你的芯片相同内核或者类似的Demo,用得到其中的配置文件FreeRTOSConfig.h。

比如我的芯片类型是STM32H743,是cortex M7内核的,但是Demo中并没有STM32H743的例程,那我就找同样cortex M7内核的例程,发现有个CORTEX_M7_STM32F7_STM32756G-EVAL_IAR_Keil,那就它了。
在这里插入图片描述

Source文件夹

FreeRTOS/Source是 FreeRTOS 内核源码。
include是头文件
portable 是移植文件:包含与具体硬件平台相关的移植代码。

内核主要文件包括:
tasks.c:任务管理。
queue.c:队列管理。
list.c:链表管理。
timers.c:软件定时器管理。
event_groups.c:事件组管理。
croutine.c:协程(几乎不用)
stream_buffer.c:缓冲区
在这里插入图片描述

Portable 文件夹

包含与具体硬件平台相关的移植代码。FreeRTOS 支持多种不同的处理器架构和编译器,因此需要针对不同的平台进行移植。
主要子文件夹包括:
MemMang:内存管理相关代码。

GCC:GNU 编译器集合相关的移植代码。
RVDS:ARM RealView 编译工具链相关的移植代码。
IAR:IAR 编译器相关的移植代码。

因为Clion是使用GCC来编译,所以只关注GCC这个文件夹,如下:
在这里插入图片描述

ARM_CM7文件内容如下:
在这里插入图片描述

遇见readMe就读一读,肯定没有坏处。

机翻一下:

在ARM Cortex-M7微控制器上运行FreeRTOS有两种选择。最佳选择取决于所使用的ARM Cortex-M7内核的版本。这个revision由一个’r’数字和一个’p’数字指定,所以看起来会有些不同比如“r0p1”。检查正在使用的微控制器的文档,以找到该微控制器中使用的Cortex-M7内核的修订版。如有疑问,请使用FreeRTOS端口是专门为r0p1版本提供的,因为它可以使用所有核心修订。

第一种选择是使用ARM Cortex-M4F端口,第二种选择是使用Cortex-M7 r0p1端口,后者包含一个小的勘误解决方法。

如果ARM Cortex-M7内核的版本不是r0p1,则可以选择已使用,但建议使用FreeRTOS ARM Cortex-M4F接口
/FreeRTOS/Source/portable/GCC/ARM_CM4F目录。

如果ARM Cortex-M7内核的版本为r0p1,则使用FreeRTOS ARM Cortex-M7 r0p1接口位于
/FreeRTOS/Source/portable/GCC/ARM_CM7/r0p1中目录。

就是说r0p1是内核版本,好像这个内核版本有个小bug?如果内核版本是r0p1就使用CM7接口,不是r0p1版本就使用CM4F接口。

老实讲,我并没有找到STM32H743的内核版本是啥。(如有大佬知道请求告知或指点)

算了,先移植一个试试。就CM7的吧

3.拷贝FreeRTOS必要文件到工程

首先有一个可正常运行的裸机工程,比如点灯工程。

在此基础上进行移植。

工程目录下新建文件夹(自己任意起名字)
我建的是
My_Middlewares/FreeRTOS。
(如果使用cubeMX配置其他中间件的话,会自动生成一个文件夹Middlewares,为了与它避免因为名字冲突所带来的麻烦,所以我建的是My_Middlewares)

文件结构如下:
在这里插入图片描述
inc是头文件,就是FreeRTOS源码中include文件夹中的内容,还有把Demo中的FreeRTOSConfig.h文件也拷贝过来。

src是源文件

port是接口文件

MemMang是内存管理文件

4.修改CMakelists_temaplate

修改cmakelists的模版文件,不要直接修改cmakelists文件,因为每次生成代码都会重新覆盖这个文件。所以修改CMakelists_temaplate

增加头文件路径
在这里插入图片描述

增加编译文件
在这里插入图片描述

将21到23取消注释,即开启硬件浮点单元FPU
在这里插入图片描述
然后更新cmakelists

5.修改FreeRTOSConfig.h

这个文件毕竟是从人家那拷贝过来的,手动修改一下

大家的每个FreeRTOSConfig.h可能都不一样,修改也可能不一样。

这里仅以我拷贝的这个文件进行说明

这里是#ifndef IAR_SYSTEMS_ASM,反正我不是使用IAR,那这个就不删了。

将#include "stm32F7xx_hal.h"修改为#include “stm32h7xx_hal.h”

将configASSERT注释掉,没注释掉一直报错。

或者可以自己加一个断言
比如这样(前提是串口可以正常使用):
#define vAssertCalled(char,int) printf(“Error:%s,%d\r\n”,char,int)
#define configASSERT(x) if((x)==0) vAssertCalled(FILE,LINE)
我这里先不加了直接注释掉了。
在这里插入图片描述
将一些钩子函数hook都置为0
在这里插入图片描述
configCPU_CLOCK_HZ默认为系统时钟
configTICK_RATE_HZ滴答频率默认1ms
这个不用修改

6.修改stm32h7xx_it.c

在stm32中,基础时钟默认使用的是Systick定时器,用于滴答计数,就是用于HAL_Delay这些。
但是在FreeRTOS中,因为所有的 Cortex M内核的单片机都有Systick定时器,所以FreeRTOS使用的是Systick产生滴答信号。
在这里插入图片描述
在FreeRTOSConfig.h中使用宏定义了这几个函数,与我们在stm32h7xx_it.c中的函数冲突,所以将stm32h7xx_it.c中将这三个修改为弱定义
在这里插入图片描述

7.验证

/*************************************FreeRTOS includes*************************************/
#include "FreeRTOS.h"
#include "task.h"

static TaskHandle_t xHandleTaskLED1 = NULL;
static TaskHandle_t xHandleTaskuart1 = NULL;

static void vTaskLED1(void *pvParameters);
static void vTaskUART1(void *pvParameters);

void vTaskLED1(void *pvParameters)
{
    while(1)
    {
        bsp_LedToggle();
        vTaskDelay(100);
    }
}
void vTaskUART1(void *pvParameters)
{
    while(1)
    {
        printf("vTaskUART1: Hello World!\r\n");
        vTaskDelay(500);
    }
}
void AppTaskCreate (void) {
    xTaskCreate(vTaskLED1,    /* 任务函数  */
                "vTaskLED1",        /* 任务名    */
                100,                /* 任务栈大小,单位word,也就是4字节 */
                NULL,                /* 任务参数  */
                1,                    /* 任务优先级*/
                &xHandleTaskLED1);  /* 任务句柄  */

    xTaskCreate(vTaskUART1,    /* 任务函数  */
                "vTaskUART1",        /* 任务名    */
                100,                /* 任务栈大小,单位word,也就是4字节 */
                NULL,                /* 任务参数  */
                1,                    /* 任务优先级*/
                &xHandleTaskuart1);  /* 任务句柄  */
}

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MPU Configuration--------------------------------------------------------*/
  MPU_Config();

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /******** 省略********/


  /*创建任务*/
  AppTaskCreate();
  /* 启动调度,开始执行任务 */
  vTaskStartScheduler();

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

在这里插入图片描述
同时led灯也在闪烁

OK!移植完成

8.修改时钟源

为了避免HAL的基础时钟和FreeRTOS的时钟冲突,可以选用其他定时器作为HAL的基础时钟,比如基本定时器TIM6
时钟这一块的内容向大佬学习的【11.2】FreeRTOS源码精讲② HAL和FreeRTOS基础时钟——Kevin带你读《STM32Cube高效开发教程高级篇》
在这里插入图片描述

  • 21
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值