当前位置: 首页 > news >正文

以江协科技STM32入门教程的方式打开FreeRTOS——STM32C8T6如何移植FreeRTOS

本文介绍了FreeRTOS实时操作系统在STM32F103C8T6上的移植过程。相关文件建议从官网下载方便以后自己建立,当然也可以通过我的主页资源获取全套资源,或者在评论区留言,我会给你私发。

一、FreeRTOS 的基础作用

FreeRTOS 是一款轻量级的实时操作系统(RTOS),核心作用是帮助嵌入式系统实现多任务管理与实时调度,让多个任务能 “有序并发” 运行,解决传统 “大循环” 架构(单任务)的局限性。

举个例子:传统单任务系统中,如果你想同时实现 “按键检测”“LED 闪烁”“串口接收”,只能在一个死循环里轮流执行这三个功能,一旦某个功能(比如串口接收)耗时过长,其他功能就会卡顿。而有了 FreeRTOS,你可以把这三个功能拆分成三个 “任务”,RTOS 会像 “调度员” 一样,根据任务的优先级或时间片,合理分配 CPU 资源,让它们看起来像 “同时运行”,且能保证高优先级任务(比如紧急的串口数据处理)优先执行,这就是 “实时性” 的体现。

二、FreeRTOS 在 STM32F103C8T6 标准库移植的基本原理

移植的核心是让 FreeRTOS 能 “适配” STM32F103 的硬件环境,本质是解决三个问题:

  1. 任务上下文切换:当 RTOS 切换任务时,需要保存当前任务的 CPU 寄存器状态(比如 R0-R15、PSP 栈指针等),并恢复下一个任务的寄存器状态。这依赖于 ARM Cortex-M3 内核的特殊指令(如PendSV中断)和硬件机制。
  2. 系统时钟节拍(Tick):RTOS 需要一个周期性的 “心跳” 来触发任务调度(比如每 1ms 一次),通常用 STM32 的SysTick定时器实现,每次中断会更新系统时间并检查是否需要切换任务。
  3. 内存管理:FreeRTOS 创建任务、队列等对象时需要动态内存,移植时需适配 STM32 的 RAM(F103C8T6 有 64KB RAM),提供内存分配 / 释放的接口。

三、移植(针对 STM32F103C8T6 + 标准库)

准备模版

首先我们有一个江协科技的工程模版,然后我们要把里面的System中的Delay文件都删除掉(因为前面我们已经知道,FreeRTOS需要借助SysTick定时器实现,而江科大的Delay基于SysTick),之后我们的FreeRTOS相关文件都放在这个System文件夹,【标准库的delay_ms()是 “阻塞式空等”(会占用 CPU),改用 FreeRTOS 的vTaskDelay()(任务进入阻塞态,CPU 可执行其他任务)】

获取FreeRTOS

FreeRTOS的github官网

进入FreeRTOS-Kernel

FreeRTOS有多个版本这里以为我自己使用的10.4.3为例

下载ZIP并解压

移植源码

我们需要主目录下所有的.c文件,一共7个(摁住Ctrl逐个选中,然后复制到模版System文件夹)

把include文件夹也复制到System然后把这个readme格式的删掉

FreeRTOS 的源码中,portable文件夹包含了不同架构的适配代码,STM32F103 是 Cortex-M3 内核。我们自己在System文件建立一个portable文件夹,之后先把RVDS的ARM_CM3中的文件中的全复制过来。

内存与任务栈配置:选择堆大小heap_4.c,一般都用方案4,这种动态分配方式的。

把MemMang中的heap_4.c复制到我们的portable文件夹中。

接下来是重中之重的FreeRTOSConfig.h文件,这个文件需要我们自己搞,我这里提供一个我修改STM32Cubemx生成的HAL库用的FreeRTOSConfig.h的魔改版,对于不同型号的芯片需要进行不同的配置,这个是魔改版(所以可以忽略注释中的V10.3.1)

/* USER CODE BEGIN Header */
/** FreeRTOS Kernel V10.3.1* Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.** Permission is hereby granted, free of charge, to any person obtaining a copy of* this software and associated documentation files (the "Software"), to deal in* the Software without restriction, including without limitation the rights to* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of* the Software, and to permit persons to whom the Software is furnished to do so,* subject to the following conditions:** The above copyright notice and this permission notice shall be included in all* copies or substantial portions of the Software.** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.** http://www.FreeRTOS.org* http://aws.amazon.com/freertos** 1 tab == 4 spaces!*/
/* USER CODE END Header */#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H/*-----------------------------------------------------------* Application specific definitions.** These definitions should be adjusted for your particular hardware and* application requirements.** These parameters and more are described within the 'configuration' section of the* FreeRTOS API documentation available on the FreeRTOS.org web site.** See http://www.freertos.org/a00110.html*----------------------------------------------------------*//* USER CODE BEGIN Includes */
/* Section where include file can be added */
/* USER CODE END Includes *//* Ensure definitions are only used by the compiler, and not by the assembler. */
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)#include <stdint.h>extern uint32_t SystemCoreClock;
#endif
#ifndef CMSIS_device_header
#define CMSIS_device_header "stm32f1xx.h"
#endif /* CMSIS_device_header */#define configUSE_PREEMPTION                     1
#define configSUPPORT_STATIC_ALLOCATION          0
#define configSUPPORT_DYNAMIC_ALLOCATION         1
#define configUSE_IDLE_HOOK                      0
#define configUSE_TICK_HOOK                      0
#define configCPU_CLOCK_HZ                       ( SystemCoreClock )
#define configTICK_RATE_HZ                       ((TickType_t)1000)
#define configMAX_PRIORITIES                     ( 56 )
#define configMINIMAL_STACK_SIZE                 ((uint16_t)128)
#define configTOTAL_HEAP_SIZE                    ((size_t)8192)
#define configMAX_TASK_NAME_LEN                  ( 16 )
#define configUSE_TRACE_FACILITY                 1
#define configUSE_16_BIT_TICKS                   0
#define configUSE_MUTEXES                        1
#define configQUEUE_REGISTRY_SIZE                8
#define configUSE_RECURSIVE_MUTEXES              1
#define configUSE_COUNTING_SEMAPHORES            1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION  0/* Co-routine definitions. */
#define configUSE_CO_ROUTINES                    0
#define configMAX_CO_ROUTINE_PRIORITIES          ( 2 )/* Software timer definitions. */
#define configUSE_TIMERS                         1
#define configTIMER_TASK_PRIORITY                ( 2 )
#define configTIMER_QUEUE_LENGTH                 10
#define configTIMER_TASK_STACK_DEPTH             256/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet            1
#define INCLUDE_uxTaskPriorityGet           1
#define INCLUDE_vTaskDelete                 1
#define INCLUDE_vTaskCleanUpResources       0
#define INCLUDE_vTaskSuspend                1
#define INCLUDE_vTaskDelayUntil             1
#define INCLUDE_vTaskDelay                  1
#define INCLUDE_xTaskGetSchedulerState      1
#define INCLUDE_xTimerPendFunctionCall      1
#define INCLUDE_xQueueGetMutexHolder        1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_xTaskGetCurrentTaskHandle   1
#define INCLUDE_eTaskGetState               1/** The CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation used* by the application thus the correct define need to be enabled below*/
#define USE_FreeRTOS_HEAP_4/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */#define configPRIO_BITS         __NVIC_PRIO_BITS
#else#define configPRIO_BITS         4
#endif/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY   15/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5/* Interrupt priorities used by the kernel port layer itself.  These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY 		( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
/* USER CODE BEGIN 1 */
#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
/* USER CODE END 1 *//* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler    SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
/* IMPORTANT: After 10.3.1 update, Systick_Handler comes from NVIC (if SYS timebase = systick), otherwise from cmsis_os2.c */#define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 0/* USER CODE BEGIN Defines */
/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */
/* USER CODE END Defines */#endif /* FREERTOS_CONFIG_H */

以下是该FreeRTOSConfig.h主要设置项的精简对应(核心配置内容)【可以不看】:

  1. 中断优先级配置

    • 中断优先级位数:configPRIO_BITS = 4(对应 STM32 中断分组 4,抢占优先级 0~15)。
    • 内核中断(PendSV、SysTick)优先级:设为系统最低(逻辑值 15,映射为 NVIC 寄存器值 240)。
    • 允许调用 FreeRTOS API 的中断优先级上限:逻辑值 5(仅优先级 5~15 的中断可调用,0~4 禁止)。
  2. 任务与调度核心

    • 启用抢占式调度(configUSE_PREEMPTION = 1)。
    • 系统时钟:使用 STM32 实际主频(configCPU_CLOCK_HZ = SystemCoreClock)。
    • 系统节拍:1ms 一次(configTICK_RATE_HZ = 1000)。
    • 任务最大优先级:56 级(configMAX_PRIORITIES = 56)。
  3. 内存管理

    • 动态内存分配:启用(configSUPPORT_DYNAMIC_ALLOCATION = 1),禁用静态分配。
    • 堆大小:8KB(configTOTAL_HEAP_SIZE = 8192)。
    • 内存管理算法:使用heap_4.c(支持碎片整理)。
    • 最小任务栈:128 字(512 字节,configMINIMAL_STACK_SIZE = 128)。
  4. 功能开关

    • 启用软件定时器(configUSE_TIMERS = 1),定时器任务优先级 2,栈深度 256 字。
    • 启用常用 API:任务创建 / 删除、优先级调整、延时等(如INCLUDE_vTaskDelete = 1)。
    • 调试断言:出错时禁用中断并死循环(configASSERT配置)。
  5. 内核与硬件映射

    • 映射 FreeRTOS 内核中断到 STM32 标准中断名(如vPortSVCHandler对应SVC_Handler)。

     6.系统时钟配置与 SysTick 适配

  1. 时钟频率:STM32F103 通常配置为 72MHz(外部晶振 + PLL),需在FreeRTOSConfig.h中定义configCPU_CLOCK_HZ = 72000000,确保 RTOS 计算时间正确。
  2. SysTick 定时器:FreeRTOS 默认用 SysTick 作为时钟节拍源,需保证其中断频率正确(比如configTICK_RATE_HZ = 1000即 1ms 一次中断)。注意:标准库中若已初始化过 SysTick,需禁用(或由 RTOS 接管),避免冲突。
keil操作

把文件都加进来

把System里面的include和portable加入编译

之后我们编译一下,一定会报错

把stm32f10x-it.c里面这三个Handler函数的弱定义都注释掉即可

测试

运行我给的示例程序

一下为main.c(LED是我自己写的,中间的FreeRTOS.h和task.c是我们移植的)

#include "stm32f10x.h"                  // Device header
#include "FreeRTOS.h"       
#include "task.h"           
#include "LED.h"#define TASK1_PRIORITY    2       // 任务1优先级(数值越大优先级越高)
#define TASK2_PRIORITY    2       // 任务2优先级void vTask1(void *pvParameters);  // 任务1:示例任务(低优先级)
void vTask2(void *pvParameters);  // 任务2:示例任务(高优先级)void Hardware_Init(void)
{LED_Init();GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)1);GPIO_WriteBit(GPIOA,GPIO_Pin_1,(BitAction)1);
}int main(void)
{Hardware_Init();// 创建任务BaseType_t xReturn1, xReturn2;xReturn1 = xTaskCreate(vTask1, "Task1", 128, NULL, TASK1_PRIORITY, NULL);xReturn2 = xTaskCreate(vTask2, "Task2", 128, NULL, TASK2_PRIORITY, NULL);// 检查任务创建结果if (xReturn1 != pdPASS || xReturn2 != pdPASS)
{// 任务创建失败,可通过LED闪烁提示(需单独配置)while (1){GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)!GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_0));for(int i=0;i<1000000;i++); // 简单延时}
}// 启动FreeRTOS调度器(启动后任务开始运行)vTaskStartScheduler();// 若调度器启动成功,程序不会执行到这里// 若执行到这里,说明调度器启动失败(通常是内存不足)while (1);
}void vTask1(void *pvParameters)
{while (1){	GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)1);vTaskDelay(pdMS_TO_TICKS(1000));  // 延时1000ms(毫秒转FreeRTOS ticks)GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)0);vTaskDelay(pdMS_TO_TICKS(1000));  // 延时1000ms(毫秒转FreeRTOS ticks)}
}void vTask2(void *pvParameters)
{while (1){GPIO_WriteBit(GPIOA,GPIO_Pin_1,(BitAction)1);vTaskDelay(pdMS_TO_TICKS(1000));  // 延时500msGPIO_WriteBit(GPIOA,GPIO_Pin_1,(BitAction)0);vTaskDelay(pdMS_TO_TICKS(1000));  // 延时500ms}
}

LED.c

#include "LED.h"void LED_Init(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	GPIO_Init(GPIOA,&GPIO_InitStructure);
}

LED.h

#ifndef __LED_H__
#define __LED_H__#endif#include "stm32f10x.h"                  // Device headervoid LED_Init(void);

如果观察到那个LED能近乎同频闪烁则移植成功

总结

FreeRTOS 的核心是 “多任务实时调度”,移植到 STM32F103 的关键是让 RTOS 适配硬件的 “上下文切换”“时钟节拍” 和 “内存”,重点关注中断优先级、内存大小和配置文件的正确性。初学者可先从官方示例(或简化移植包)入手,逐步理解每个配置的作用,避免一开始陷入细节。这里面的很多东西是什么其实我也不知道

本文介绍了FreeRTOS实时操作系统在STM32F103C8T6上的移植过程。相关文件建议从官网下载方便以后自己建立,当然也可以通过我的主页资源获取全套资源,或者在评论区留言,我会给你私发。

http://www.dtcms.com/a/430988.html

相关文章:

  • 企业建设网站有哪些费用网站设计培训学院
  • ORB_SLAM2原理及代码解析:Frame::UnprojectStereo() 函数
  • SLAM算法分类对比
  • 碎片笔记|生成模型原理解读:AutoEncoder、GAN 与扩散模型图像生成机制
  • 中文粤语(广州)语音语料库:6219条高质量语音数据助力粤语语音识别与自然语言处理研究
  • Kubernetes HTTPS迁移:Ingress到GatewayAPI实战
  • [Power BI] 矩阵表
  • 陕西省建设厅网站劳保统筹基金网站建设合同需要注意什么
  • 【多线程】——基础篇
  • 多语言网站 自助洛阳兼职网站
  • 【C++实战(61)】C++ 并发编程实战:解锁线程池的奥秘与实现
  • 外贸网站做开关行业的哪个好做网站用什么配置笔记本
  • 极路由 极1s J1S hc5661 刷入OpenWRT并设置同网段子路由
  • 帮传销组织做网站wordpress换域名安装
  • ubuntu 24.04 从 6.8 内核升级 6.11 网卡加载失败问题
  • 如何让网站gzipwordpress 站长
  • SQL——子查询
  • dw做的网站怎么传到网络上去腾度网站建设
  • [创业之路-643]:互联网与移动互联网行业与通信行业的关系
  • Easyx使用(下篇)
  • css`font-variant-numeric: tabular-nums` 用来控制数字的样式。
  • CentOS7二进制安装包方式部署K8S集群之ETCD集群部署
  • Python常用三方模块——Pillow
  • 友情下载网站外贸cms建站
  • 976. 三角形的最大周长
  • 该怎么跟程序员谈做网站自己怎么免费做网站
  • 基于岗位需求的康体项目策划与设计实训室规划
  • 大理做网站哪家好大概多少钱
  • Nest 中使用Swagger自动化API文档生成
  • 融合:迈向 “一台计算机” 的终极架构