告别开发板,零成本学习 FreeRTOS 本文介绍一个开源项目easy-freertos它将 FreeRTOS 内核、ARM GCC 工具链、QEMU 模拟器和 STM32 HAL 打包在一起让你无需任何外部依赖即可开始学习嵌入式实时操作系统仓库地址https://gitcode.com/qingshan1206/easy-freertos。为什么需要这个项目学习 FreeRTOS 通常面临两个门槛硬件门槛需要购买开发板、配置交叉编译工具链、烧录固件环境门槛需要安装 STM32CubeMX、Keil MDK、STM32CubeIDE 等大型 IDEeasy-freertos的目标是一条命令即可开始 FreeRTOS 学习。# 克隆项目后直接构建运行gitclone https://gitcode.com/qingshan1206/easy-freertos.gitcdeasy-freertos cmake-S.-Bbuild cmake--buildbuild项目内置了✅ ARM GCC 15.2.1 交叉编译工具链无需安装✅ QEMU ARM 系统模拟器无需真实硬件✅ STM32L475 HAL 库✅ FreeRTOS V10.3.1 内核✅ CMSIS-RTOS2 应用编程接口项目概览目标平台STM32L475VGTX (Cortex-M4F, 带硬件 FPU)仿真环境QEMU (ARM System Emulator)参考开发板ST 官方 B-L475E-IOT01A核心定位面向初学者的 FreeRTOS 学习项目使用 CMSIS-RTOS2 标准 API源码结构构建系统详解架构设计整个项目采用单可执行文件模式三个静态库hal、bsp、freertos始终编译通过BUILD_PROJECT变量选择哪个main.c参与链接。CMake 构建流程 ├── 1. 加载工具链 → cmake/arm-none-eabi.cmake ├── 2. 发现项目 → projects/projects.cmake扫描 */project.cmake ├── 3. 编译静态库 │ ├── hal → STM32 HAL 启动代码 系统调用桩 │ ├── bsp → boardInit() 半主机日志 │ └── freertos → 内核 端口层 heap_4 CMSIS-RTOS2 适配 ├── 4. 链接单一可执行文件 └── 5. 后构建生成 .bin .dis 内存使用报告编译命令# 默认构建 01_task_createcmake-S.-Bbuild cmake--buildbuild# 构建指定项目cmake-S.-Bbuild-DBUILD_PROJECT02_list cmake--buildbuild# 清理cmake--buildbuild--targetdistcleanCMAKE_TOOLCHAIN_FILEcmake/arm-none-eabi.cmake已设为默认值无需手动指定。关键链接选项-nostartfiles # 不使用标准启动文件用自定义 startup_stm32l475xx.s -specsnosys.specs # 使用 nosys 库无操作系统环境 -static # 静态链接 -Wl,--gc-sections # 垃圾回收未引用段 -TSTM32L475VGTX_FLASH.ld # 链接脚本技术特性1. 内存布局区域地址大小用途ROM0x080000001024KB代码、常量、向量表RAM0x2000000096KB.data, .bss, 堆, 栈SRAM20x1000000032KB额外数据区FreeRTOS Heap—16KBpvPortMalloc()分配2. 启动流程Reset_Handler (startup_stm32l475xx.s) → SystemInit() // 配置时钟树MSI → PLL → 80MHz → __libc_init_array() // C 静态构造函数 → main() // 进入应用代码 → boardInit() // HAL_Init() logInit() → osKernelInitialize() // CMSIS-RTOS2 内核初始化 → osThreadNew(...) // 创建任务 → osKernelStart() // 启动调度永不返回3. 调试输出半主机模式由于运行在 QEMU 中无真实 UART调试输出使用 ARM 半主机协议// bsp/log_semihost.cstaticinlineuint32_tsemihostingCall(uint32_tsyscall,void*params){// 内联汇编bkpt 0xAB — 触发 QEMU 半主机处理}voidlogPrintf(constchar*format,...){charbuffer[256];vsnprintf(buffer,sizeof(buffer),format,args);semihostingWriteString(buffer);// SYS_WRITE0 0x04}日志宏LOGI()→[INFO]: messageLOGD()→[DEBUG]: messageLOGW()→[WARN]: messageLOGE()→[ERROR]: message4. CMSIS-RTOS2 适配层应用代码使用 CMSIS-RTOS2 标准接口而非裸 FreeRTOS APICMSIS-RTOS2 API对应 FreeRTOS APIosKernelInitialize()xTaskCreateStatic() 内部初始化osThreadNew()xTaskCreateStatic()osDelay()vTaskDelay()osKernelStart()vTaskStartScheduler()示例演示01_task_create项目结构projects/01_task_create/ ├── project.cmake # CMake 项目配置 ├── app/ │ └── main.c # 核心应用代码76行 └── config/ ├── FreeRTOSConfig.h # FreeRTOS 内核配置 └── stm32l4xx_hal_conf.h # STM32 HAL 模块配置核心代码/** * file main.c * brief CMSIS-RTOS2 双任务创建示例 * * 本文件演示如何使用 CMSIS-RTOS2 创建并运行两个 RTOS 任务 * - test_task1每秒打印一次 * - test_task2每两秒打印一次 * 两个任务并发运行由 RTOS 内核调度。 */#includestdint.h#includecmsis_os2.h#includeboard.h/** * brief 任务1函数 - 每 1000 ticks打印一次 */voidtest_task1(void*argument){int32_tcounter0;while(1){LOGI(Test Task1 running %d...,counter);osDelay(1000);}}/** * brief 任务2函数 - 每 2000 ticks打印一次 */voidtest_task2(void*argument){int32_tcounter0;while(1){LOGI(Test Task2 running %d...,counter);osDelay(2000);}}/** * brief 程序入口函数 * * 执行以下步骤 * 1. 初始化板级硬件 * 2. 初始化 CMSIS-RTOS2 内核 * 3. 创建 test_task1 和 test_task2 两个任务 * 4. 启动 RTOS 内核调度从此进入多任务并发模式 */intmain(void){osThreadAttr_tattr1{.nametest_task1,.stack_size1024,// 1024字 4KB32位系统.priorityosPriorityNormal,};osThreadAttr_tattr2{.nametest_task2,.stack_size1024,.priorityosPriorityNormal,};boardInit();// 初始化板级硬件osKernelInitialize();// 初始化 CMSIS-RTOS2 内核osThreadNew(test_task1,NULL,attr1);// 创建任务11秒间隔osThreadNew(test_task2,NULL,attr2);// 创建任务22秒间隔osKernelStart();// 启动内核调度while(1);// 理论上不会执行到此}代码解析1. 任务函数设计voidtest_task1(void*argument){int32_tcounter0;while(1){LOGI(Test Task1 running %d...,counter);osDelay(1000);// 延时 1000 ticks1秒}}关键点任务函数绝不能返回必须while(1)或vTaskDelete(NULL)osDelay(1000)让出 CPU 给其他任务LOGI()使用半主机输出在 QEMU 控制台显示2. 任务属性配置osThreadAttr_tattr1{.nametest_task1,.stack_size1024,// 单位字Word.priorityosPriorityNormal,};注意事项stack_size单位是字Word不是字节1024 字 4096 字节 4KB32位系统osPriorityNormal是默认优先级03. 主函数流程intmain(void){boardInit();// 第一步硬件初始化osKernelInitialize();// 第二步RTOS 内核初始化osThreadNew(test_task1,NULL,attr1);// 第三步创建任务osThreadNew(test_task2,NULL,attr2);osKernelStart();// 第四步启动调度器while(1);// 防御性代码不应执行到此}执行流程图main() │ ▼ boardInit() ├── HAL_Init() // 初始化核心、SysTick、NVIC └── logInit() // 半主机初始化无需硬件 │ ▼ osKernelInitialize() // FreeRTOS 内部初始化 │ ▼ osThreadNew(test_task1) // 创建任务1 osThreadNew(test_task2) // 创建任务2 │ ▼ osKernelStart() // 启动调度器永不返回 │ ▼ [RTOS 接管控制权 — 任务并发运行]FreeRTOSConfig.h 关键配置/* 调度器配置 */#defineconfigUSE_PREEMPTION1// 启用抢占式调度#defineconfigTICK_RATE_HZ1000// 系统节拍 1ms#defineconfigMAX_PRIORITIES56// CMSIS-RTOS2 要求 56/* 内存配置 */#defineconfigTOTAL_HEAP_SIZE(16*1024)// 16KB 堆#defineconfigMINIMAL_STACK_SIZE128// 最小栈单位字/* 内核特性 */#defineconfigUSE_TIMERS1// 启用软件定时器#defineconfigUSE_MUTEXES1// 启用互斥锁#defineconfigSUPPORT_STATIC_ALLOCATION1// CMSIS-RTOS2 要求/* 中断配置 */#defineconfigPRIO_BITS4// 16 个优先级级别#defineconfigLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY5// 安全中断优先级/* CMSIS-RTOS2 强制要求 */#defineconfigUSE_PORT_OPTIMISED_TASK_SELECTION0// 必须关闭构建并运行构建项目# 克隆项目gitclone https://github.com/xxx/easy-freertos.gitcdeasy-freertos# 构建默认项目01_task_createcmake-S.-Bbuild cmake--buildbuild# 构建完成后查看生成的文件ls-lhbuild/# FreeRTOS_test # ELF 可执行文件# FreeRTOS_test.bin # 固件镜像用于烧录# FreeRTOS_test.dis # 反汇编文件在 QEMU 中运行# 方式一直接运行推荐./tools/qemu/xpack-qemu-arm/bin/qemu-system-arm\-Mb-l475e-iot01a\-kernelbuild/FreeRTOS_test\-nographic\-semihosting-configenableon,targetnative# 方式二使用内置脚本./tools/qemu/qemu.sh预期输出[Test]: Test Task1 running 0... [Test]: Test Task2 running 0... [Test]: Test Task1 running 1... [Test]: Test Task1 running 2... [Test]: Test Task2 running 1... [Test]: Test Task1 running 3... [Test]: Test Task1 running 4... [Test]: Test Task2 running 2...Task1 每 1 秒出现一次Task2 每 2 秒出现一次交替打印——直观展示了 RTOS 的并发调度能力。VS Code 调试可选项目已配置.vscode/launch.json支持 QEMU GDB 远程调试在 VS Code 中按 F5 启动调试需安装C/C插件QEMU 启动并暂停在入口点可设置断点、单步执行、查看变量如何添加新项目只需在projects/下创建新目录projects/ └── 03_my_demo/ ├── project.cmake # CMake 配置 ├── app/ │ └── main.c # 你的代码 └── config/ ├── FreeRTOSConfig.h # 复制自 01_task_create └── stm32l4xx_hal_conf.h # 复制自 01_task_createproject.cmake 最小模板# 设置项目源文件 set(PROJECT_SOURCES ${CMAKE_SOURCE_DIR}/projects/03_my_demo/app/main.c ) # 设置配置目录 set(PROJECT_CONFIG_DIR ${CMAKE_SOURCE_DIR}/projects/03_my_demo/config ) # 设置包含目录 set(PROJECT_INCLUDES ${PROJECT_CONFIG_DIR} ) # 添加到全局列表 set(PROJECTS_SOURCES ${PROJECTS_SOURCES} ${PROJECT_SOURCES}) set(PROJECT_CONFIG_DIR ${PROJECT_CONFIG_DIR} ${PROJECT_CONFIG_DIR}) set(PROJECT_INCLUDES ${PROJECT_INCLUDES} ${PROJECT_INCLUDES})然后构建cmake-S.-Bbuild-DBUILD_PROJECT03_my_demo cmake--buildbuild项目约定命名规范类型风格示例用户代码snake_caseboardInit,logPrintfFreeRTOS 内核前缀规范v/x/ux/pc注释语言中文应用/ 英文内核—常见陷阱❌ 错误做法✅ 正确做法configMAX_SYSCALL_INTERRUPT_PRIORITY设为 0必须 0否则中断嵌套不安全任务函数返回必须while(1)或vTaskDelete(NULL)configUSE_PORT_OPTIMISED_TASK_SELECTION设为 1CMSIS-RTOS2 要求设为 0混用递归互斥量和普通互斥量xSemaphoreCreateMutex()配对xSemaphoreTake()项目文件速查表需求位置启动流程bsp/board.c→hal/Device/Src/system_stm32l4xx.c→projects/*/app/main.cFreeRTOS 配置projects/*/config/FreeRTOSConfig.hRTOS 端口层freertos/portable/GCC/ARM_CM4F/port.cCMSIS-RTOS2 APIprojects/*/app/main.c使用osThreadNew,osDelay内存管理freertos/portable/MemMang/heap_4.c链接脚本linkerscript/STM32L475VGTX_FLASH.ld半主机日志bsp/log_semihost.c构建系统CMakeLists.txtcmake/arm-none-eabi.cmake总结easy-freertos项目提供了完整的 FreeRTOS 学习环境零配置内置工具链和模拟器克隆即用渐进式学习从01_task_create开始逐步深入现代 API使用 CMSIS-RTOS2 标准接口便于移植到真实项目QEMU 调试无需真实硬件通过半主机模式查看调试输出项目隔离每个示例独立配置互不干扰推荐学习路径阅读01_task_create/main.c理解任务创建流程修改任务间隔如osDelay(500)观察调度行为查看02_list/main.c学习 FreeRTOS 内核数据结构自己编写新项目实践所学知识相关资源FreeRTOS 官方文档https://www.freertos.org/Documentation/RTOS_book.htmlCMSIS-RTOS2 API 参考https://developer.arm.com/documentation/101029/latest/QEMU ARM 系统模拟https://qemu-project.gitlab.io/qemu/system/arm/stm32.html项目源码https://gitcode.com/qingshan1206/easy-freertos

相关新闻

最新新闻

【QT】国产化编译指南7

【QT】国产化编译指南7

qt-everywhere-opensource5.12.6.zip与.tar.xz的区别qt-everywhere-opensource-src-5.12.6.zip 和 qt-everywhere-opensource-src-5.12.6.tar.xz 是 Qt 5.12.6 开源完整源码包的两种不同压缩格式,核心内容(源码文件)完全一致,主要…

2026/7/6 14:45:20
在 PMP(项目管理专业人士)考试中,“领导力、团队建设、冲突管理、利益相关者参与”构成了人(People)这一核心领域的核心考点

在 PMP(项目管理专业人士)考试中,“领导力、团队建设、冲突管理、利益相关者参与”构成了人(People)这一核心领域的核心考点

在 PMP(项目管理专业人士)考试中,“领导力、团队建设、冲突管理、利益相关者参与”构成了人(People)这一核心领域的核心考点(在考题中占比高达 42%)。尤其在敏捷(Agile)和…

2026/7/6 14:45:20
【QT】国产化编译指南6

【QT】国产化编译指南6

rmp系统能用yum吗在 Linux 系统中,通常是 “RPM 包管理系统”(使用.rpm 格式包的系统,如 CentOS、RHEL、Fedora 等),这类系统可以使用 yum。yum(Yellowdog Updater Modified)是基于 RPM 包管理的…

2026/7/6 14:45:20
【QT】国产化编译指南5

【QT】国产化编译指南5

银河麒麟高级服务器操作系统V10(Kylin Linux Advanced Server V10)的x86结构和arm架构分别可以用哪个版本的qt包,能离线安装。附带链接网址 以下是银河麒麟高级服务器操作系统 V10 不同架构可用的离线安装 Qt 包版本及链接: x86…

2026/7/6 14:45:20
【CMD】查找进程运行状态

【CMD】查找进程运行状态

查看进程的运行状态,可根据操作系统的不同使用相应的命令,以下是常见系统的操作方法:一、Linux/Unix 系统通过 ps、top 或 htop 命令查看进程状态,其中 ps 命令最常用,可显示进程的状态标识(如运行、睡眠、…

2026/7/6 14:45:20
【AAAI 2026】VQAThinker:通过RL进行可解释VQA训练

【AAAI 2026】VQAThinker:通过RL进行可解释VQA训练

note 本文提出了VQAThinker,一种基于推理的VQA框架,通过结合大型多模态模型和强化学习,实现了可泛化和可解释的视频质量评估。它把视频质量评估从“直接回归一个分数”,升级成“先像人一样分析视频有哪些质量问题,再给…

2026/7/6 14:40:20

月新闻