面灵AI→

27 届嵌入式软件开发必备八股文:20 道高频题与复习顺序

时间
2026-10
来源
牛客网

《面试题目》

  1. volatile 在嵌入式里哪些场景必须用?不加通常会出现什么后果?
  2. const int *p、int * const p、const int * const p 有什么区别?
  3. 结构体内存对齐规则是什么?为什么要对齐?#pragma pack 有什么代价?
  4. 堆和栈的区别是什么?嵌入式里栈溢出常见现象有哪些,怎么预防?
  5. 大小端是什么?如何判断当前平台是大端还是小端?
  6. 上电复位到进入 main 之间,MCU 一般做了哪些事?
  7. 中断服务函数里能做什么、不能做什么?为什么不宜随意 printf/malloc?
  8. NVIC 抢占优先级和响应优先级有什么区别?和临界区有什么关系?
  9. HardFault 发生后,你会先看哪些寄存器?常见根因有哪些?
  10. 轮询、中断、DMA 三种数据获取方式如何取舍?
  11. UART 丢数据的常见原因有哪些?你会怎么定位?
  12. I2C 和 SPI 的核心差异是什么?各自适合什么场景,怎么选型?
  13. I2C 为什么通常要上拉?软件 I2C 和硬件 I2C 怎么选?
  14. SPI 的 CPOL/CPHA 四种模式怎么理解?收发时序如何描述?
  15. SPI 配合 DMA 时,有 Cache 的平台为什么要做 Clean/Invalidate?
  16. CAN 总线仲裁机制是什么?标准帧和扩展帧有什么区别?
  17. FreeRTOS 里任务有哪些状态?调度是怎么触发的?
  18. 信号量、互斥量、消息队列分别适合什么场景?
  19. 什么是优先级反转?优先级继承是怎么缓解的?
  20. Bootloader 跳转到 App 前通常要完成哪些关键步骤?OTA 断电如何尽量避免变砖?

《参考解析》

C 语言内存观:volatile 保证每次都从内存读写,防止编译器把变量缓存到寄存器或优化掉,适合硬件寄存器、ISR 与主循环共享变量、DMA 缓冲区;它不保证原子性和内存屏障。const int *p 是指向常量的指针,int * const p 是常量指针,const int * const p 两者都不可变。结构体对齐按成员对齐数和最大对齐数计算,#pragma pack 能省空间但可能带来非对齐访问的性能损失甚至异常。

启动、中断与异常:上电后 MCU 从复位向量取栈顶和复位处理函数,初始化时钟、看门狗、内存段(.data 从 Flash 搬到 RAM、.bss 清零),再跳 main。ISR 要短,不能阻塞、不能随意 printf/malloc,因为重入、堆锁和耗时都会影响实时性。NVIC 抢占优先级决定能否打断当前 ISR,响应优先级只在同时挂起时决定先后。HardFault 先看栈帧里的 PC、LR、xPSR 和 CFSR/HFSR/MMFAR/BFAR,常见根因是空指针、越界、非对齐、栈溢出和非法指令。

数据获取与总线:轮询简单但占 CPU,中断实时但频繁打断,DMA 适合大块/高速数据且 CPU 不参与搬运,三者常组合使用。UART 丢数据看波特率误差、FIFO 溢出、中断延迟、DMA 配置、流控和线缆干扰。I2C 两线、半双工、有地址和 ACK,适合低速多从机;SPI 四线、全双工、无地址,靠片选,适合高速。I2C 开漏输出必须上拉;软件 I2C 灵活但占 CPU,硬件 I2C 稳定但受外设限制。SPI 的 CPOL/CPHA 决定空闲电平和采样边沿,四种模式要和从机手册一致。带 Cache 的平台做 DMA 前要 Clean(把 CPU 写的数据刷到内存),DMA 后要 Invalidate(丢掉 CPU 缓存里的旧数据)。

RTOS 与 Bootloader:FreeRTOS 任务有运行、就绪、阻塞、挂起等状态,调度由 SysTick、中断唤醒和任务主动让出触发。信号量做同步/计数,互斥量保护共享资源并支持优先级继承,消息队列传数据。优先级反转的解法是优先级继承和天花板。Bootloader 跳转前要关中断、关外设、设置 MSP、检查 App 向量表、跳转到复位处理函数;OTA 要双分区、校验签名、断电保护、回滚和看门狗,避免升级中断变砖。