STM32学习日志_FreeRTOS_day1

参考:

02-STM32CubeIDE创建FreeRTOS工程_哔哩哔哩_bilibili

大D老师

概述

FreeRTOS (Free Real-Time Operating System)** 是一个开源的、小型的、专为微控制器设计的实时操作系统内核。它在资源受限的嵌入式系统中扮演着核心角色,提供任务调度、通信、同步和定时器等关键服务。

层级架构:

从上至下,由表及里:

  • 应用:使用FreeRTOS实现具体逻辑:
  • Task层:通过FreeRTOS创建任务:
  • 系统初始化层:初始化系统时钟,外设,硬件,FreeRTOS内核等
  • FreeRTOS内核层:调度和管理任务的核心层,负责任务调度、通信、同步和定时器等;
  • 硬件抽象层(HAL):最内层,直接操作硬件;
  • 硬件层:STM32芯片

核心定位

  • 实时性:核心目标是提供*确定性*和*可靠性*的任务执行。保证高优先级的任务能在预定的时间内(或尽可能接近)响应事件并执行完毕。对于控制类应用(如电机控制、传感器读取)至关重要。
  • 轻量级:设计极其精简,内核代码量小(通常几KB到十几KB),内存占用低(RAM 需求从几百字节到几KB不等)。这使得它非常适合资源极其有限的微控制器。
  • 可移植性:内核绝大部分代码用标准的 C 语言编写,与处理器架构无关。通过提供针对不同处理器架构(ARM Cortex-M, RISC-V, PIC, AVR, MSP430, Xtensa 等)的*移植层*,可以轻松地移植到各种微控制器上。
  • 开源免费:采用 MIT 许可证,允许在商业闭源产品中免费使用、修改和分发,无需支付版税,极大地降低了开发成本。

核心功能:
任务调度:

  •  抢占式调度:核心机制。高优先级任务可以“抢占”(中断)正在运行的低优先级任务,立即获得 CPU 执行权,确保高优先级事件的及时响应。
  • 时间片轮转调度: 在相同优先级的任务之间,可以配置为按时间片轮流执行,实现公平性。
  • 协程: 提供了一种更轻量级的、协作式(非抢占)的任务模型(现在较少使用)。

任务间通信与同步:

  • 队列:最主要的通信机制。任务之间、任务与中断服务程序之间可以通过队列安全地传递数据(消息或数据块)。支持阻塞和非阻塞操作。
  • 信号量:用于资源访问控制(二进制信号量、计数信号量)和任务同步(通常用二进制信号量实现)。
  • 互斥锁: 一种特殊的二进制信号量,具有*优先级继承*机制,用于解决优先级反转问题,保护共享资源。
  • 事件组:允许任务等待或通知多个事件(标志位)的组合,提供更灵活的同步方式。

内存管理:

  • FreeRTOS 本身不提供复杂的内存分配器,而是提供几个可选的、简单的堆管理方案(`heap_1` 到 `heap_5`),开发者也可以完全使用自己的内存分配策略。
  • `heap_4` 和 `heap_5` 提供了碎片整理功能。

时间管理:

  • 系统节拍器:依赖硬件定时器中断提供时间基准(Tick),用于任务延时、超时判断和调度决策。
  • 软件定时器:提供创建周期性或一次性定时器的功能(由守护任务管理执行回调函数)。
  • 中断管理:提供安全的机制让中断服务程序与任务进行通信(通常通过队列、信号量、任务通知)和唤醒阻塞的任务。定义了中断安全版本的 API(通常以 `FromISR` 结尾)。

优势:

  • 极低的资源开销:对 RAM 和 ROM 的需求极小,适用于成本敏感、资源受限的 MCU。
  • 卓越的实时性能: 抢占式调度确保了关键任务能及时响应。
  • 高可移植性:广泛支持各种微控制器架构和开发工具链。
  • 强大社区和生态系统:拥有庞大且活跃的开发者社区,丰富的文档、教程、示例和第三方组件支持。
  • 免费且商业友好:MIT 许可证消除了商业化的障碍。
  • 成熟稳定:经过多年发展和广泛应用(数十亿设备部署),非常成熟可靠。
  • 模块化设计:核心精简,许多高级功能(如 TCP/IP 栈、文件系统、USB 协议栈)可通过附加组件实现,按需选用,避免资源浪费。
  •  亚马逊维护: 自 2017 年起由亚马逊 AWS 收购并积极维护,确保了其持续发展和支持。

    应用领域:

  • 工业自动化与控制(PLC、传感器、执行器)

  • 消费电子(家电、可穿戴设备、智能家居)

  • 汽车电子(车身控制、信息娱乐辅助系统)

  • 物联网设备与边缘节点

  • 医疗设备(监护仪、便携设备)

  • 网络设备(交换机、路由器模块)

  • 测试测量设备

  • 任何需要多任务管理、实时响应且运行在资源受限 MCU 上的嵌入式系统。

部署

以STM32cubeIDE为例,核心流程:创建工程 -> 图形化配置 -> 生成代码 -> 编写任务代码

S1:创建或打开 STM32CubeIDE 工程

S2:使用 CubeMX 配置 FreeRTOS

ioc 配置

在 Project Explorer 中双击项目根目录下的 .ioc 文件,打开 CubeMX 图形界面。

启用 FreeRTOS

在左侧的 Middleware and Software Packs 分类下,找到 FREERTOS。点击下拉箭头,选择 CMSIS_V2 (推荐使用此版本,兼容性更好,功能更丰富)。状态会变为 Enabled(可选) 如果你看到的是 CMSIS_V1 或 NativeCMSIS_V2 通常是更好的选择。

配置 FreeRTOS 参数 (关键步骤)

  • 切换到顶部的 Middleware and Software Packs 选项卡 (或直接在 .ioc 视图中间区域找到 FreeRTOS 配置项)。

  • 选择 FreeRTOS 接口,推荐选择 CMSIS_V2(功能更丰富,兼容性更好),点击下拉框 → 选择 CMSIS_V2 → 状态变为 Enabled

  • 展开 FREERTOS 下的 Configuration,

  • Kernel Settings 标签页

    • TICK_RATE_HZ:设置系统节拍频率 (Hz)。通常为 1000 (1ms) 或 100 (10ms)。更高的 Tick Rate 提供更精细的时间控制但增加 CPU 开销。

    • USE_PREEMPTION:确保勾选 (抢占式调度是核心)。

    • MAX_PRIORITIES:设置最大优先级数量 (通常 5-15 足够,太多浪费 RAM)。

    • MINIMAL_STACK_SIZE:设置最小任务栈大小 (单位:字,4字节/字)。务必根据任务需求增加! 默认值 (128 字 = 512 字节) 对简单任务可能够用,复杂任务或使用 printf 等函数需增大 (如 256-512 字或更大)。栈溢出是常见问题!

    • TOTAL_HEAP_SIZE非常重要! 设置 FreeRTOS 动态内存堆的总大小 (单位:字节)。所有任务栈、队列、信号量等动态创建对象都从这里分配。默认值 (3072 字节 = 3KB) 通常太小! 根据你计划创建的任务数和对象大小估算并增大 (例如 8192, 16384 甚至更大)。监控运行时的 xPortGetFreeHeapSize() 来调整。

    • MEMORY_ALLOCATION:选择内存分配方案:

      • Dynamic:使用 FreeRTOS 自带的堆管理器 (heap_x.c)。heap_4.c (包含碎片合并) 是最常用推荐选项 (在 Project Manager -> Code Generator 中选择 Copy only necessary library files 后会自动包含)。

      • Static:用户自己提供内存块 (需要手动分配内存数组)。更复杂但确定性更高。

 配置系统时钟 (SysTick 冲突)

    • FreeRTOS 默认使用 SysTick 定时器作为其时钟源 (Timebase Source)。

    • 转到 System Core > SYS 配置。

    • 确保 Timebase Source 设置为除 SysTick 以外的选项 (如 TIM1TIM6 等)。这是必须步骤,避免 FreeRTOS 和 HAL 库争用 SysTick。

  1. 配置中断优先级 (NVIC)

    • 转到 System Core > NVIC

    • 找到与 FreeRTOS 相关的中断:

      • PendSV_IRQn:应设置为最低优先级 (如优先级 15)。

      • SVCall_IRQn:通常设置为最低优先级 (如优先级 15)。

      • SysTick_IRQn:FreeRTOS 使用,优先级应高于 PendSV 和 SVC,但低于等于你应用的最高优先级中断。一个常见的设置是比最低优先级高一点 (如优先级 14 或 15)。确保其抢占优先级低于你的关键硬件中断。

    • 关键原则:确保 FreeRTOS 管理的中断 (PendSVSVCSysTick) 的优先级低于等于你应用中需要快速响应的硬件中断的优先级。避免 FreeRTOS 中断抢占关键硬件中断。

S3:生成代码

  1. 完成所有配置(FreeRTOS 和其他所需外设如 GPIO, UART, SPI 等)后。

  2. 点击 CubeMX 界面顶部的 GENERATE CODE 按钮 (或按 Alt+K)。

  3. STM32CubeIDE 会自动:

    • 根据你的配置生成 HAL 库初始化代码。

    • 生成 FreeRTOS 配置文件 FreeRTOSConfig.h (位于 Core/Inc),包含所有你在 CubeMX 中设置的宏定义。

    • 生成 FreeRTOS 移植层代码 (位于 Middlewares/Third_Party/FreeRTOS/Source/portable/[Compiler]/[Architecture],如 GCC/ARM_CM4F)。

    • 生成你在 Tasks and Queues 中定义的任务函数框架 (位于 Core/Src/freertos.c 和 Core/Inc/freertos.h)。任务函数体是空的 for(;;) 循环或 osDelay 调用。

    • 将 FreeRTOS 内核源文件 (tasks.cqueue.clist.ctimers.cevent_groups.cheap_x.c 等) 链接到你的项目 (通常位于 Middlewares/Third_Party/FreeRTOS/Source)。

S4:编写任务代码

  1. 在 Project Explorer 中,打开 Core/Src/freertos.c 文件。

  2. 找到你在 CubeMX 中创建的任务对应的函数 (如 void StartDefaultTask(void *argument)。

  3. 在此函数内编写你的任务逻辑

    • 任务通常包含一个无限循环 (for(;;) {...} 或 while(1) {...})。

    • 在循环内部,使用 FreeRTOS API 进行:

      • 延时vTaskDelay(pdMS_TO_TICKS(100)); // 延迟 100ms (推荐方式)

      • 挂起/恢复任务vTaskSuspend()vTaskResume()

      • 任务间通信xQueueSend()xQueueReceive()xSemaphoreGive()xSemaphoreTake()xEventGroupSetBits()xEventGroupWaitBits() 等。

      • 获取时间xTaskGetTickCount()

  4. 创建更多任务/对象

    • 除了在 CubeMX 中静态创建的任务,可以在 main() 函数 (或某个任务中) 使用 FreeRTOS API 动态创建

      ​
      xTaskCreate(MyTaskFunction,   // 任务函数指针
                  "MyTaskName",     // 任务名字符串
                  256,              // 栈大小 (字)
                  NULL,             // 传递给任务的参数
                  tskIDLE_PRIORITY + 2, // 优先级
                  &xMyTaskHandle);  // 任务句柄指针 (用于后续操作)
      
      ​
    • 同样可以动态创建队列、信号量等:xQueueCreate()xSemaphoreCreateBinary() 等。

  5. 启动调度器

    • 在 Core/Src/main.c 的 main() 函数中,HAL 初始化 (MX_xxx_Init()) 和 FreeRTOS 初始化 (MX_FREERTOS_Init()) 完成后,会调用 osKernelStart() (这是 CMSIS-RTOS v2 封装的 API)。

    • osKernelStart() 会启动 FreeRTOS 调度器,永不返回。 你的任务从此开始运行。

 S5:编译、下载与调试

  1. 编译:点击工具栏上的锤子图标或 Project -> Build Project

  2. 下载:连接开发板,点击工具栏上的绿色箭头图标或 Run -> Run

  3. 调试

    • 使用 STM32CubeIDE 的内置调试器。

    • 查看任务状态:在 Run -> Debug 后,打开 Window -> Show View -> Other...,在 FreeRTOS 分类下找到 FreeRTOS Task List 和 FreeRTOS Queue List 等视图。这些视图能实时显示任务状态(Running, Ready, Blocked, Suspended)、栈使用量、队列状态等,是调试利器!

    • 监视堆使用:在代码中调用 xPortGetFreeHeapSize() 或 uxTaskGetStackHighWaterMark() 监控堆和栈的使用情况,防止溢出。

 关键注意事项与提示:

  1. 栈大小 (Stack Size) 和堆大小 (TOTAL_HEAP_SIZE): 这是新手最容易出错的地方。务必根据任务复杂度、函数调用深度(尤其是递归、局部大数组、调用库函数如 printf)、队列/信号量数量等慷慨设置实时监控。栈溢出或堆耗尽会导致极其难以调试的崩溃。

  2. 中断优先级 (NVIC): 正确配置 SysTickPendSVSVC 的优先级至关重要,必须低于你的关键硬件中断优先级。

  3. Timebase Source: 必须确保不是 SysTick

  4. API 版本: 优先使用 CMSIS-RTOS v2 (CMSIS_V2) 封装层。它提供了更现代、更统一的 API 接口。

  5. 延时: 在任务中务必使用 FreeRTOS 提供的延时函数 (vTaskDelayosDelay),而不是 HAL_Delay 或忙等待。这会让出 CPU 给其他任务。

  6. 共享资源保护: 在任务间或任务与中断间共享变量、外设等资源时,必须使用互斥量 (osMutex...)、信号量或关中断等机制进行保护,防止竞态条件。

  7. FreeRTOSConfig.h: 这个文件定义了所有核心配置。CubeMX 生成后,除非必要,不建议手动修改,最好通过 CubeMX 界面修改后重新生成。如需手动调整高级特性,请小心操作。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值