• FreeRTOS移植:STM32L476 nucleo-L476RG 开发板《02》


    系列文章

    说明

    • 上一篇 FreeRTOS移植:STM32L476 nucleo-L476RG 开发板《01》 主要讲了一下如何快速搭建一个 STM32 裸机工程,其实 STM32CubeMX 可以生成 FreeRTOS 的工程,这就没有了 FreeRTOS 的移植文章

    • 本篇继续讲一下 【手动】移植 FreeRTOS 的步骤,移植完成后,继续研究 FreeRTOS 的使用

    环境

    • Win10 64位:当前 Windows 主流操作系统

    • Keil MDK 5.36,IDE,方便开发与调试

    • STM32CubeMX 6.11.1 本篇不再使用

    获取与下载 FreeRTOS

    (1)直接在 FreeRTOS 官方下载 发布的版本,压缩包,解压后使用

    • FreeRTOS 官方的网址 https://www.freertos.org/

    • 点击下载 FreeRTOS,发布版本可能没有那么新,比如当前最新版本 FreeRTOS 202212.01,但是下载的压缩包比较小,容易下载

    在这里插入图片描述

    在这里插入图片描述

    (2)在 github 使用 Git 工具下载源码

    • FreeRTOS 主仓库 https://github.com/FreeRTOS/FreeRTOS.git

    • FreeRTOS 内核仓库 https://github.com/FreeRTOS/FreeRTOS-Kernel.git

    • 由于 FreeRTOS 内核仓库仅仅为内核代码文件,没有 Demo,因此建议直接下载 FreeRTOS 主仓库,使用 Git 命令如下

    git clone https://github.com/FreeRTOS/FreeRTOS.git --recurse-submodules

    • 同时把 FreeRTOS 各个 Git 子仓库一起克隆到本地

    (3)在 github 直接下载 Release 版本

    • 可以直接在 github 点击下载 Release 发布版本,无须使用 Git 工具

    在这里插入图片描述

    在这里插入图片描述

    • 【备注】Github 仓库的 Release 版本地址可能会不时更新,因此建议自己打开进入网址后,下载自己想要的版本,如最新的软件版本

    FreeRTOS 工程目录管理

    • 直接下载下来的 FreeRTOS,需要整理一下,这样方便工程的管理,有些不需要的 Demo,无须加入工程

    • 当前平台:STM32L476,可以参考 FreeRTOS 中的一些 Demo,找到相似 CPU,这样 CPU 部分就不需要额外移植了

    • 当前 FreeRTOS 没有 STM32L476 Keil MDK5 的 Demo,因此手动搭建 FreeRTOS 工程即可,使用上次生成的 STM32L476 裸机工程

    在这里插入图片描述

    在这里插入图片描述

    • 进入 STM32L476 裸机工程(STM32CubeMX 生成)

    在这里插入图片描述
    在这里插入图片描述

    Keil MDK5 添加分组

    • 打开 Keil MDK5,开始工程文件的管理(分类、添加)

    在这里插入图片描述

    • 可以在 Keil MDK5 中创建 FreeRTOS/KernelFreeRTOS/cpu 的分组(Group)

    在这里插入图片描述

    • cpu port 部分可以暂时选择 FreeRTOS\Source\portable\RVDS\ARM_CM4F

    在这里插入图片描述

    初步编译

    • 报编译错误,找不到 "FreeRTOS.h"
    compiling croutine.c...
    ..\FreeRTOS\Source\croutine.c(29): error:  #5: cannot open source input file "FreeRTOS.h": No such file or directory
      #include "FreeRTOS.h"
    ..\FreeRTOS\Source\croutine.c: 0 warnings, 1 error
    
    ... ...
    
    

    Keil MDK5 设置 头文件路径

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    再次编译:

    • 添加 FreeRTOS 头文件路径后,再次编译,提示找不到 "FreeRTOSConfig.h" 头文件,这个头文件属于工程配置文件,可以在 FreeRTOS Demo 中找到一个类似的,然后进行配置与修改

    在这里插入图片描述

    compiling croutine.c...
    ..\FreeRTOS\Source\include\FreeRTOS.h(58): error:  #5: cannot open source input file "FreeRTOSConfig.h": No such file or directory
      #include "FreeRTOSConfig.h"
    ... ...
    
    
    • 可以使用 FreeRTOS 的 FreeRTOSConfig.h 模板文件,

    在这里插入图片描述

    • 或者从其他的 相似平台 Demo 中复制一份出来,比如 Cortex-M4 平台的

    FreeRTOS\Demo\CORTEX_M4F_STM32F407ZG-SK\FreeRTOSConfig.h

    • FreeRTOSConfig.h 放在工程根目录下即可,无须放在 FreeRTOS 目录,因为这个是工程本身的专有的配置文件

    在这里插入图片描述

    继续编译

    • 此时编译报错比较少了,可以针对性的开始移植与适配了

    • 此时编译,报错 "SystemCoreClock" is undefined

    ..\FreeRTOS\Source\portable\RVDS\ARM_CM4F\port.c(813): error:  #20: identifier "SystemCoreClock" is undefined
              portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
    ..\FreeRTOS\Source\portable\RVDS\ARM_CM4F\port.c: 0 warnings, 1 error
    "stm32l475_freertos\stm32l475_freertos.axf" - 1 Error(s), 0 Warning(s).
    
    • 此时可以先不着急解决这个编译问题,我们只是把 FreeRTOS 相关的文件(可能目前还缺少内存管理部分)放进工程,并没有创建 FreeRTOS 的例程,也就是还没有使用 FreeRTOS,平台相关的编译,需要使用时一并修改

    FreeRTOS 例程

    • 在 main 函数添加 FreeRTOS 的使用例程,比如创建一个 task
    #include "main.h"
    
    #include "FreeRTOS.h"
    #include "task.h"
    
    UART_HandleTypeDef huart2;
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    static void MX_USART2_UART_Init(void);
    
    #define TASK_TEST_PRIORITY      (tskIDLE_PRIORITY + 6)
    #define TASK_TEST2_PRIORITY     (tskIDLE_PRIORITY + 8)
    
    static void task_test_entry(void *pvParameters)
    {
        while (1)
        {
            vTaskDelay(1000);
        }
    }
    
    static void task_test2_entry(void *pvParameters)
    {
        while (1)
        {
            vTaskDelay(2000);
        }
    }
    
    int main(void)
    {
        HAL_Init();
        SystemClock_Config();
        MX_GPIO_Init();
        MX_USART2_UART_Init();
    
        xTaskCreate(task_test_entry, "task_test", 512, NULL, TASK_TEST_PRIORITY, NULL);
        xTaskCreate(task_test2_entry, "task_test2", 512, NULL, TASK_TEST2_PRIORITY, NULL);
        vTaskStartScheduler();
    
        while (1)
        {
            HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
            HAL_Delay(500);
            HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
            HAL_Delay(500);
        }
    }
    
    • 这里整理了一下 main.c,创建两个 task,task中只有循环,可以通过调试确认 task 是否正常切换,比如在每个 task 中增加断点

    继续编译,确认移植与适配问题

    • 解决 SystemCoreClock 找不到的编译报错,这里有个 编译器的判断,或者改为 Keil MDK5 编译器的,armcc 或者 armclang 等,建议去掉即可,因为这个配置文件来自其他的编译器

    • 【备注】 FreeRTOSConfig.h 文件为工程配置文件,可以根据当前的平台随时修改(适配)

    在这里插入图片描述
    在这里插入图片描述

    • 中断重定义问题,由于 FreeRTOS 接管了 STM32 的部分中断,用于 RTOS 的任务调度。
    stm32l475_freertos\stm32l475_freertos.axf: Error: L6200E: Symbol SVC_Handler multiply defined (by port.o and stm32l4xx_it.o).
    stm32l475_freertos\stm32l475_freertos.axf: Error: L6200E: Symbol PendSV_Handler multiply defined (by port.o and stm32l4xx_it.o).
    stm32l475_freertos\stm32l475_freertos.axf: Error: L6200E: Symbol SysTick_Handler multiply defined (by port.o and stm32l4xx_it.o).
    
    • 因此把 stm32l4xx_it.c 中的自动生成的中断函数【注释掉】

    在这里插入图片描述

    FreeRTOS 继续适配

    • 继续编译,发现 FreeRTOS 需要实现几个 适配的函数
    stm32l475_freertos\stm32l475_freertos.axf: Error: L6218E: Undefined symbol pvPortMalloc (referred from event_groups.o).
    stm32l475_freertos\stm32l475_freertos.axf: Error: L6218E: Undefined symbol vPortFree (referred from event_groups.o).
    stm32l475_freertos\stm32l475_freertos.axf: Error: L6218E: Undefined symbol vApplicationIdleHook (referred from tasks.o).
    stm32l475_freertos\stm32l475_freertos.axf: Error: L6218E: Undefined symbol vApplicationStackOverflowHook (referred from tasks.o).
    stm32l475_freertos\stm32l475_freertos.axf: Error: L6218E: Undefined symbol vApplicationTickHook (referred from tasks.o).
    

    在这里插入图片描述

    • 这个适配问题在下一篇继续讲解

    小结

    • FreeRTOS 在 STM32L476 平台(Cortex-M4)上适配其实很容易,当然也需要一些细节的处理

    • 本篇主要搭建 FreeRTOS 的工程,几个编译问题的【修改】

    • 下一篇继续讲解 FreeRTOS 的适配,让FreeRTOS 在 STM32L476 平台上运行起来

  • 相关阅读:
    解读下SWD协议以及其应用
    【微电网优化】粒子群优化算法的微电网调度(光伏、储能、电动车、电网交互)【含Matlab源码 2190期】
    如何实现Spring的事务管理功能:@Transactional声明式事务
    Spire.OCR for .NET 1.9.0 Crack
    探索Semantic Plugins:开启大模型的技能之门
    处理器知识基础
    AntDB-M高性能设计之hash索引动态rehash
    面试官:volatile如何保证可见性的,具体如何实现?
    儿童台灯哪个品牌更护眼推荐?2022年最新护眼台灯十大品牌排行榜
    组合数学(下):概率、博弈
  • 原文地址:https://blog.csdn.net/tcjy1000/article/details/139697431