
为了演示在裸机环境中添加RTOS,我们使用一个基于STM32 NUCLEO-C562RE开发板的“Hello Blinky”应用程序,该程序已在IAR Embedded Workbench中成功编译。
项目使用STM32CubeMX生成,并编写了一些基本的控制逻辑,用于读取按键状态、改变状态并闪烁LED灯。项目仅包含标准的启动代码、时钟配置以及main()函数中的一个while循环。基于该应用程序,我们只需添加PX5 RTOS即可。
PX5 RTOS是一种专为资源受限的嵌入式设备设计的第五代实时操作系统(RTOS)。它强调高性能、极小的内存占用和经过认证的安全性,适用于包括汽车、工业自动化、医疗设备和IoT在内的各种应用场景。
在项目创建完成后,我们就可以开始将PX5集成到应用中。
从RTOS的角度来看,每个应用程序只需提供以下四项功能:
• 用于在线程之间进行上下文切换的机制;
• 周期性系统滴答,以便调度器能够管理延迟、超时和定时器;
• 线程执行所需的栈空间;
• 启动调度器并移交其控制权移的入口。
在Cortex-M微控制器上,上下文切换通常基于PendSV异常实现,而周期滴答则来自SysTick。
在此阶段,我们所做的只是添加调度器,并将其连接到若干与架构相关的回调函数。
集成过程包含五个简单步骤。
步骤1:添加RTOS源文件
在IAR Embedded Workbench中,将PX5调度器实现文件(px5.c)和Cortex-M架构实现文件(px5_binding.S)添加到项目中:

图1 将PX5源码添加到IAR Embedded Workbench项目中
接下来,设置编译器指向PX5的头文件和源文件目录,如下所示:

图2 在Preprocessor选项卡中添加PX5包含路径
构建项目,PX5 RTOS成功编译。

图3 添加PX5 RTOS后成功构建
此时,RTOS已添加到项目中,但尚未运行。
步骤2:启动调度器
接下来,我们要启动调度器。首先在main.c中添加POSIX线程头文件:
#include <pthread.h>
然后调用px5_pthread_start()初始化RTOS:
px5_pthread_start(0,NULL,0);
px5_pthread_start()函数在调度器初始化完成后返回。此后,main()函数将成为RTOS管理的一个POSIX线程。
无需重新编写应用,调度器被插入到现有应用程序!
在此步骤中,可能还需要进行一项额外的修改。由于PX5实现了上下文切换机制,STM32CubeMX生成的PendSV_Handler函数需删除或注释掉。
此时,应用程序已具备多线程能力,但其执行效果仍和之前完全一致。运行该应用时,观察到的行为与之前毫无差别,唯一的不同是现在这段裸机代码是由PX5内核来执行。
所有与计时器无关的功能现已启用!不过,如果你要使用时间相关功能,则需要添加时间支持。接下来我们就来完成这一步。
步骤3:添加系统滴答
调度器现已启动运行,但目前尚未接入时间源。
若要启用延迟、定时器及超时服务,需在SysTick_Handler()中调用px5_timer_interrupt_process()。可以在项目中搜索SysTick_Handler来找到该函数;对于STM32C562,函数位于generated/hal/mx_system.c文件中,按如下方式对其进行修改:

图4 将PX5定时器服务接入SysTick_Handler
注意,你可能还需要在文件顶部添加#include <pthread.h>。
还需要根据应用场景,为SysTick中断配置合适的优先级。在示例中,优先级设为高(1)。打开generated/hal/stm32c5xx_hal_conf.h文件,找到USE_HAL_TICK_INT_PRIORITY将其值设为1:
#define USE_HAL_TICK_INT_PRIORITY 1U /*!<tick interrupt priority*/
如果没有这个函数,线程调度、互斥锁、信号量及其他同步原语仍可正常工作。只有依赖时间的服务例如线程休眠和软件定时器不可用。
步骤4:验证RTOS已正确添加到裸机环境中
此时,应用程序的构建、下载和执行行为与之前完全一致。区别在于,它现在是在RTOS的控制下运行的。
验证定时器服务是否正常运行的一个简单方法是将忙等待替换为以下函数的调用:
px5_pthread_tick_sleep(10);
如果线程按预期完成休眠并恢复运行,说明调度器与系统滴答协同工作。
步骤5:启用可选功能
以上四个步骤就是将RTOS添加到裸机环境中所需的全部操作。之后,可以根据应用的实际需求启用附加功能。
例如,如果你需要动态创建线程、互斥锁或其他对象,可以为px5_pthread_start()提供一块内存区域,供PX5用于分配操作。完全依赖静态分配的应用程序则可直接跳过这一步。
同样,如果使用PX5的指针/数据验证(PDV)功能,可在启动阶段传入运行时生成的随机种子。这会让应用每次执行时都生成独一无二的验证值,从而强化RTOS执行的完整性校验。
要让现有裸机应用在PX5下运行,这两项特性都不是必需的。
提示:在此阶段,你已成功将RTOS添加到裸机开发环境中。项目目前已在RTOS的控制下运行。原有的启动代码保持完整,项目结构未发生改动,现有的构建系统也仍能和之前一样正常工作。你无需围绕新框架重新构建应用程序,只需在能正常运行的软件底层引入一个调度器即可。
此时,应用程序在PX5调度下运行,但其行为并未改变。整个超级循环只是在main()线程内部执行。
开发者在引入RTOS时最常见的错误之一,就是试图一次性重新设计整个应用程序。每个循环都变成一个线程,每个全局变量都变成共享状态,结果项目变得比实际需要复杂得多。
相反,应采取逐步迁移的方式。
我们的示例应用包含了两个独立的功能:一部分代码负责监控并去抖用户按键,另一部分则负责以指定频率闪烁LED。目前这两个功能在同一个while循环内执行。

图5 按键处理和LED闪烁位于单一的超级循环
第一步先识别出可独立执行的任务。由于main()函数本身已以POSIX线程的形式运行,你可以按单一职责的原则,逐步将功能迁移到其它线程中。
例如,只需修改极少量代码,即可将LED闪烁逻辑移入独立线程中:
static void *led_thread(void *arg){while (1){HAL_GPIO_TogglePin(HAL_GPIOA,LD1_PIN);px5_pthread_tick_sleep(BLINK_PERIOD);}return NULL;}
我们只需在启动期间创LED建线程:
pthread_t led_thread_handle;pthread_create(&led_thread_handle,NULL,led_thread,NULL);
现在LED功能可独立运行。按键处理逻辑可以原封不动地保留在当前位置,直到你准备好对其进行迁移。最终,应用会演进为如下所示的形态:

图6 基于PX5调度器拆分线程
你的应用代码最终可能如下所示:
int main(void){if (mx_system_init() != SYSTEM_OK){return -1;}gpio_init();/* Start PX5 RTOS */px5_pthread_start();/* Create application threads */pthread_create(&led_thread_handle,NULL,led_thread,NULL);pthread_create(&button_thread_handle,NULL,button_thread,NULL);while(1){/* Optional housekeeping */px5_pthread_tick_sleep(1000);}}
硬件初始化逻辑仍位于main()函数中,时钟配置未做改动,GPIO初始化流程完全一致。应用代码并非被重写,而是在原有基础上迭代演进而来!
这是一个至关重要的区别。
我们的目标并非一次性把所有函数都改造成线程。真正的目标是先识别出独立的任务,将它们迁移到独立的执行上下文中,验证整个系统仍能正常运行,之后再重复这一流程。每次迁移的规模都很小,既易于理解,也便于测试,却能逐步优化你的架构、可扩展性、可复用性等方面。
当许多开发者考虑如何在裸机系统中引入RTOS时,往往会想到需要数周的工作、全新的构建系统以及对整个应用程序的彻底重写。但实际上,在裸机系统上添加RTOS的学习过程要简单得多。
我们以一个已运行的STM32裸机应用为基础,通过引入调度器、连接几个架构特定的钩子函数,并启用系统滴答,成功添加了PX5 RTOS。应用本身基本保持不变,之后便可逐步演化为多线程设计,每个线程负责单一任务。
这种区别在将RTOS引入裸机系统时尤为重要。
添加RTOS与采用软件框架是两个截然不同的决策。如果你的目标仅仅是为现有应用引入确定性调度和多线程功能,那么你不一定需要替换已经构建好的项目。要成功地在裸机系统中引入RTOS,有时你所需要的仅仅是一个调度器。
PX5很好地展示了这一方法:集成工作量小,应用界面依然熟悉,迁移过程可以分阶段进行,而非一次性全面重写。
麦克泰技术是PX5 RTOS的合作伙伴和代理商,长期致力于嵌入式安全操作系统的市场与技术服务工作,欢迎联系info@bmrtech.com咨询相关信息。

产品购买(麦克泰)

产品购买(贝尼思)

线上课程(网校)
欢迎关注微信公众号【麦克泰技术】,回复 “加群” 按提示可加入技术交流群
产品咨询:
北京:010-62975900
上海:021-62127690
深圳:0755-82977971
分享、在看与点赞,至少我要拥有一个吧
