虹软科技 嵌入式开发软件 一面

1. 自我介绍

您好,我是XXX,目前就读于XX大学电子信息工程/自动化专业。我的技术方向是嵌入式系统开发,对单片机、RTOS、驱动开发有深入的学习和实践。

技术能力方面:

  • 熟练掌握C/C++编程
  • 熟悉ARM Cortex-M系列单片机的开发
  • 熟悉FreeRTOS、RT-Thread等实时操作系统的使用和移植
  • 了解常见的通信协议如UART、SPI、I2C、CAN等
  • 了解网络协议如TCP/IP、MQTT

项目经验方面:

我做过智能小车、物联网数据采集系统等项目。

在智能小车项目中,我负责底层驱动开发和传感器数据采集,实现了电机控制、超声波避障、循迹等功能。

在物联网项目中,我负责设备端的开发,使用MQTT协议实现数据上报和远程控制。

比赛经验方面:

我参加过全国大学生电子设计竞赛、智能车竞赛等,获得过省级奖项。通过比赛锻炼了快速开发和调试的能力,也积累了团队协作的经验。

我对嵌入式技术充满热情,喜欢研究底层原理,善于解决实际问题。希望能加入贵公司,在实际项目中不断提升自己。

2. FreeRTOS的任务调度机制,抢占式和时间片轮转的区别

FreeRTOS调度机制

FreeRTOS使用基于优先级的抢占式调度。每个任务有一个优先级,数字越大优先级越高。调度器总是运行就绪态中优先级最高的任务。

当高优先级任务就绪时,会立即抢占低优先级任务的CPU。低优先级任务被挂起,高优先级任务开始运行。这就是抢占式调度。

对于相同优先级的任务,FreeRTOS使用时间片轮转。每个任务运行一个时间片(tick),时间片到了就切换到下一个同优先级任务。这样保证了同优先级任务的公平性。

任务状态

FreeRTOS的任务有四种状态:

  • 运行态:任务正在执行
  • 就绪态:任务可以运行但还没轮到
  • 阻塞态:任务在等待事件,比如等待信号量、延时
  • 挂起态:任务被主动挂起,不参与调度

任务从运行态可以进入阻塞态,比如调用延时函数。从阻塞态可以进入就绪态,比如延时到期。从就绪态可以进入运行态,被调度器选中。

调度时机

调度发生在几个时机:

  1. 系统滴答中断,每个tick都会检查是否需要切换任务
  2. 任务主动放弃CPU,比如调用延时、等待信号量
  3. 中断服务程序结束时,可能有高优先级任务就绪

抢占式 vs 时间片轮转

抢占式调度:

  • 保证了实时性,高优先级任务可以立即响应
  • 但可能导致低优先级任务饥饿,长时间得不到执行

时间片轮转:

  • 保证了公平性,同优先级任务都能得到执行机会
  • 但实时性相对差一些,任务可能要等待一个时间片

FreeRTOS结合了两者的优点,不同优先级用抢占式,相同优先级用时间片轮转。这样既保证了实时性,又保证了公平性。

实际应用

在设计任务时,要合理分配优先级:

  • 紧急的、实时性要求高的任务设置高优先级
  • 不紧急的、后台任务设置低优先级

要避免优先级反转问题。低优先级任务持有资源,高优先级任务等待资源,中优先级任务抢占CPU,导致高优先级任务无法执行。可以使用优先级继承或优先级天花板解决。

要注意任务的栈大小设置。栈太小会导致栈溢出,栈太大会浪费内存。可以使用栈溢出检测功能,及时发现问题。

3. MQTT协议的原理,和TCP有什么区别?

MQTT协议

MQTT是Message Queuing Telemetry Transport的缩写,是一种轻量级的消息传输协议。它基于发布-订阅模式,适合物联网场景。

MQTT的核心概念是主题Topic。发布者向某个主题发布消息,订阅者订阅某个主题接收消息。中间有一个Broker代理服务器,负责消息的转发。

MQTT支持三种QoS质量等级:

  • QoS 0:最多一次,消息可能丢失
  • QoS 1:至少一次,消息可能重复
  • QoS 2:恰好一次,消息不丢失不重复

MQTT vs TCP

TCP:

  • 传输层协议,提供可靠的字节流传输
  • 点对点通信,需要知道对方的IP和端口
  • 需要自己处理消息的封装、解析、重传等
  • 适合两个设备直接通信

MQTT:

  • 应用层协议,基于TCP实现,提供消息传输功能
  • 发布-订阅模式,不需要知道对方地址,通过主题通信
  • 已经实现了消息封装、解析等功能,使用更简单
  • 适合多个设备通过服务器通信,特别是一对多、多对多的场景

为什么用MQTT

  1. 轻量级:协议开销小。MQTT的消息头只有2字节,适合带宽受限的物联网场景
  2. 支持弱网络环境:有心跳机制,可以检测连接状态。有遗嘱消息机制,设备异常断开时可以通知其他设备
  3. 支持QoS:可以根据需求选择消息质量。重要消息用QoS 2保证可靠,不重要的消息用QoS 0节省资源
  4. 支持主题订阅:实现灵活的消息路由。可以用通配符订阅多个主题,比如sensor/+/temperature订阅所有传感器的温度数据

MQTT点对点通信

MQTT本身是发布-订阅模式,不是点对点。但可以通过设计主题实现点对点。

比如设备A要给设备B发消息,可以发布到主题device/B/message。设备B订阅这个主题,就能收到消息。

或者使用私有主题,每个设备有唯一的主题。设备A发布到设备B的主题,只有设备B能收到。

但这种方式需要知道对方的设备ID,而且Broker会转发所有消息,效率不高。如果真的需要点对点,直接用TCP更合适。

实际应用

在物联网项目中,我使用MQTT实现设备和云平台的通信:

  • 设备定期发布传感器数据到主题sensor/data,云平台订阅这个主题接收数据
  • 云平台发布控制命令到主题device/控制,设备订阅这个主题接收命令
  • 使用QoS 1保证消息可靠,避免数据丢失
  • 使用遗嘱消息机制,设备断开时自动发布离线消息,云平台可以及时发现设备离线

4. Linux驱动框架的理解,字符设备驱动的实现

Linux驱动框架

Linux把设备分为三类:

  • 字符设备:按字节流访问,比如串口、LED
  • 块设备:按块访问,比如硬盘、SD卡
  • 网络设备:用于网络通信,比如网卡

Linux的驱动框架实现了应用层和驱动层的隔离。应用程序通过设备文件访问设备,不需要知道驱动的实现细节。驱动程序实现设备的操作函数,注册到内核。

这种分层设计的好处是应用程序可以用统一的接口访问不同的设备。驱动程序可以独立开发和更新,不影响应用程序。

字符设备驱动

字符设备驱动的核心是file_operations结构体,定义了设备的操作函数:

  • open:打开设备
  • release:关闭设备
  • read:读取数据
  • write:写入数据
  • ioctl:控制设备

驱动程序实现这些函数,然后注册到内核。应用程序通过openreadwrite等系统调用访问设备,内核会调用驱动的对应函数。

注册字符设备需要设备号,包括主设备号和次设备号。主设备号标识驱动程序,次设备号标识具体设备。可以静态分配设备号,也可以动态分配。

设备文件

设备文件是应用程序访问设备的接口,位于/dev目录下。设备文件有设备号,内核根据设备号找到对应的驱动。

可以用mknod命令手动创建设备文件,也可以用udev自动创建。现代Linux系统都使用udev,驱动加载时自动创建设备文件。

驱动加载

驱动可以编译到内核中,也可以编译为模块动态加载。模块方式更灵活,可以在运行时加载和卸载。

驱动模块有init函数和exit函数:

  • init函数在模块加载时执行,注册设备
  • exit函数在模块卸载时执行,注销设备

使用insmod命令加载模块,rmmod命令卸载模块,lsmod命令查看已加载的模块。

FreeRTOS vs Linux

FreeRTOS没有驱动框架,驱动代码和应用代码混在一起。应用程序直接调用驱动函数,耦合度高。

如果要在FreeRTOS上实现类似Linux的驱动框架,可以定义统一的设备接口。每个驱动实现这些接口,注册到设备管理器。应用程序通过设备管理器访问设备,不直接调用驱动函数。

这样可以实现应用和驱动的解耦,提高代

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

嵌入式面试八股文全集 文章被收录于专栏

这是一个全面的嵌入式面试专栏。主要内容将包括:操作系统(进程管理、内存管理、文件系统等)、嵌入式系统(启动流程、驱动开发、中断管理等)、网络通信(TCP/IP协议栈、Socket编程等)、开发工具(交叉编译、调试工具等)以及实际项目经验分享。专栏将采用理论结合实践的方式,每个知识点都会附带相关的面试真题和答案解析。

全部评论

相关推荐

02-16 01:39
南昌大学 Java
坚持无悔意无休:xhs上集美最爱说谎博人眼球
点赞 评论 收藏
分享
02-15 14:18
已编辑
江西工程学院 Java
点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务