嵌入式开发六大岗位:从 MCU 裸机到 Linux 内核
本文结合一个 RT-Thread 工程,介绍嵌入式开发中最常见的 6 类岗位:
-
MCU 裸机开发
-
MCU-RTOS 应用开发
-
MCU 驱动/BSP 开发
-
嵌入式 Linux 应用开发
-
嵌入式 Linux 驱动/BSP 开发
-
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.c、drv_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/video0 和 eth0,驱动工程师看到的是设备树、寄存器、中断、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 管理进程、内存、文件和网络的方式。
九、最后用六句话总结
-
MCU 裸机开发:没有操作系统,自己用主循环和中断安排所有工作。
-
MCU-RTOS 应用开发:使用线程和 IPC 编写产品业务,主要调用现成设备接口。
-
MCU 驱动/BSP 开发:操作寄存器、处理中断,让 RTOS 和硬件连接起来。
-
嵌入式 Linux 应用开发:在用户空间编写界面、网络和业务程序。
-
嵌入式 Linux 驱动/BSP 开发:移植 Linux,并让内核识别和控制板上设备。
-
Linux 内核开发:修改调度、内存、文件系统和网络等 Linux 核心机制。
判断一个岗位最简单的方法是看它主要面对什么:
-
面对产品需求和业务逻辑,是应用开发。
-
面对寄存器、中断和硬件时序,是驱动/BSP 开发。
-
面对调度、内存和文件系统,是内核开发。
岗位名称可能不同,但只要找到它在整个系统中的位置,就能判断这份工作究竟需要写哪一层代码。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐




所有评论(0)