理想汽车 嵌入式软件二面面经:多传感器帧格式、SPI/I2C 资源冲突与 OTA
- 轮次
- 二面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 自我介绍
- 重点介绍一下实习经历和项目:部门几个人,如何分工的?你负责项目的哪一部分?
- 项目中多传感器采集的数据是什么格式?自定义帧的格式吗?
- 如果 XX 传感器和通信任务同时访问 SPI、I2C,怎么解决资源冲突?
- MQTT 数据报文大概是什么结构?抓过 MQTT 包吗?一个数据包大概多少字节?
- 调试 XX 控制器的时候,Modbus RTU 具体怎么通信的?怎么判断数据有没有问题?
- 项目 OTA 具体实现过程?MCU 的启动流程。
- 如果 EEPROM 突然读不到了,你是怎么排查的?
- 项目 MCU 如何选型的?ARM Cortex-M 中常见的寄存器有哪些?
《参考解析》
-
自定义帧格式要按字段逐个说清作用:一个可用的设计是「帧头 + 设备 ID + 数据类型 + 数据长度 + Payload + CRC」——帧头用于同步和判断一帧的开始,设备 ID 区分数据来源,数据类型区分压力、温度、GPS 等不同量,长度字段决定 Payload 边界(也是解析时防止越界的关键),CRC 用来发现传输错误。答题时最好顺着「传感器原始数据 → 数据解析 → 内部数据结构 → 自定义通信帧 → 上层传输」这条链路讲,并强调原始数据格式与通信帧格式是两回事,不要混着说。
-
共享总线的资源冲突,核心是互斥加临界区尽量短:多个 FreeRTOS 任务访问同一条 I2C 或 SPI 时,用 Mutex 保护整个「开始传输到完成」的过程,用完立刻释放,绝不能持锁做长计算或阻塞等待。SPI 还要额外注意片选(CS)的管理,避免一个任务在传输中途被另一个任务切走导致片选错乱。如果中断服务程序也访问同一总线,就要设计 ISR 与任务之间的同步方式(信号量、消息队列或把实际访问推到任务上下文)。被追问 Mutex 与二值信号量的区别时要点明:Mutex 用于资源互斥且支持优先级继承,能缓解优先级反转;二值信号量用于同步和事件通知。
-
MQTT 与 Modbus RTU 要答到协议结构这一层:MQTT 控制报文由固定头、可变头、Payload 三段组成,固定头里有报文类型和剩余长度(剩余长度用变长编码),并不是每种报文都有可变头和 Payload;实际报文大小取决于 Topic 长度与 Payload 大小,传感器业务常见几十字节量级,再叠加 TCP/IP 的额外开销。Modbus RTU 是主从模式,主站发请求、从站按从站地址与功能码响应,典型帧是「从站地址 + 功能码 + 数据 + CRC」,读寄存器就是地址加寄存器数量。判断数据有没有问题要按层次排:RS485 电平 → UART 参数(波特率、校验位)→ 帧格式 → 从站地址 → 功能码 → 数据长度 → CRC → 业务解析,逐层定位比直接猜协议强。
-
OTA 与 MCU 启动流程可以放在一起答:OTA 的链路是获取升级通知、下载固件、写入升级区域、做完整性校验(CRC 或签名)、置升级标志、重启、Bootloader 检查新固件、跳转或回滚。A/B 分区方案的好处是新固件验证通过后再切换,失败还能退回旧分区,代价是 Flash 空间翻倍。Cortex-M 的启动流程是上电或复位后从向量表取初始 SP 与复位向量,进入 Reset_Handler,初始化运行环境(.data 从 Flash 复制到 RAM、.bss 清零),调用 SystemInit,最后进 main;带 Bootloader 时中间多一步判断 App 是否有效再跳转。
-
EEPROM 读不到的排查顺序是「硬件 → 总线 → 地址 → 时序 → 软件」:先用万用表确认供电、SDA 与 SCL 电平以及上拉电阻;再用逻辑分析仪抓一次完整事务,看 START、设备地址、ACK、寄存器地址、数据、STOP 停在哪一步。地址阶段就没有 ACK,优先查硬件、电源、地址配置(注意 7 位地址与读写位的区别)和总线电平;能 ACK 但读回数据不对,就查寄存器地址、读写时序、数据长度以及 EEPROM 的写周期等待(写操作后需要等待内部擦写完成,期间不响应)。这条路径的价值在于先判断问题出在硬件、协议还是驱动,而不是盲目改代码。
-
选型与寄存器是「基础知识有没有体系」的考察点:MCU 选型按功能需求 → CPU 性能与主频 → RAM、Flash → 外设资源(UART、SPI、I2C、CAN、ADC、DMA、定时器、中断数量)→ 实时性 → 功耗 → 封装 → 成本 → 供货与开发生态排序,并且每一项都要能对上项目的具体约束(比如采集频率决定主频与 DMA 需求、量产周期决定供货风险)。Cortex-M 有 16 个 32 位核心寄存器,R0 到 R12 是通用寄存器,R13 是栈指针、R14 是链接寄存器、R15 是程序计数器,另外还有 xPSR 等状态寄存器;答的时候最好点出 MSP 与 PSP 的区分、以及异常进出的硬件自动压栈,这些细节比背寄存器名字更能体现理解。