4. 医疗可穿戴设备操作系统与实时调度
医疗可穿戴设备与普通消费电子最大的差别,在于它必须对生理事件给出可预期、可界定的响应。一次心率异常、一次血氧骤降、一次跌倒冲击,如果被延迟几十毫秒甚至上百毫秒才处理,可能就错过了临床上有意义的窗口。因此,操作系统与调度策略的选择,本质上是在回答一个问题:当多个任务同时想占用 CPU 时,谁先运行、运行多久、什么时候必须让出。本节围绕 RTOS、Linux、Zephyr 三类典型运行环境,讲清任务优先级、中断处理与低功耗调度如何协同工作。
一、三类运行环境的定位差异
医疗可穿戴设备的软件栈通常不是单一系统,而是分层组合。最贴近传感器的是实时操作系统(RTOS),如 FreeRTOS、Zephyr、RT-Thread,它们提供确定性的任务切换和微秒级中断响应;中间层可能是嵌入式 Linux,负责显示、蓝牙协议栈、文件系统和网络;再上层是应用逻辑与算法。Zephyr 的特殊之处在于它既是 RTOS,又提供了设备树、Kconfig、网络协议栈和电源管理框架,适合从 MCU 到应用处理器的统一开发。
选择依据不是“哪个更先进”,而是时间确定性要求。心电采样、PPG 采样、跌倒检测这类硬实时任务,必须在截止时间内完成,适合放在 RTOS 或 Zephyr 的高优先级任务中;而数据上传、界面刷新、日志写入属于软实时或非实时任务,可以放在 Linux 或低优先级任务中。混合架构中,MCU 负责采集与实时判断,Linux 主控负责交互与联网,两者通过 SPI、UART 或共享内存通信。
二、任务优先级:不是越高越好
在 RTOS 中,优先级通常是一个整数,数值越小或越大代表优先级越高,具体取决于系统约定。以 Zephyr 为例,优先级数值越小优先级越高,范围从负数的协作式优先级到正数的抢占式优先级。医疗设备中常见的任务划分如下:
- 中断服务程序(ISR):不参与任务调度,但触发后立即执行,负责把数据从硬件寄存器搬走、置位信号量或发送消息队列。
- 采样任务:优先级最高,周期固定,例如 ECG 以 250 Hz 采样,每 4 ms 触发一次,必须在下一个采样点到来前完成读取和初步滤波。
- 检测任务:优先级次高,对采样数据做 QRS 检测、跌倒判断,允许几毫秒到几十毫秒的延迟。
- 通信与存储任务:优先级较低,负责打包、写 Flash、通过 BLE 发送,可以容忍百毫秒级延迟。
优先级分配的核心原则是速率单调调度:周期越短、截止时间越紧的任务,优先级越高。但要注意优先级反转问题——当低优先级任务持有高优先级任务需要的互斥锁时,高优先级任务会被阻塞。解决办法是使用优先级继承互斥量,或在设计上避免共享资源的长时间占用。
三、中断处理:快进快出,把重活留给任务
中断是实时性的第一道关口。ISR 执行时间越长,其他中断被延迟的概率越大。医疗设备中,ECG 前端芯片的 DRDY 引脚、IMU 的 FIFO 水印中断、BLE 的连接事件中断,都需要在微秒级得到响应。推荐的做法是两段式处理:ISR 只做最紧急的事,例如读取一个寄存器、把数据放入环形缓冲区、释放一个信号量;真正的滤波、特征提取、协议打包交给被唤醒的任务。
以 Zephyr 为例,可以用 k_sem_give() 在 ISR 中释放信号量,采样任务在 k_sem_take() 上等待。这样 ISR 执行时间可以控制在几微秒,而任务上下文可以安全地使用浮点运算、动态内存和阻塞调用。中断优先级也需要配置:NVIC 中数值越小优先级越高,通常把采样相关中断设为最高,通信中断设为较低,避免 BLE 中断频繁打断采样。
四、低功耗调度:让 CPU 在无事可做时真正停下来
可穿戴设备的电池容量通常只有几百毫安时,续航要求却常常是数天到数周。低功耗调度的核心思想是事件驱动 + 深度休眠。当所有任务都在等待信号量、消息队列或定时器时,调度器应让 CPU 进入低功耗状态,而不是空转。
Zephyr 的 Tickless 模式是典型实现:关闭周期性系统 tick,只在下一个定时器到期或中断到来时唤醒。系统根据下一个超时时间计算可以休眠多久,选择对应的低功耗等级。例如,下一个采样点在 4 ms 后,就进入轻度睡眠;如果 500 ms 内没有任何任务就绪,就进入深度休眠,关闭高频时钟和外设电源。
实际配置时,需要关注几个参数:唤醒延迟(从休眠到恢复运行的时间)、外设功耗(传感器是否支持低功耗模式)、通信占空比(BLE 连接间隔从 7.5 ms 到 4 s 可调)。一个常见的优化是:把 BLE 连接间隔从 20 ms 放宽到 200 ms,同时把数据缓存在本地,每 200 ms 批量发送一次,可以显著降低射频和 CPU 的唤醒次数。
五、一个可参考的调度配置示例
下面给出一个基于 Zephyr 的简化配置片段,用于说明采样任务、检测任务和低功耗策略如何组合。参数为教学示例,实际值需根据传感器手册和功耗预算调整。
/* 采样任务:周期 4 ms,优先级 1(数值小优先级高) */
K_THREAD_DEFINE(sampling_tid, 1024,
sampling_task, NULL, NULL, NULL,
1, 0, 0);
/* 检测任务:由采样任务通过消息队列触发,优先级 3 */
K_THREAD_DEFINE(detect_tid, 2048,
detect_task, NULL, NULL, NULL,
3, 0, 0);
/* 信号量:ISR 释放,采样任务获取 */
K_SEM_DEFINE(drdy_sem, 0, 1);
void ecg_drdy_isr(const struct device *dev)
{
k_sem_give(&drdy_sem); /* ISR 只做最少的事 */
}
void sampling_task(void)
{
while (1) {
k_sem_take(&drdy_sem, K_FOREVER);
ecg_read_sample(&sample);
ecg_filter(&sample);
k_msgq_put(&detect_q, &sample, K_NO_WAIT);
}
}
/* 低功耗:启用 Tickless,空闲时自动进入低功耗 */
CONFIG_TICKLESS_IDLE=y
CONFIG_PM=y
CONFIG_PM_DEVICE=y
判断这套配置是否合理,可以观察三个指标:采样任务是否在每个周期内完成、消息队列是否溢出、系统在两次采样之间是否进入了低功耗状态。如果采样任务执行时间接近 4 ms,说明滤波算法需要简化或下移到检测任务;如果消息队列频繁满,说明检测任务优先级偏低或处理太慢;如果电流波形显示 CPU 一直在运行,说明 Tickless 未生效或某个外设阻止了休眠。
六、选型与调度的实践建议
对于以生理信号采集为核心、对时间确定性要求高的设备,优先选择 RTOS 或 Zephyr,把硬实时任务放在 MCU 上;对于需要图形界面、Wi-Fi、云端协议栈的设备,可以采用“MCU + Linux”双核架构,MCU 负责实时采集和本地判断,Linux 负责交互和联网。无论哪种架构,调度设计都应遵循三条原则:中断快进快出、高优先级任务短而确定、空闲时真正休眠。这三条原则落实到位,医疗可穿戴设备才能在保证临床响应质量的同时,把功耗控制在可接受范围内。