本文结合一个 RT-Thread 工程,介绍嵌入式开发中最常见的 6 类岗位:

  1. MCU 裸机开发

  2. MCU-RTOS 应用开发

  3. MCU 驱动/BSP 开发

  4. 嵌入式 Linux 应用开发

  5. 嵌入式 Linux 驱动/BSP 开发

  6. Linux 内核开发

读完后,就能大致判断这个岗位每天在做什么、需要写哪一层代码。

rt‑thread
├─ Applications    # 用户应用代码,main.c放这里
├─ Compiler        # 编译器适配层
├─ DeviceDrivers   # RT‑Thread驱动框架(操作系统自带)
├─ Drivers         # BSP板级驱动 drv_xxx.c、board.c【重点】
├─ Filesystem      # 文件系统组件
├─ Finsh           # 命令行shell
├─ Kernel          # RT‑Thread内核源码
├─ klibc           # RT‑Thread小型C库
├─ libcpu          # CPU架构移植层
├─ Libraries       # MCU原厂库(GD32/STM32库)
└─ CMSIS           # ARM标准CMSIS

一、先看懂这六个岗位的位置

可以把嵌入式系统从上到下分成三层:

┌─────────────────────────────────────────────
│  应用层:实现产品功能                        
│  MCU-RTOS 应用开发 / 嵌入式 Linux 应用开发    
├─────────────────────────────────────────────
│  操作系统层:管理线程、内存、文件和网络          
│  RTOS / Linux 内核                            
├─────────────────────────────────────────────
│  驱动与 BSP 层:让操作系统能够控制具体硬件      
│  MCU 驱动/BSP / Linux 驱动/BSP                
├─────────────────────────────────────────────
│  硬件层:MCU、SoC、传感器、Flash、网卡等       
└─────────────────────────────────────────────

MCU 裸机项目没有操作系统,应用、任务调度和硬件控制通常都放在同一个固件中。

二、六个岗位快速对照

岗位 核心工作 主要面对什么 典型代码
MCU 裸机开发 不使用操作系统,直接完成产品功能 主循环、中断、外设 main.c、状态机、外设初始化
MCU-RTOS 应用开发 使用 RTOS 编写产品业务 线程、IPC、设备 API 业务线程、协议解析、数据处理
MCU 驱动/BSP 开发 让 MCU 外设和开发板正常工作 寄存器、中断、DMA board.cdrv_xxx.c
嵌入式 Linux 应用开发 在 Linux 用户空间实现产品功能 进程、线程、文件、网络 C/C++ 程序、Qt、后台服务
嵌入式 Linux 驱动/BSP 开发 让 Linux 识别并控制硬件 设备树、内核驱动、SoC DTS、platform 驱动、内核配置
Linux 内核开发 修改 Linux 操作系统本身 调度、内存、文件系统、网络 kernel/mm/fs/net/

三、MCU 裸机开发

这个岗位是干什么的

MCU 裸机开发就是在 STM32、GD32 等单片机上直接编写程序,不使用 RTOS。

程序一般从 main() 开始,完成硬件初始化后进入一个无限循环。开发者需要自己决定按键什么时候扫描、传感器什么时候采集、串口数据什么时候处理。

int main(void)
{
    board_init();
    uart_init();
    sensor_init();
​
    while (1)
    {
        key_scan();
        sensor_read();
        protocol_process();
        control_output();
    }
}

这里所说的“裸机”是没有操作系统,不是所有代码都必须从零开始写。开发中仍然可以使用 CMSIS、HAL 或芯片厂商提供的标准外设库。

平时主要做什么

  • 配置 GPIO、UART、SPI、I2C、ADC、PWM 和定时器。

  • 编写主循环、状态机和产品控制逻辑。

  • 编写并处理各种中断。

  • 解析串口、CAN 或 RS485 通信协议。

  • 使用示波器和逻辑分析仪检查硬件时序。

  • 处理程序跑飞、数据丢失和响应不及时等问题。

主要写什么代码

main.c              主函数和大循环
board.c             开发板初始化
xxx_it.c            中断服务函数
bsp_uart.c          串口控制
bsp_spi.c           SPI 控制
protocol.c          通信协议
control.c           产品控制逻辑

常见产品

小家电、玩具、遥控器、简单仪表、传感器节点和简单控制器。

一句话记忆

MCU 裸机开发:没有操作系统,开发者用主循环、中断和状态机安排所有事情。


四、MCU-RTOS 应用开发

这个岗位是干什么的

MCU-RTOS 应用开发是在 RT-Thread、FreeRTOS、ThreadX 等实时操作系统上编写产品业务。

开发者不再把所有功能都塞进一个大循环,而是把不同功能拆成线程,并通过信号量、互斥量和消息队列进行协作。

例如:

传感器线程:定时采集数据
通信线程:接收并解析串口协议
控制线程:根据数据控制设备
显示线程:刷新屏幕

平时主要做什么

  • 创建和管理业务线程。

  • 使用信号量、互斥量、事件集和消息队列。

  • 编写串口协议解析、传感器数据处理和控制逻辑。

  • 调用 RTOS 设备接口访问串口、SPI、I2C 等设备。

  • 处理线程阻塞、优先级、栈空间和共享数据问题。

  • 添加 Shell 命令,查看设备运行状态。

主要写什么代码

在图中的 RT-Thread 工程里,主要对应:

Applications/main.c
Applications/ 下新增的业务文件

典型设备调用如下:

rt_device_t dev = rt_device_find("uart1");
rt_device_open(dev, RT_DEVICE_FLAG_INT_RX);
rt_device_read(dev, 0, buffer, sizeof(buffer));
rt_device_write(dev, 0, data, length);

这个岗位通常通过设备 API 使用硬件,不直接操作寄存器。小公司中应用开发者也可能同时承担部分驱动工作,但这是岗位合并,不是应用层本身的主要职责。

常见问题

  • 线程优先级设置不合理。

  • 线程栈太小导致栈溢出。

  • 多个线程同时访问同一资源。

  • 消息处理不及时或线程发生死锁。

  • 业务状态机设计混乱。

一句话记忆

MCU-RTOS 应用开发:驱动负责让硬件可用,应用负责调用设备 API 实现产品功能。


五、MCU 驱动/BSP 开发

这个岗位是干什么的

MCU 驱动/BSP 开发负责让 RTOS 在一块具体开发板上运行,并让板上的串口、SPI、I2C、CAN 等外设正常工作。

BSP 是 Board Support Package,也就是板级支持包。它连接了 RTOS 和具体硬件。

RTOS 应用
   ↓ 调用 rt_device_read/write
RT-Thread 设备框架
   ↓
drv_uart.c / drv_spi.c
   ↓
寄存器、中断、DMA
   ↓
真实硬件

平时主要做什么

  • 配置芯片时钟和引脚复用。

  • 编写 UART、SPI、I2C、CAN、ADC、PWM 等驱动。

  • 处理中断、DMA、超时和缓冲区。

  • 把具体驱动注册到 RT-Thread 设备框架。

  • 移植 RTOS 到新的 MCU 或开发板。

  • 与硬件工程师一起排查板级问题。

常见故障包括:

  • 串口发送正常但接收不到数据。

  • SPI 能读到数据,但数据内容错误。

  • 中断始终不触发。

  • DMA 偶尔丢数据。

  • 换一块板后系统无法启动。

主要写什么代码

在图中的工程里,主要对应:

Drivers/
├── board.c
├── startup_gd32f30x_hd.s
├── drv_gpio.c
├── drv_spi.c
└── drv_usart.c

同时需要使用或理解:

Libraries/          GD32 厂商外设库
DeviceDrivers/      RT-Thread 通用设备框架

一般情况下,BSP 工程师主要修改 Drivers/。只有扩展 RT-Thread 通用设备模型时,才需要经常修改 DeviceDrivers/

需要掌握什么

  • C 语言和基本汇编知识。

  • MCU 寄存器、启动流程和中断机制。

  • GPIO、UART、SPI、I2C、CAN、ADC 和 DMA。

  • 芯片数据手册和开发板原理图。

  • 示波器、逻辑分析仪和调试器。

一句话记忆

MCU 驱动/BSP 开发:面对寄存器和硬件,让 RTOS 能在这块板上运行并使用外设。


六、嵌入式 Linux 应用开发

这个岗位是干什么的

嵌入式 Linux 应用开发是在 ARM Linux 等系统的用户空间编写应用程序。

它和普通 Linux 应用开发很接近,常用 C、C++ 或 Python,通过文件、设备节点和网络接口实现产品功能。

例如,应用通过 /dev 下的设备文件访问串口:

int fd = open("/dev/ttyS1", O_RDWR);
write(fd, data, length);
read(fd, buffer, sizeof(buffer));
close(fd);

应用程序只需要知道怎样使用 /dev/ttyS1。这个设备节点怎样控制真实串口,是驱动工程师负责的事情。

平时主要做什么

  • 使用 C/C++ 编写产品业务程序。

  • 使用 Qt 编写触摸屏和图形界面。

  • 使用多进程、多线程和进程间通信。

  • 编写 TCP、UDP、HTTP、MQTT 等网络程序。

  • 操作串口、摄像头、音频和其他设备。

  • 使用 SQLite 等数据库保存数据。

  • 编写后台服务和开机启动配置。

  • 排查崩溃、内存泄漏和线程同步问题。

主要写什么代码

main.cpp             应用入口
device_manager.cpp   设备访问
protocol.cpp         通信协议
business.cpp         业务逻辑
ui/                  Qt 界面
CMakeLists.txt       构建配置
*.service            systemd 服务配置

这个岗位与 RT-Thread 工程中的 Applications/ 层最接近,但程序运行在 Linux 用户空间,能够使用更加完整的文件系统、网络、数据库和图形库。

常见产品

工控机、智能网关、机顶盒、安防设备、机器人控制器和车载中控。

一句话记忆

嵌入式 Linux 应用开发:驱动提供设备接口,应用通过这些接口实现界面、网络和业务功能。


七、嵌入式 Linux 驱动/BSP 开发

这个岗位是干什么的

嵌入式 Linux 驱动/BSP 开发负责把 U-Boot 和 Linux 移植到新的 ARM 开发板,并让 Linux 识别和控制板上的硬件。

应用开发者看到的是 /dev/ttyS1/dev/video0eth0,驱动工程师看到的是设备树、寄存器、中断、DMA 和 Linux 设备子系统。

平时主要做什么

  • 移植 U-Boot 和 Linux 内核。

  • 修改设备树 DTS,描述板上的硬件。

  • 编写 platform、I2C、SPI、USB、网卡、显示和音频驱动。

  • 配置和编译 Linux 内核。

  • 编译、加载和调试内核模块。

  • 分析内核启动日志和驱动加载过程。

  • 调试设备识别失败、内核 panic 和硬件性能问题。

主要写什么代码

设备树用来描述硬件:

sensor@48 {
    compatible = "vendor,temp-sensor";
    reg = <0x48>;
};

驱动代码负责匹配和控制这个设备:

static const struct of_device_id sensor_of_match[] = {
    { .compatible = "vendor,temp-sensor" },
    { }
};

常见源码位置:

arch/arm/boot/dts/       ARM 设备树
arch/arm64/boot/dts/     ARM64 设备树
drivers/gpio/            GPIO 驱动
drivers/i2c/             I2C 驱动
drivers/spi/             SPI 驱动
drivers/tty/             串口驱动
drivers/net/             网卡驱动
drivers/media/           摄像头驱动

驱动可以编译为 .ko 模块,也可以直接编译进内核。因此,.ko 是驱动的一种编译和加载方式,不是 Linux 驱动的全部。

BSP 和驱动有什么区别

  • BSP 更偏整块板:启动、设备树、时钟、内存、内核配置和根文件系统。

  • 驱动更偏某个设备:串口、传感器、摄像头、网卡、显示和音频。

小公司经常把两个方向合并成一个岗位。

常见产品

ARM 开发板、工业控制设备、安防摄像头、智能网关、机器人和车载设备。

一句话记忆

嵌入式 Linux 驱动/BSP 开发:让 Linux 在新板子上启动,并按照 Linux 的规则控制硬件。


八、Linux 内核开发

这个岗位是干什么的

Linux 内核开发是修改 Linux 操作系统本身,而不是只为某个外设编写驱动。

主要方向包括:

  • 进程和线程调度。

  • 虚拟内存和页面管理。

  • 文件系统和块设备层。

  • TCP/IP 和网络协议栈。

  • 系统调用、锁和多核并发。

  • 内核安全、实时性和性能优化。

平时主要做什么

  • 阅读和修改 Linux 内核源码。

  • 分析调度延迟、内存不足和系统卡顿。

  • 优化文件系统、网络或多核性能。

  • 排查 kernel panic、死锁和内存错误。

  • 使用 perf、ftrace、crash 等工具分析内核。

  • 编写和维护内核补丁及测试用例。

主要写什么代码

kernel/        调度、中断、时间和内核核心机制
mm/            虚拟内存和页面管理
fs/            VFS 和具体文件系统
net/           网络协议栈
ipc/           进程间通信
block/         块设备通用层
arch/          CPU 架构相关代码

在 RT-Thread 工程中,可以把 Linux 内核粗略类比为 Kernel/Filesystem/DeviceDrivers/libcpu/ 等目录的集合。但 Linux 的代码规模和机制复杂得多。

和 Linux 驱动开发有什么区别

对比项 Linux 驱动/BSP Linux 内核开发
主要目标 让某块板或某个设备工作 修改操作系统的通用机制
常见对象 DTS、寄存器、中断、DMA 调度、内存、文件系统、网络
常见目录 drivers/、DTS、部分 arch/ kernel/mm/fs/net/
岗位数量 相对较多 相对较少、专业方向更细

从广义上说,Linux 驱动也是内核代码;但在实际招聘中,“Linux 驱动工程师”和“Linux 内核工程师”通常指两个不同方向。

Linux 内核岗位常见于芯片原厂、操作系统厂商、云计算公司、服务器厂商和大型终端公司,数量通常少于应用与驱动岗位。

一句话记忆

Linux 内核开发:不只让某个硬件工作,而是修改 Linux 管理进程、内存、文件和网络的方式。

九、最后用六句话总结

  1. MCU 裸机开发:没有操作系统,自己用主循环和中断安排所有工作。

  2. MCU-RTOS 应用开发:使用线程和 IPC 编写产品业务,主要调用现成设备接口。

  3. MCU 驱动/BSP 开发:操作寄存器、处理中断,让 RTOS 和硬件连接起来。

  4. 嵌入式 Linux 应用开发:在用户空间编写界面、网络和业务程序。

  5. 嵌入式 Linux 驱动/BSP 开发:移植 Linux,并让内核识别和控制板上设备。

  6. Linux 内核开发:修改调度、内存、文件系统和网络等 Linux 核心机制。

判断一个岗位最简单的方法是看它主要面对什么:

  • 面对产品需求和业务逻辑,是应用开发。

  • 面对寄存器、中断和硬件时序,是驱动/BSP 开发。

  • 面对调度、内存和文件系统,是内核开发。

岗位名称可能不同,但只要找到它在整个系统中的位置,就能判断这份工作究竟需要写哪一层代码。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐