
前言
之前我们把 linux 系统移植介绍完了,现在我们正式开始对 Linux 驱动开发进行介绍,首先我们先与裸机开发进行区别介绍一下。
一、为什么要上操作系统呢?
在嵌入式开发早期,很多设备是'裸机运行'的——没有操作系统,程序直接跑在 CPU 上。这时候的驱动开发更像'全栈工程师':既要管硬件寄存器操作,又要处理业务逻辑。
比如做一个智能灯泡,用 51 单片机控制 LED:
- 首先得配置 GPIO 引脚(通用输入输出口)的寄存器,设置为输出模式;
- 然后写代码控制引脚的高低电平(高电平亮,低电平灭);
- 还要处理按键输入,检测用户是否按下开关;
- 甚至得自己实现'软定时器',让灯泡支持闪烁功能。
这种模式下,驱动和业务逻辑完全绑定,代码复用性极差。如果换一款不同型号的单片机(比如从 STC89C52 换成 STM32),GPIO 寄存器的地址和配置方式可能完全不同,几乎要重写整个驱动。
随着嵌入式设备功能越来越复杂,裸机开发的局限性越来越明显:
- 硬件资源(CPU、内存)需要高效调度,否则多个任务会'打架';
- 不同硬件的驱动代码需要隔离,避免某个驱动崩溃导致整个系统死机;
- 开发者希望'一次编写,多处运行',减少重复劳动。
这时候操作系统(比如 Linux)就登场了。操作系统就像一个'大管家',把驱动从业务逻辑中解放出来,让它们专注做一件事:和硬件'对话'。
比如在 Linux 系统中,驱动只需要负责:
- 初始化硬件(比如配置摄像头的 I2C 寄存器);
- 处理硬件中断(比如收到传感器数据时触发中断);
- 提供统一的接口给上层应用(比如应用调用 read() 函数就能获取传感器数据)。
而任务调度、内存管理、文件系统这些'杂活',都由操作系统内核处理。驱动开发者终于可以'术业有专攻'了。
二、裸机驱动开发回顾
裸机驱动开发更加底层一些,直接跟寄存器打交道,虽然一些 MCU 提供了库,但相比 Linux 驱动开发还是更加底层了一些。
三、Linux 驱动开发思维
- Linux 下驱动开发一般不直接操作寄存器,比较复杂,不现实。
- 根据 Linux 下的各种驱动框架进行开发。一定要满足框架,也就是 Linux 下各种驱动框架的掌握。
- 驱动最终表现就是/dev/xxx 文件。打开、关闭、读写。
- Linux 内核支持设备树,这是一个.dts 文件,此文件描述了板子的设备信息。
四、Linux 驱动开发分类
Linux 设备的'三大门派'
Linux 把硬件设备分成了三大类,就像武侠小说里的'少林、武当、峨眉',各有各的套路。
1、总体框图

2、字符设备驱动(最常见)
特点是数据传输以字节为单位,没有固定的块结构。常见的键盘、鼠标、串口、传感器(如温湿度传感器)都属于这类。
例子:用串口调试助手发送'Hello',驱动会把数据拆成'H'、'e'、'l'、'l'、'o'逐个发送,接收方也是逐个字节读取。
字符设备的核心是**cdev结构体(字符设备描述符)**,驱动需要实现 file_operations 结构体中的函数(比如 open、read、),这些函数就是上层应用和硬件交互的'桥梁'。



