4. 医疗可穿戴设备操作系统与实时调度

医疗可穿戴设备与普通消费电子最大的差别,在于它必须对生理事件给出可预期、可界定的响应。一次心率异常、一次血氧骤降、一次跌倒冲击,如果被延迟几十毫秒甚至上百毫秒才处理,可能就错过了临床上有意义的窗口。因此,操作系统与调度策略的选择,本质上是在回答一个问题:当多个任务同时想占用 CPU 时,谁先运行、运行多久、什么时候必须让出。本节围绕 RTOS、Linux、Zephyr 三类典型运行环境,讲清任务优先级、中断处理与低功耗调度如何协同工作。

一、三类运行环境的定位差异

医疗可穿戴设备的软件栈通常不是单一系统,而是分层组合。最贴近传感器的是实时操作系统(RTOS),如 FreeRTOS、Zephyr、RT-Thread,它们提供确定性的任务切换和微秒级中断响应;中间层可能是嵌入式 Linux,负责显示、蓝牙协议栈、文件系统和网络;再上层是应用逻辑与算法。Zephyr 的特殊之处在于它既是 RTOS,又提供了设备树、Kconfig、网络协议栈和电源管理框架,适合从 MCU 到应用处理器的统一开发。

选择依据不是“哪个更先进”,而是时间确定性要求。心电采样、PPG 采样、跌倒检测这类硬实时任务,必须在截止时间内完成,适合放在 RTOS 或 Zephyr 的高优先级任务中;而数据上传、界面刷新、日志写入属于软实时或非实时任务,可以放在 Linux 或低优先级任务中。混合架构中,MCU 负责采集与实时判断,Linux 主控负责交互与联网,两者通过 SPI、UART 或共享内存通信。

医疗可穿戴设备分层运行环境与调度关系 传感器 / 前端 ECG · PPG · IMU 温度 · 皮肤阻抗 MCU + RTOS / Zephyr 硬实时任务:采样、滤波 中断服务 + 高优先级任务 低功耗调度:Tickless 应用处理器 + 嵌入式 Linux 软实时:蓝牙、显示、上传 CFS 调度 + 实时补丁可选 电源管理:suspend / idle SPI/I2C UART/共享内存 任务优先级与调度策略(示例配置) 优先级 0:中断服务 优先级 1:ECG 采样 优先级 2:跌倒检测 优先级 3:数据打包 优先级 4:上传 抢占式调度:高优先级任务就绪即抢占低优先级任务;同优先级按时间片轮转 低功耗调度状态迁移 Run 运行 Idle 空闲 Sleep 睡眠 Deep 深度休眠 无任务 定时唤醒 长时间无事件 中断或定时器到期可将系统从任意低功耗状态唤醒,恢复时间随休眠深度增加

二、任务优先级:不是越高越好

在 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 的唤醒次数。

在混合架构中,MCU 可以长期处于 Tickless 休眠,由传感器中断唤醒;Linux 主控则可以在屏幕关闭后进入 suspend,仅保留 BLE 控制器低功耗广播。两者通过 GPIO 或 UART 唤醒信号协同,避免主控频繁启动。

五、一个可参考的调度配置示例

下面给出一个基于 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 负责交互和联网。无论哪种架构,调度设计都应遵循三条原则:中断快进快出、高优先级任务短而确定、空闲时真正休眠。这三条原则落实到位,医疗可穿戴设备才能在保证临床响应质量的同时,把功耗控制在可接受范围内。