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://www.cnblogs.com/milton/p/16740075.html
软件版本STM32F10x_StdPeriph_Driver V3.6.2上一个版本V3.6.1发布于2012年, 因为HAL的存在, 都以为SPL不会再更新了, 但是没想到在时隔九年后, 2021年又发布了V3.6.2.
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 vPortSVCHandlerSVC_Handler#define xPortPendSVHandlerPendSV_Handler#define xPortSysTickHandler SysTick_Handler测试代码以上步骤就已经完成了 FreeRTOS 的集成, 可以使用以下代码检测结果. 对于 Bluepill 板载 LED PC13 的亮灯测试.
需要注意的是, 如果使用了 FreeRTOS, 就不要再调用 SysTick_Config() 方法, 会和 FreeRTOS 冲突.
#include <stm32f10x.h>#include <stm32f10x_gpio.h>#include <stm32f10x_rcc.h>#include "FreeRTOS.h"#include "task.h"#include "queue.h"void vTaskFunction(void *pvParameters){(void)(pvParameters);// Suppress "unused parameter" warningwhile (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 initializationGPIO_InitTypeDef GPIO_InitStructure;// enable clock on APB2RCC_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 modeGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // highest speedGPIO_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 nameconfigMINIMAL_STACK_SIZE,// Use the minimum stack size, each take 4 bytes(32bit)NULL,// Parameters2,// PriorityNULL);// Task handlerif (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;}

推荐阅读