面灵AI→

中控技术嵌入式开发(系统软件)面经:FreeRTOS 任务设计与 Modbus RTU 通讯

时间
2026-10
来源
牛客网

《面试题目》

自我介绍与背景

  1. 简单做一下自我介绍。
  2. 你有没有做过驱动相关的工作?
  3. 你日常开发主要偏向驱动还是应用?

FreeRTOS 控制器项目深挖

  1. 基于 FreeRTOS 的控制器开发项目,是你个人完成还是几个人合伙?
  2. 硬件是买的开发板吗?还是自己做的?
  3. 底层驱动需要你自己调吗?还是拿开发板自带的直接用?
  4. 买开发板时配套的教程、基础源码你用了吗?用这些驱动时出过问题吗?
  5. 你在这个控制器里具体做了哪些功能?
  6. 你设计了几个任务?哪个优先级最高?哪个最低?
  7. 看门狗任务的优先级是多少?
  8. 这些任务的优先级为什么这么设定?是怎么考虑的?
  9. 升级过程不需要监控吗?没有心跳?
  10. 如果任务卡死了,靠什么触发软复位?由谁来判断?
  11. 那个时间判断是在任务本身做,还是在别的任务里做?
  12. 如果任务自己卡死了,它怎么自己监控自己?

Modbus RTU 与 485 通讯

  1. Modbus RTU 你应该知道吧?
  2. 485 有收发控制,一般通过什么事件控制收转发、发转收?讲一下逻辑。
  3. TC 这一位代表什么?是最后一个字节传完了,还是已经填到计数器里了?你确认吗?

FreeRTOS 任务函数耗时测量

  1. 在 FreeRTOS 工程下,要测某个任务里某个函数的执行时间,有哪几种方式?
  2. 这个时间戳是在哪里增加的?是软件驱动还是硬件驱动的?
  3. 你说 CPU 内部计数器,那多任务场景下要严格测函数的完整执行时间,是不是还要考虑任务切换和调度?
  4. 如果要考虑调度和其他干扰,应该怎么做?

Linux 与 AI 单元测试

  1. 你有 Linux 开发经验,Linux 上主要做哪些事情?
  2. 你用 AI agent 做单元测试,效果怎么样?测出来的结果可信吗?
  3. 你现在是在实验室吗?

岗位适配与收尾

  1. 你有哪些问题需要了解?
  2. 面试官介绍岗位后反问:DCS 行业嵌入式工作强度有点大,你心理预期怎么样?能接受吗?

《参考解析》

  1. 任务划分与优先级怎么定:优先级不是按「哪个功能重要」排,而是按截止期和实时性排——硬实时的外设收发、控制输出、采样这类错过就有后果的任务放最高;控制计算与状态机次之;上报、日志、OTA、参数存取这类可以容忍延迟的放最低,被前面任意任务抢占。FreeRTOS 里数值越大优先级越高,同优先级默认按时间片轮转;如果控制环是固定周期的,可以照速率单调的思路——周期越短优先级越高。要主动交代的是共享资源的处理:跨任务访问同一外设或缓冲区用互斥量而不是二值信号量,让优先级继承机制抑制优先级反转;中断服务里只做置位、发信号这类短操作,用 FromISR 版 API,把耗时处理交给任务。
  2. 看门狗任务的优先级与位置:看门狗任务本身得能被及时调度到,所以一般放较高优先级,但也不能高到把实时任务饿死。它的职责是收集各任务上报的心跳计数或时间戳,统一判断后决定要不要喂硬件狗。要强调一点:如果把喂狗放在最低优先级的任务里,一旦上面某个任务卡死,这个任务照样会按时喂狗,硬件看门狗就形同虚设。
  3. 任务卡死与软复位由谁判断:判断者不能是被监控者自己——一个任务自己死循环或者阻塞住了,它没有任何机会去上报「我卡了」,所以必须由另一个任务或定时器中断来看它的最后活动时间戳,超时就触发 NVIC_SystemReset() 软复位,或者先尝试只重启相关模块。硬件层面还有独立看门狗(IWDG)兜底,它由独立时钟驱动,主逻辑整体跑飞时靠它复位。要补一句局限:如果任务仍在被调度、只是逻辑上有问题(比如每轮都做无用功),单纯的时间戳看不出异常,得让它每轮上报「进度」而不是只报「我还活着」。
  4. Modbus RTU 与 485 的收发方向控制:RS-485 是半双工差分总线,收发共用一对线,方向由 DE/RE 引脚控制。切换时机是这道题的核心:发送前拉高 DE 进入发送态,写数据到 UART,等**发送完成(TC,Transmit Complete)**再切回接收态,因为 TC 才表示最后一个字节已经从移位寄存器完全送上线、总线空闲;如果只等 TXE(发送数据寄存器空)就切,最后那个字节还在移位寄存器里没发完,就会被截断。实现上可以走「TC 中断里翻转 DE」,也可以用 DMA 发送加传输完成中断,部分 MCU 自带 RS485 模式由硬件自动翻转。往上还有协议层的活:用 3.5 个字符时间的总线空闲判帧结束、CRC 校验、超时重传和主从轮询节拍。
  5. FreeRTOS 下测函数执行时间:常用的有几种,各有取舍。① 读 CPU 周期计数器(Cortex-M 的 DWT->CYCCNT)前后取差值,精度最高、开销最小;② 用系统时间戳,比如 xTaskGetTickCount(),但精度受 tick 周期限制;③ GPIO 翻转加逻辑分析仪或示波器,对被测代码侵入小、还能看到波形;④ 打开 FreeRTOS 的运行时统计(configGENERATE_RUN_TIME_STATS)看各任务的 CPU 占用,但它到不了单个函数的粒度;⑤ 用 SystemView、Tracealyzer 这类 trace 工具;⑥ 把纯逻辑抽出来在主机上跑 benchmark。至于时间戳的软硬件之分:CYCCNT 是 CPU 内部的硬件周期计数器,SysTick 与 RTOS tick 是软件计数,精度和抖动完全不同。
  6. 多任务下的干扰怎么处理:直接读计数器测到的是挂钟时间——函数执行期间如果被高优先级任务抢占、被中断打断,这段时间都会算进去,所以它不等于函数自己消耗的 CPU 时间。要严格测量有两种思路:一是排除干扰,把测量区间放进临界区关中断(taskENTER_CRITICAL)或者把当前任务临时提到最高优先级且保证不阻塞,代价是会拉长中断延迟、改变系统时序,测完必须恢复,且不适合测长函数;二是把干扰量化扣掉,用带上下文切换记录的 trace 工具,把被抢占的时间段减掉,或者用 CPU 周期计数配合 trace 事件统计。更实用的做法是分两类各测一次——「含调度的挂钟延迟」用于评估实时性,「纯执行时间」在关中断或单任务环境下测,两边一起看才能判断问题出在函数本身还是被抢占太频繁。
  7. Linux 上主要做什么:常见几块——写和维护内核驱动或字符设备、应用层服务(网络、串口、进程管理)、用 Buildroot/Yocto 做交叉编译与系统裁剪、启动流程与文件系统打包、以及调试(gdb、strace、perf、dmesg、ftrace)。回答时最好落到自己真做过的具体事和踩过的坑,别只报名词。
  8. AI agent 做单元测试可信吗:可以当补充手段,不能直接当验收依据。风险有三点:模型容易顺着实现写用例,把实现当成规范,实现错了用例也跟着错;为了让测试通过,它有时会去改断言或加特判;嵌入式代码里被 mock 掉的寄存器时序、并发与硬件行为,恰恰是最容易出问题的地方,mock 掉就等于不测。可行的用法是把 AI 用在生成边界用例、补齐回归脚手架、把已有用例改写成新框架这类低风险环节,断言必须能追溯到需求或协议文档而不是实现,覆盖率只当参考指标,关键路径仍然要在板或 HIL 上验。用例进主干之前要人工评审。
  9. 岗位适配与反问:被问到「强度大能不能接受」时,具体比表态有用——可以问清楚典型项目的交付节奏、是否需要驻场或出差、on-call 与加班的大致情况,再结合自己的预期给出明确回答,含糊的「能接受」反而显得没准备。反问环节可以问团队做的方向(DCS 里偏控制器、IO 模块还是上位通信)、新人培养与导师安排、技术栈与代码规范、以及考核与晋升的节奏。