1. 第二段实习的通信链路为什么用UDP不用TCP实际遇到过丢帧吗我们项目选用 UDP主要是业务传输 IMU、图像这类实时传感器数据对时延和抖动要求高。TCP 的重传、拥塞控制会带来不确定延迟而且旧帧重传回来已经失效。UDP 无连接开销小、延迟稳定还支持组播。可靠性我们在应用层自己实现序号、校验。 实际遇到过丢帧大多是接收缓冲区不足、瞬时流量超限、UDP 大包 IP 分片导致。处理方式限制单包大小调大网卡缓冲区接收线程高优先级传感器流丢帧不重传关键指令上层做可选重传。2. 描述I2C帧格式地址是几位如何识别读写两根线都拉低是什么情况如何解决出现这种情况多吗怎么判断连没连上I2C 由 SDA、SCL 两根线。帧顺序起始 S → 从机地址字节 → ACK → 数据 ACK → 停止 P。 常用 7 位从地址字节最低位是读写位0 写 1 读。 两根线同时拉低是 I2C 总线死锁一般是通信中途异常从机钳住 SDA 无法释放。解决方法用 bit-bang 方式输出 9 个时钟脉冲让从机释放总线再发停止信号也可以复位从机。正常稳定业务场景死锁不常发生断电或者程序跑飞时容易触发。 判断设备是否连接主机发送起始信号发送从机写地址等待 ACK收到 ACK 代表设备在线NACK 代表不存在或者接线故障。3. FreeRTOS任务调度机制时间片轮转的任务切换通过什么方式实现调度通过什么触发pendsv由什么触发为什么需要pendsvFreeRTOS 是抢占式优先级调度同优先级开启时间片轮转。时间片轮转依靠 SysTick 定时器中断时间片到期触发切换。调度触发来源SysTick 中断、外部中断或者任务调用 vTaskDelay、taskYIELD、队列信号量 API。PendSV 通过置位 NVIC 的 PendSV pending 标记触发portYIELD 函数会置位它。PendSV 优先级最低用来延迟执行上下文切换保证所有中断处理完成之后才做任务切换避免在中断嵌套过程中切换上下文防止系统异常。4. 任务有几个状态运行态到就绪态的切换条件FreeRTOS 任务四个状态运行、就绪、阻塞、挂起。 运行态转到就绪态两种情况同优先级时间片耗尽SysTick 中断触发轮转时间片到当前任务被切走放回就绪队列。高优先级任务就绪抢占当前任务低优先级正在跑高优先级任务就绪抢占 CPU旧任务回到就绪。任务调用taskYIELD()主动放弃 CPU任务在代码里主动调用taskYIELD()自愿交出 CPU。5. 创建任务需要提供哪些内容返回什么动态创建还是静态创建栈在哪里1. 创建任务需要提供哪些参数xTaskCreate函数原型BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 1. 任务函数入口 const char * const pcName, // 2. 任务名字调试用字符串 const configSTACK_DEPTH_TYPE usStackDepth, //3. 栈深度单位word不是byte void * const pvParameters, //4. 传给任务函数的入参 UBaseType_t uxPriority, //5. 任务优先级 TaskHandle_t * const pxCreatedTask//6. 任务句柄输出可以传NULL不保存 );需要提供内容任务函数指针任务入口返回 void参数 void*任务名称字符串任务栈深度以word为单位不是字节任务函数参数任务优先级任务句柄指针用来接收句柄不需要就填 NULL2. 返回什么返回值类型BaseType_tpdPASS任务创建成功pdFALSE创建失败最常见堆内存不足栈申请失败注意任务句柄是输出参数不是返回值用来后续操作任务vTaskDelete、vTaskSuspend 等。3. 动态创建还是静态创建xTaskCreate动态创建任务控制块 TCB 任务栈都从 FreeRTOS 堆pvPortMalloc动态分配。删除任务时内存会在空闲任务里自动回收。xTaskCreateStatic静态创建需要用户预先定义好静态数组任务栈数组 静态 TCB 结构体内存放在全局 / 静态区不使用堆。 优点没有 malloc内存确定适合高可靠、不能动态内存的场景缺点内存必须提前预留删除后需要手动管理不能自动释放。4. 栈在哪里✅ 动态创建 (xTaskCreate)任务栈是pvPortMalloc从FreeRTOS 堆中申请出来的一块内存。注意不是 MCU 的 C 语言栈每个 FreeRTOS 任务拥有独立私有栈。✅ 静态创建 (xTaskCreateStatic)任务栈是你定义的全局静态数组放在 MCU 的RAM.bss/.data 段编译时就固定分配。系统栈主栈 MSP中断使用的栈属于内核不属于任何任务任务运行时使用各自任务栈 PSP。一句话总结面试背诵版xTaskCreate需要传入任务函数、任务名、栈深度、入参、优先级、句柄指针返回 pdPASS 成功 /pdFALSE 失败属于动态创建TCB 和任务栈从 FreeRTOS 堆分配静态版本 xTaskCreateStatic 由用户提供静态内存。每个任务有独立私有栈动态任务栈在 FreeRTOS 堆静态任务栈在全局静态 RAM中断使用 MSP 主栈。6. 消息队列、信号量、互斥锁分别的作用锁和信号量的差异1. 消息队列 Queue作用任务间传递数据带内容实现任务通信可以存放完整数据拷贝数据不是传地址也可传地址支持多任务读、多任务写读写阻塞等待超时典型场景传感器采集任务把数据发给显示任务、串口收发数据。特点有实体数据先进先出 FIFO队列里可以存多条消息。2. 信号量 Semaphore分二值信号量、计数信号量作用事件通知、资源计数只传递 “事件有没有发生”不带数据二值信号量只有 0/1。多用于事件通知。 例中断收到数据释放信号量唤醒任务去处理。计数信号量0~N。用于多个同类资源管理。 例3 个串口最多 3 个任务同时使用资源数 3。特点只传递状态不带数据信号量计数值。3. 互斥锁 Mutex互斥信号量作用保护临界资源实现独占访问防止多个任务同时修改共享资源本质是特殊二值信号量拥有所有权谁拿到锁只有谁才能释放锁自带优先级继承用来缓解优先级反转问题典型场景多个任务读写同一个全局变量、操作同一个硬件外设。特点用于排他访问资源不是事件通知。二、互斥锁 vs 普通信号量核心差异面试高频所有权互斥锁有所有权谁获取只能谁释放。别的任务不能随便释放。二值信号量无所有权任务 A 获取任务 B 也可以直接释放。优先级继承互斥锁自带优先级继承缓解优先级反转。普通二值信号量没有优先级继承存在优先级反转风险。用途定位互斥锁保护临界区独占资源访问。二值信号量事件通知中断通知任务。计数互斥锁只能 0/1不能计数。计数信号量计数值可以大于 1。递归递归互斥锁支持同一个任务多次获取需要多次释放普通信号量不支持递归获取。一句话背诵差异 互斥锁有所有权、带优先级继承用于资源互斥保护只能持有者释放普通信号量无所有权任意任务可释放多用于事件通知没有优先级继承。一句话总述背诵版消息队列用于任务间传递数据信号量用于事件通知或统计可用资源数量互斥锁用于共享资源的独占保护。互斥锁拥有所有权自带优先级继承只能持有者释放普通信号量没有所有权任意任务都可以释放没有优先级继承多用于事件通知。7. 建立TCP连接时三次握手的过程在建立之前有其他连接需要建立吗三次握手后状态机进入什么状态8. 如何根据IP获取MAC地址9. 手撕面试官给了一段指针相关的代码问输出