2. 实时操作系统(RTOS)基础:任务调度、优先级、中断管理
做运动控制这些年,我越来越觉得RTOS是绕不开的坎。你想想看,一个伺服驱动器里同时要处理电流环、速度环、位置环,还得兼顾通讯和故障保护——裸机轮询根本忙不过来。这时候,RTOS就是那个帮你把时间掰成几瓣用的管家。
说白了,RTOS的核心就三件事:任务怎么切换、谁先跑、中断来了怎么办。咱们一个一个聊。
2.1 任务调度:谁该干活了?
任务调度是RTOS的发动机。我习惯把它理解成「排队买饭」——有人急着赶火车(高优先级),有人只是闲逛(低优先级),调度器就是那个维持秩序的大妈。
核心调度策略:
- 抢占式调度:高优先级任务随时可以打断低优先级任务。运动控制里电流环必须用这个,否则电流过冲会烧MOS管。
- 时间片轮转:同等优先级的任务轮流跑,每人分一个时间片。适合按键扫描、LED刷新这类不紧急的活。
- 协作式调度:任务主动让出CPU。嗯,这个在工业控制里很少用,我见过有人用它做Bootloader。
我在项目中遇到过一个问题:两个任务共享一个全局变量,调度器在中间切了一下,数据就乱了。后来加了互斥锁才解决。记住:共享资源不加锁,调试两行泪。
2.2 优先级:谁说了算?
优先级是RTOS的命门。设高了,低优先级任务饿死;设低了,实时性保不住。我个人习惯遵循「紧急程度决定优先级,而非重要性」这个原则。
| 任务类型 | 推荐优先级 | 说明 |
|---|---|---|
| 电流环控制 | 最高(如 5) | 微秒级响应,不可被打断 |
| 速度环/位置环 | 高(如 4) | 百微秒级,可被电流环抢占 |
| 通讯任务(CAN/EtherCAT) | 中(如 3) | 毫秒级,丢包可重传 |
| 状态监测/日志 | 低(如 1) | 不紧急,有空再跑 |
避坑指南:我曾经把通讯任务优先级设得比电流环还高,结果电机在高速运行时电流环被频繁打断,导致转矩波动。后来花了三天才定位到问题——优先级反转害死人。
2.3 中断管理:紧急通道怎么走?
中断是RTOS里最特殊的存在。它不归调度器管,直接由硬件触发。我常说:中断里别干重活,就像急诊室只做急救,不做手术。
中断处理分两段:
- ISR(中断服务函数):只做最紧急的事,比如读寄存器、清标志位。时间控制在10微秒以内。
- 下半部处理(如FreeRTOS的任务通知):把数据扔给任务去慢慢算。这样既保证了实时性,又不阻塞其他中断。
举个例子,编码器Z信号中断来了:
// ISR —— 只做最少的活
void Z_Signal_ISR(void) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
// 记录脉冲计数值
g_z_pulse_count = TIM1->CNT;
// 通知处理任务
vTaskNotifyGiveFromISR(xHandleTask, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
// 任务 —— 处理具体逻辑
void PositionTask(void *pvParameters) {
while(1) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
// 这里做归零、误差补偿等耗时操作
CalculateHomePosition(g_z_pulse_count);
}
}
我的经验:中断优先级不要和任务优先级混为一谈。中断优先级由NVIC控制,任务优先级由RTOS控制。两者独立,但中断永远比任务快。所以,能用中断解决的实时问题,别用任务。
2.4 知识体系总览
下面这张图是我自己梳理的RTOS核心脉络。你看,调度、优先级、中断三者环环相扣——调度器决定谁跑,优先级决定谁先跑,中断则提供了一条硬件级别的快车道。
你看,从硬件中断到任务调度,再到优先级裁决,整个链路环环相扣。任何一个环节出问题,运动控制的周期抖动就会直接反映在电机轴上——轻则噪音,重则丢步。
一句话总结:RTOS不是银弹,但它给了你一把管理实时性的尺子。用好了,周期抖动可控;用不好,比裸机还糟。我见过太多人把RTOS当裸机用,结果该抖还是抖。
嗯,这一节就聊到这儿。记住:调度是骨架,优先级是灵魂,中断是加速器。三者缺一不可。