第二章:嵌入式系统基础:微控制器选型、RTOS概念、起搏器中的实时性要求

好,咱们正式开始聊干货。这一章是地基,地基打不牢,后面盖楼全得塌。我见过太多项目,选型拍脑袋,RTOS 随便挑一个,最后调试到崩溃。起搏器这东西,不是手机,死机了重启就行。它死机,人就没了。所以,这一章咱们得把话说透。

2.1 微控制器选型:不是选最贵的,是选最对的

选 MCU,说白了就是一场权衡。性能、功耗、外设、成本、供货周期,哪个都不能少。我个人习惯,先列需求清单,再去找芯片。

2.1.1 起搏器的核心需求

起搏器对 MCU 的要求,其实很苛刻。你想想看,它要泡在体液里,几十年不能换电池。所以,第一要义是 超低功耗。第二是 高可靠性,不能有逻辑错误。第三是 实时响应,心脏跳不跳,它说了算。

具体到参数,我一般会关注这几个点:

  • 工作电压:通常 1.8V - 3.3V,越低越好,直接关系到电池寿命。
  • 待机电流:μA 级别,甚至 nA 级别。起搏器大部分时间在“听”,不干活。
  • 唤醒时间:从休眠到全速运行,必须在微秒级。心脏可不等你开机。
  • 外设集成度:ADC(感知心脏电信号)、定时器(精确计时)、SPI/I2C(与传感器通信),最好片上集成,省电省空间。

核心指标速查表

参数 起搏器要求 普通消费级
待机功耗 < 1 μA 10-100 μA
唤醒时间 < 2 μs 10-100 μs
工作温度 37°C 恒温 -40°C ~ 85°C
安全认证 ISO 13485, IEC 62304 无强制要求

2.1.2 主流架构对比

目前起搏器领域,ARM Cortex-M 系列是绝对的主流。尤其是 Cortex-M0+ 和 M4。M0+ 功耗极低,适合做纯控制。M4 带 DSP 和 FPU,适合做复杂的信号处理,比如感知心内心电图。

我在项目中遇到过一个问题:选了一款 M4 芯片,性能确实强,但待机功耗死活降不下去。后来发现,是它的 LDO(低压差线性稳压器)在休眠模式下漏电。嗯,这里要注意,数据手册上的“典型值”往往是最理想情况,你得看“最大值”

还有 RISC-V,这几年势头很猛。开源、灵活、授权费低。但说实话,在医疗领域,生态还不够成熟。你想想看,一个起搏器要过 FDA 认证,芯片的 errata(勘误表)必须清清楚楚。RISC-V 的 IP 核五花八门,你敢用吗?我个人建议,保守一点,选 ARM

2.2 RTOS 概念:为什么起搏器需要它?

很多人觉得,起搏器逻辑简单,一个超级循环就够了。我刚开始也这么想。直到我处理一个需求:既要精确计时 1ms 的起搏脉冲,又要实时响应心室的感知事件,还要定期跟体外程控仪通信。

一个 while(1) 循环,你怎么保证 1ms 的定时不被通信打断?用中断?中断多了,优先级搞死你。这时候,RTOS 的价值就出来了。

2.2.1 什么是 RTOS?

RTOS,实时操作系统。它跟 Linux 那种“分时系统”不一样。分时系统追求“公平”,每个人都能用一会 CPU。RTOS 追求“确定性”,我说 1ms 响应,就必须 1ms 响应,晚 1μs 都不行。

它的核心是 任务调度器。你把不同的功能拆成独立的任务:

  • 感知任务:最高优先级,一旦检测到心脏自主搏动,立刻响应。
  • 起搏任务:次高优先级,负责发放起搏脉冲。
  • 通信任务:低优先级,跟体外程控仪交换数据。
  • 诊断任务:最低优先级,跑自检、记录日志。

调度器保证:高优先级任务随时可以抢占低优先级任务。这样,心脏事件来了,感知任务能立刻拿到 CPU,不会被通信任务耽误。

我的经验:起搏器里,任务数量不要超过 5 个。任务多了,上下文切换的开销就大了,反而影响实时性。我曾经见过一个团队,拆了 12 个任务,最后调度器自己把自己跑死了。

2.2.2 常见的 RTOS 选型

起搏器领域,FreeRTOS 是首选。为什么?因为它简单、可靠、代码量小。整个内核就几个 .c 文件,你能读得完。而且它通过了大量的安全认证,比如 IEC 61508。

其他选项:

  • uC/OS-II:老牌 RTOS,文档齐全,但需要商业授权。
  • RT-Thread:国产之光,生态丰富,但在医疗领域的案例还不够多。
  • 裸机 + 状态机:对于极简单的单腔起搏器,其实也可以。但一旦复杂度上来,维护成本指数级增长。

我个人习惯,能用 FreeRTOS 就用 FreeRTOS。别自己造轮子,起搏器不是练手项目。

2.3 起搏器中的实时性要求:硬实时,没得商量

实时性分两种:硬实时软实时。软实时,比如视频播放,卡顿一下,用户骂一句,但死不了人。硬实时,比如起搏器,晚 10ms 响应,患者可能就晕厥了。

起搏器是典型的 硬实时系统。它的时间约束是绝对的,不是统计意义上的。

2.3.1 关键时间参数

起搏器有几个核心的时间参数,你必须刻在脑子里:

  • 起搏间期 (Pacing Interval):比如 800ms。这意味着,从上一个起搏脉冲开始,到下一个起搏脉冲,最多等 800ms。如果 800ms 内没有感知到心脏自主搏动,必须立刻发一个脉冲。
  • 感知空白期 (Blanking Period):起搏脉冲发出后,有几十毫秒的空白期。这段时间内,感知电路会被屏蔽,防止被起搏脉冲本身误触发。
  • 不应期 (Refractory Period):感知到心脏事件后,有一段时间不响应新的感知事件,防止被 T 波误触发。

这些时间,都是用 硬件定时器 来保证的。RTOS 的软件定时器,精度不够,也不可靠。

避坑指南:我曾经犯过一个错误。用 RTOS 的软件定时器来做起搏间期计时。结果发现,当系统负载高时,定时器回调被延迟了 5ms。5ms 啊,在起搏器里就是天大的事。从那以后,所有跟心脏节律相关的时间,我全部用硬件定时器,并且放在最高优先级的中断里处理。

2.3.2 如何保证实时性?

保证实时性,不是靠嘴说,是靠设计。我总结了几条铁律:

  1. 中断优先级要绝对明确:心脏感知中断 > 起搏定时器中断 > 通信中断 > 其他。中断嵌套要控制好,最好只嵌套一层。
  2. 临界区要短:关中断的时间,不能超过 10μs。否则会影响其他中断的响应。
  3. 任务优先级要静态分配:不要动态调整优先级。动态优先级在起搏器里是灾难,你无法预测它什么时候会变化。
  4. 避免优先级反转:低优先级任务拿了锁,高优先级任务等锁,中间优先级任务抢 CPU。这是 RTOS 的经典问题。解决办法:用优先级继承协议,或者干脆不用锁,用消息队列。

举个例子,感知事件的响应流程:

// 伪代码:感知中断服务函数
void P_Sense_IRQHandler(void) {
    // 1. 读取硬件时间戳
    uint32_t timestamp = TIM_GetCounter();

    // 2. 清除中断标志
    P_Sense_ClearFlag();

    // 3. 发送消息到感知任务(不处理复杂逻辑)
    osMessageQueuePut(SenseQueue, ×tamp, 0, 0);

    // 4. 退出中断,让调度器决定何时运行感知任务
}

你看,中断里只做最必要的事:读时间戳、清标志、发消息。剩下的逻辑,交给任务去处理。这样,中断的占用时间极短,不会影响其他实时事件。

2.4 小结

这一章,我们聊了 MCU 选型、RTOS 概念,还有起搏器的实时性要求。说白了,就是一句话:选对芯片,用好 RTOS,死磕时间确定性

下一章,我们会深入起搏器的核心——状态机设计。那是起搏器的灵魂,也是很多工程师翻车的地方。做好准备,咱们继续。