联想嵌入式一面 9.8 base上海
- 轮次
- 一面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- SPI 的时序是怎样的?四种模式 CPOL/CPHA 怎么区分?主从模式如何配置?通信异常时要从哪些方向排查故障?
- I2C 的时序、起始与停止信号是怎么定义的?ACK/NACK 应答、7 位与 10 位地址有什么区别?仲裁、时钟拉伸、无应答这些异常情况怎么分析?
- FreeRTOS 的任务切换为什么放在 PendSV 异常里面执行?
- RTC tickless 低功耗模式如何实现?
- SPI 做从机时,CS 拉低到第一个时钟到来之间的间隔需要注意什么?
- GCC 的完整编译流程是什么?RW 段等各个段分别是什么含义?
- 聊一下你的个人发展规划?
《参考解析》
-
SPI 的四种模式与异常排查:CPOL 决定空闲时 SCK 的电平,CPHA 决定在第一个还是第二个时钟沿采样,两者组合出 Mode0~Mode3;主从必须配成同一模式,否则整体错一位。排查通信异常按「硬件—配置—时序」三层走:先看片选是否真正拉低、地线是否共地、上拉与走线长度是否带来过冲振铃;再核对模式、位序(MSB/LSB first)、数据宽度;最后用量逻辑分析仪抓波形,看第一个采样沿上的数据是否已经稳定。多从机场合还要检查 CS 的互斥与建立/保持时间。
-
I2C 的仲裁、时钟拉伸与 NACK:仲裁发生在多主机同时发起传输时,各主机逐位发送并回读 SDA,谁发出 1 而读到 0 就退出,赢家继续——这也是 I2C 必须开漏加上的原因。时钟拉伸是从机拉低 SCL 给自己争取处理时间,主机必须尊重而不能强推时钟。NACK 分两处:地址阶段无应答说明器件不在、地址错或没上电;数据阶段 NACK 通常是接收方缓冲区满、写保护(如 EEPROM 页写完)或寄存器不允许写。实战中还会遇到总线被某个掉电从机拉住 SDA 导致死锁,处理办法是发 9 个时钟把它顶出来,或者加总线复位器件。
-
任务切换为什么放在 PendSV:Cortex-M 里 PendSV 是专门留给操作系统的异常,优先级可以设到最低。这样安排两个好处:一是在中断服务程序里只需要挂起 PendSV,不立刻切换,等所有高优先级中断处理完、退出到线程模式之前再统一做上下文切换,避免打断中断的临界区;二是 PendSV 是可挂起的异常,多次
PendSV_Set只会置一次挂起位,不会像普通中断那样被重复触发。剩下的寄存器现场由软件在 PendSV 里压栈保存,硬件已自动保存了 xPSR、PC、LR、R12 和 R3~R0。 -
tickless 低功耗的实现:核心是停掉周期性的 SysTick,改成「算出下一个即将到期的任务唤醒时间,把低功耗定时器(RTC/LPTIM)设到那个时刻,然后进 sleep/stop 模式」。醒来后按实际经过的时间补偿 tick 计数,再跑一次任务调度;如果没有就绪任务,睡眠时间可以一直延长。要注意的坑:低功耗定时器的时钟源精度与溢出、唤醒后 tick 补偿不能丢、调试与串口等外设的时钟在低功耗模式下被关掉、以及进 stop 模式前的 IO 状态要处理,否则会有漏电。
-
CS 到第一个时钟的建立时间:SPI 从机一般把 CS 的下降沿当作帧同步,内部要在这之后锁存/预装载移位寄存器。如果主机在
tSU(CS)满足之前就把第一个 SCK 沿发出来,从机会丢掉第一位或采到位偏移。做法是查从机器件手册的 CS setup/hold 参数,主机侧在拉低 CS 后插入一小段延时再启动时钟,或降低首个时钟频率、把 CPHA 配成在第二个沿采样。软件模拟 SPI 时这段延时就是几条空指令,硬件 SPI 则可以靠分频和 FIFO 启动时序来保证。 -
GCC 编译流程与段布局:一次构建实际是四步——预处理(展开宏与头文件)、编译成汇编、汇编成目标文件、链接成可执行文件(
gcc -E/-S/-c),烧录前还要objcopy成 bin/hex。段的含义:.text是代码,.rodata是只读常量与字符串,.data(RW 段)是已初始化的全局/静态变量,.bss(ZI 段)是未初始化或初值为 0 的变量。RW 段要占两份空间——初值存在 Flash 里,启动时由启动文件的拷贝循环搬到 RAM;ZI 段不占 Flash,启动时清零。链接脚本决定各段的地址,栈与堆的大小也在这里给定。 -
个人发展规划类问题:回答时给出方向加理由,别只报职位名称。可以说清想在 MCU 与驱动这一层把基础打扎实、两三年的目标是能独立负责一个模块或一款产品的底层软件,并说明为什么选这个方向——比如喜欢能直接和硬件、现象打交道,排查问题有确定性。面试官问它主要是看稳定性和岗位匹配度,跟岗位无关的方向(比如准备做纯上层应用)不必强调。