• STM32F10x SPL V3.6.2 集成 FreeRTOS v202112


    STM32F10x SPL 集成 FreeRTOS

    在整理 GCC Arm 工具链的Bluepill代码示例, 常用外设都差不多了, 接下来是 FreeRTOS, 网上查到的基本上都是基于旧版本的集成, STM32 SPL版本3.5.0, FreeRTOS版本9.x或者10.x, 不如自己用新版本集成一下. 顺便做个笔记.

    转载请标明出处: https://iosetting.blog.csdn.net/article/details/127099447

    软件版本

    STM32F10x_StdPeriph_Driver V3.6.2

    上一个版本V3.6.1发布于2012年, 因为HAL的存在, 都以为SPL不会再更新了, 但是没想到在时隔九年后, 2021年又发布了V3.6.2.

    下载地址 https://www.st.com/zh/embedded-software/stsw-stm32054.html 因为这个地址经常404, 可以使用这个备份下载地址

    FreeRTOSv202112.00

    这个版本也发布了好一阵了, 一直没见新的版本, LTS是202012.05, 比这个还早一年, 先用这个吧.

    GCC Arm 11.2-2022.02

    使用的 gcc-arm-11.2-2022.02-x86_64-arm-none-eabi, 次新的版本.

    集成的要点

    前提

    已经有可以使用 GCC Arm 工具链编译的基于 SPL V3.6.2 的项目模板

    需要复制的文件

    https://www.freertos.org/下载 FreeRTOS 202112.00 , 文件比较大, 但是实际上需要的文件很少. 解开后到 FreeRTOS/Source 目录下, 复制以下的文件到项目目录下

    • FreeRTOS/Source/include 整个目录, 这些是头文件
    • FreeRTOS/Source 下的所有C文件
    • FreeRTOS/Source/portable/GCC/ARM_CM3 目录, 这是针对 STM32F103 的适配文件
    • FreeRTOS/Source/portable/MemMang 目录, 里面包含一些现成的内存管理实现

    放到项目下, 目录结构是这样的

    FreeRTOS
    ├── include
    │   ├── atomic.h
    │   ├── croutine.h
    │   ├── deprecated_definitions.h
    │   ├── event_groups.h
    │   ├── FreeRTOS.h
    │   ├── list.h
    │   ├── message_buffer.h
    │   ├── mpu_prototypes.h
    │   ├── mpu_wrappers.h
    │   ├── portable.h
    │   ├── projdefs.h
    │   ├── queue.h
    │   ├── semphr.h
    │   ├── stack_macros.h
    │   ├── StackMacros.h
    │   ├── stdint.readme
    │   ├── stream_buffer.h
    │   ├── task.h
    │   └── timers.h
    ├── portable
    │   ├── GCC
    │   │   └── ARM_CM3
    │   │       ├── port.c
    │   │       └── portmacro.h
    │   └── MemMang
    │       ├── heap_1.c
    │       ├── heap_2.c
    │       ├── heap_3.c
    │       ├── heap_4.c
    │       └── heap_5.c
    ├── croutine.c
    ├── event_groups.c
    ├── list.c
    ├── queue.c
    ├── stream_buffer.c
    ├── tasks.c
    └── timers.c
    

    需要准备的文件: FreeRTOSConfig.h

    可以直接使用 FreeRTOS/Demo/CORTEX_STM32F103_Keil/ 这个例子的 FreeRTOSConfig.h, 如果要避免编译中的warning, 需要加一行

    #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 0
    

    里面几个可调节的项

    • configMINIMAL_STACK_SIZE 最小栈尺寸, 默认为128, 需要占用的内存为 128 * 4 = 512 bytes
    • configTOTAL_HEAP_SIZE 声明的堆尺寸, 默认的( ( size_t ) ( 17 * 1024 ) )会恰好将STM32F103C8的20K内存用完

    需要修改的代码: 中断处理

    选项一: 替换 startup 中的中断处理函数

    如果项目固定启用 FreeRTOS, 则直接在 startup 代码中修改, 对于代码中的函数名直接替换

    • SVC_Handler -> vPortSVCHandler
    • PendSV_Handler -> xPortPendSVHandler
    • SysTick_Handler -> xPortSysTickHandler

    选项二: 使用宏定义编译时替换

    这个方式便于切换 FreeRTOS 和 Non-FreeRTOS 模式, 在 FreeRTOSConfig.h 中, 最后一个#endif之前添加以下代码就可以了

    /* Use MACRO to replace the handlers without changing startup file */
    #define vPortSVCHandler     SVC_Handler
    #define xPortPendSVHandler  PendSV_Handler
    #define xPortSysTickHandler SysTick_Handler
    

    测试代码

    以上步骤就已经完成了 FreeRTOS 的集成, 可以使用以下代码检测结果. 对于 Bluepill 板载 LED PC13 的亮灯测试.

    需要注意的是, 如果使用了 FreeRTOS, 就不要再调用 SysTick_Config() 方法, 会和 FreeRTOS 冲突.

    #include 
    #include 
    #include 
    #include "FreeRTOS.h"
    #include "task.h"
    #include "queue.h"
    
    void vTaskFunction(void *pvParameters)
    {
        (void)(pvParameters);   // Suppress "unused parameter" warning
    
        while (1)
        {
            GPIO_ResetBits(GPIOC, GPIO_Pin_13);
            vTaskDelay(500);
            GPIO_SetBits(GPIOC, GPIO_Pin_13);
            vTaskDelay(500);
        }
    }
    
    void LED_Config(void)
    {
        // GPIO structure for port initialization
        GPIO_InitTypeDef GPIO_InitStructure;
        // enable clock on APB2
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
        /* configure port PC13 for driving an LED
         * Use GPIO_Pin_All if you want to drive the whole port
         */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  // output push-pull mode
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // highest speed
        GPIO_Init(GPIOC, &GPIO_InitStructure);            // initialize port
    }
    
    int main(void)
    {
        BaseType_t xReturned;
    
        /*
         * Don't use Delay_Init(), which conflict with FreeRTOS tick handling
         */
    
        LED_Config();
    
        xReturned = xTaskCreate(
            vTaskFunction,              // Task function point
            "TaskLED",                  // Task name
            configMINIMAL_STACK_SIZE,   // Use the minimum stack size, each take 4 bytes(32bit)
            NULL,                       // Parameters
            2,                          // Priority
            NULL);                      // Task handler
    
        if (xReturned != pdPASS)
        {
            while (1);
        }
    
        /* Start the scheduler. */
        vTaskStartScheduler();
    
        /* Will only get here if there was not enough heap space to create the idle task. */
        return 0;
    }
    

    参考

  • 相关阅读:
    熊市链游模型如何设计开发?
    Pytorch总结二之线性回归算法原理与实现
    【C++】C++中那些有点意思,但一般也用不到的替代运算符
    JAVA提取嵌套夹带文件之Apache Tika
    海外商城小程序开发方案
    (附源码)php校园寝室分配查询系统 毕业设计 032027
    中国电信天翼云进入4.0阶段,打造一朵无处不在的分布式云
    元学习:如何使模型快速适应新任务
    C#对字典容器Dictionary<TKey, TValue>内容进行XML序列化或反序列化报错解决方法
    2023年度中国开源研究报告
  • 原文地址:https://blog.csdn.net/michaelchain/article/details/127099447