前置说明
- 开发环境:CubeMX+CLion,Windows
- 工具链:CMake + Ninja + arm-none-eabi-gcc + JLink
- 芯片选择:STM32F103CB(T6)
- 参考资料来源:b站up主keysking
1.Pinout&Configuration
(1)SystemCore
- GPIO设置
- SYS设置:
- Debug选Serial Wire
- Timebace Source不使用SysTick,切换成一个未使用的。比如我这里用TIM4。
Timebase Source(时基来源)是 STM32 HAL 库的 “时间基准” 配置,默认为SysTick。FreeRTOS 作为实时操作系统,必须有一个高精度、稳定的时钟基准来实现核心功能。因此,它会征用SysTick 。既然 Systick 被 FreeRTOS 占用了,就给 HAL 库重新指定一个未使用的通用定时器(比如 TIM4)作为时基来源。两者互不干扰,彻底解决冲突。

(2)Middleware & SoftPacks(中间件与软件)
- 选中左侧的FreeRTOS
- interface勾选CMSIS_V2,启用 CMSIS-OS2 接口规范来适配 FreeRTOS(或其他 RTOS)。
-
CMSIS-OS 是 ARM 公司推出的 “Cortex 微控制器软件接口标准(CMSIS)” 中的实时操作系统(RTOS)抽象层与 API 规范,并非独立的 RTOS。 CMSIS-OS 的核心价值是:定义一套统一的 RTOS 上层 API 规范,要求各 RTOS 厂商(如 FreeRTOS、RTX5)适配该规范。开发者只需基于 CMSIS-OS 接口编程,即可实现 “一次编码,多 RTOS 兼容”—— 更换 RTOS 时无需修改应用层代码,仅需替换底层 RTOS 内核和 CMSIS-OS 适配层。
- 选中下方出现的Tasks and Queues
- 该页面用于管理任务和任务队列。可以在这里查看当前代码有的任务,双击可查看与修改其属性。
- 新建项目中,会生成一个默认任务

2.ProjectManager
- 项目命名,路径选择
- Toolchain/IDE:选择CMake
- 点击右上角GenerateCode生成代码
3.CLine中打开项目
第一次打开项目需要配置一下工具链之类的,这里跳过,直接看到代码。我们以点灯测试为例,测试FreeRTOS是否正确安装。
打开main.c查看主要业务代码


- CMSIS中的Thread和FreeRTOS中的Task是同一概念
点开StartDefaultTask,转到其定义,编写一个小灯闪烁代码
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
for(;;)
{
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
osDelay(500);
}
/* USER CODE END 5 */
}
编译下载后,小灯成功闪烁,FreeRTOS移植成功。
3.补充资料
CMSIS-OS 的核心功能模块(基于 V2 规范)
CMSIS-OS2 定义了 7 大核心功能模块,所有接口均以 osXXX() 命名(如 osThreadNew()、osSemaphoreRelease()),开发者无需关注 RTOS 底层实现,仅需调用统一接口即可:
- 线程管理(核心模块)
- 功能:创建 / 删除线程、挂起 / 恢复线程、设置线程优先级、获取线程状态
- 关键接口:
- osThreadNew():创建并启动线程(替代 FreeRTOS 的 xTaskCreate());
- osThreadSuspend()/osThreadResume():挂起 / 恢复线程;
- osThreadGetState():获取线程状态(运行 / 就绪 / 阻塞 / 终止);
- 特性:支持抢占式调度(高优先级线程打断低优先级)、时间片轮转(同优先级线程轮流执行),适配 STM32 的中断机制(线程可被中断打断,中断服务函数中可调用 CMSIS-OS 安全接口)。
- 同步与通信机制
- 解决线程间、线程与中断间的协作问题
- 核心接口包括:
- 信号量(Semaphore):osSemaphoreNew()/osSemaphoreAcquire()/osSemaphoreRelease()—— 用于资源共享(如串口、SPI 外设)或线程同步;
- 互斥量(Mutex):osMutexNew()/osMutexAcquire()/osMutexRelease()—— 专门解决 “资源竞争”,支持优先级继承(避免优先级反转,STM32 外设共享场景必备);
- 消息队列(Message Queue):osMessageQueueNew()/osMessageQueuePut()/osMessageQueueGet()—— 线程间传递数据(如传感器数据、指令);
- 事件标志组(Event Flags):osEventFlagsNew()/osEventFlagsSet()/osEventFlagsWait()—— 线程等待多个事件触发(如 “按键按下 + 定时器超时”)。
- 时间管理
- 延时功能:osDelay()(相对延时,单位:系统滴答周期,默认 1ms)、osDelayUntil()(绝对延时,确保线程执行周期稳定);
- 软件定时器:osTimerNew()/osTimerStart()/osTimerStop()—— 基于系统滴答定时器的虚拟定时器,支持单次 / 周期性触发(如定时采集传感器数据);
- 系统时间:osKernelGetTickCount()—— 获取系统运行总滴答数(用于计时、日志时间戳)。
- 内存管理
- 动态内存:osMemoryPoolNew()—— 创建内存池,避免碎片化(比标准 malloc() 更适合 RTOS 场景,STM32 中常用于动态创建线程 / 队列);
- 静态内存:支持通过宏定义指定线程栈、队列缓冲区等的静态分配(适合无堆空间的 STM32 低端芯片,或对稳定性要求极高的场景)。
- 内核控制
- 内核启动:osKernelStart()—— 启动 RTOS 内核(STM32 中需在 main() 函数初始化硬件后调用);
- 内核状态:osKernelGetState()—— 判断内核是否运行、是否锁定;
- 临界区:osKernelLock()/osKernelUnlock()—— 禁止 / 允许线程调度(保护临界资源,如全局变量)。
下一步:体验FreeRTOS各大功能,了解每个模块的思想和实现方法。巩固C语言基础知识以及OS相关基础知识(需要出FreeRTOS源码分析?)
1116

被折叠的 条评论
为什么被折叠?



