大疆嵌入式一面面经
- 轮次
- 一面
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
- 多传感器数据采集系统中,不同采样率的传感器如何同时采集、打时间戳并保证时间对齐?丢帧或 CPU 繁忙时如何不丢数据?
- DMA 加环形缓冲区如何判断满和空?生产速度大于消费速度、DMA 写与 CPU 读并发时如何保证一致性?
- volatile 在中断、硬件寄存器、DMA 场景中什么时候必须使用?它能否保证线程安全?
volatile int count的count++是原子操作吗? - static 修饰全局变量、局部变量和函数分别有什么作用?static 局部变量存在哪里?
- const 与指针的几种写法有什么区别?哪个是指针不能改、哪个是数据不能改?哪些操作合法?
- 结构体内存对齐如何计算 sizeof?如何重新排列成员以减少结构体占用空间?
- 大小端是什么?如何用 C 代码判断当前 CPU 是大端还是小端?总线传输为什么需要关心字节序?
- 浮点数和定点数有什么区别?嵌入式控制系统为什么有时使用定点数?定点数扩大 1000 倍后如何恢复真实值?
- 如何用位操作实现寄存器指定位置 1、清零、翻转和连续位设置,且不影响其他位?
- 一个中断从触发到进入 ISR 中间发生了什么?中断嵌套、优先级和 ISR 设计要注意什么?
- DMA 与 CPU 同时访问同一内存会不会冲突?有 Cache 时为什么要 Clean 和 Invalidate?
- I2C 和 SPI 应该如何选择?
- 固定窗口滑动平均滤波器如何实现并优化?
《参考解析》
- 多传感器时间对齐与不丢数据:不同采样率的通道要各留一条缓冲队列,采集侧只负责把「数据 + 硬件时间戳」压进队列,融合侧按时间戳做最近邻或插值对齐;时间戳最好来自同一个硬件计数器,用系统时间会引入调度抖动。不丢数据靠的是缓冲区水位而不是运气:给每个通道留足余量,快满时优先丢最旧的非关键帧并计数上报,CPU 繁忙导致的溢出必须能被观测到,否则只能事后猜。中断只做搬运、解析和业务处理放到任务里,是保证 CPU 繁忙时仍能收数的最常见做法。
- DMA 环形缓冲区的满空判断:环形缓冲区不能只用读写指针相等判空,因为满的时候它们也相等,常用办法是牺牲一个槽位(写指针 +1 等于读指针即满)、或者单独维护计数器。并发场景下指针的读写要分清所有权:DMA 侧通常只更新写指针,CPU 侧只更新读指针,各自读对方的指针时要加
volatile和内存屏障,必要时用双缓冲或者半传输中断降低竞争。生产快于消费时缓冲区一定会满,设计上要么提高消费优先级、要么明确丢弃策略,别指望靠加锁解决。 - volatile 的边界:
volatile告诉编译器这个值可能被程序之外的东西改动,每次访问都必须真的读写内存、不许把它缓存进寄存器或优化掉重排。所以中断里改的标志、映射到内存的硬件寄存器、DMA 会写的内存都该加它——但加了volatile的count++依然不是原子操作,它至少是读、加、写三步,多核或中断与主流程并发时仍会丢更新,要原子性得用关中断、原子指令或者互斥量。面试官常追问「volatile 和内存屏障的区别」,答案是前者约束编译器、后者约束 CPU 与编译器的重排序。 - static 的三种用法:修饰全局变量和函数是把链接属性收成内部链接,只在该编译单元内可见,避免重名冲突,也让接口边界清晰;修饰局部变量是改变生命周期——它在静态存储区只初始化一次,函数退出后值仍然保留。static 局部变量存在数据段而不是栈上,所以它不可重入,中断或递归里使用要格外小心,多任务环境下还要考虑是否需要加锁。
- 内存对齐与结构体排布:每个成员相对结构体起始地址的偏移必须是自身对齐数的整数倍,结构体总大小再补齐到最大成员对齐数的整数倍,成员顺序不同会得到不同的 sizeof。减少占用最有效的手段是把成员按对齐数从大到小排列,把
char、bool这类小成员集中放在一起,必要时用#pragma pack或__attribute__((packed))压紧——但压紧会带来非对齐访问,在部分架构上要么性能下降要么直接异常,协议报文解析时用才划算。 - 大小端的判断与传输:小端把低字节放在低地址,大端相反。运行时判断最简单的写法是取一个多字节变量的首字节:
int x = 1;判断*(char *)&x是不是 1。总线传输关心字节序是因为通信双方可能不同架构,协议一般约定网络字节序(大端),发送前用htons这类函数转换,多字节寄存器的位域定义也要跟手册核对。 - 中断流程与 ISR 设计:从中断源置位、控制器按优先级裁决、保存现场、查向量表跳到 ISR,到执行完返回并恢复现场,中间可能还有流水线冲刷与延迟。ISR 的原则是短——只清标志、读关键数据、投递给任务,不能阻塞、休眠、做浮点运算或调用不可重入函数;嵌套与优先级要按实时性排,高优先级中断尽量不被打断,共享数据用关中断或者无锁的单生产者单消费者队列保护。
- DMA 与 Cache 的一致性:DMA 是绕过 CPU 直接访问内存的外设,它不经过 Cache,于是会出现 Cache 里还是旧值、内存里已经是新数据的情况。原则是方向决定操作:CPU 写好缓冲区交给 DMA 发送前要 Clean(把 Cache 刷回内存),DMA 收完数据交给 CPU 读之前要 Invalidate(让 Cache 失效重新从内存读)。缓冲区最好按 cache line 对齐并放在非缓存区域,否则一次 Clean 会把相邻数据一起写回,踩到别的变量。