Linux 驱动开发实战:从手写 LED 字符设备驱动到设备树

前言

学习Linux驱动,LED是经典入门案例。本文从最基础的硬编码寄存器字符设备驱动,过渡到设备树+platform平台驱动,完整梳理IMX6ULL上的实现思路,理解软硬件解耦思想。

一、传统字符设备驱动(无设备树)

原理

直接在驱动代码写死寄存器物理地址,使用ioremap完成地址映射,手动注册字符设备,提供open/release/write接口,应用层通过/dev/led操作LED。

核心代码片段

c 复制代码
static struct file_operations led_fops = {
    .owner = THIS_MODULE,
    .open = led_open,
    .release = led_release,
    .write = led_write,
};

static int __init led_init(void)
{
    register_chrdev(LED_MAJOR, "led", &led_fops);
    gpio_base = ioremap(GPIO_PHYS_ADDR, REG_SIZE);
    writel(OUT_MODE, gpio_base + GPIO_DIR);
    return 0;
}

缺点:硬件信息硬编码,更换硬件就要修改驱动源码、重新编译模块,可移植性差,仅适合入门理解字符设备底层原理。

二、设备树版本 platform 驱动(工程标准写法)

设备树将硬件信息剥离到dts文件,驱动只保留业务逻辑,依靠compatible属性完成设备与驱动匹配,实现软硬件分离。

dts节点片段

dts 复制代码
led_test {
    compatible = "myimx6ull,led";
    gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
    status = "okay";
};

平台驱动核心片段

c 复制代码
static const struct of_device_id led_of_match[] = {
    { .compatible = "myimx6ull,led" },
    {}
};

static struct platform_driver led_platform_driver = {
    .probe = led_probe,
    .remove = led_remove,
    .driver = {
        .name = "led-drv",
        .of_match_table = led_of_match,
    },
};
module_platform_driver(led_platform_driver);

匹配成功后自动执行probe函数,解析设备树GPIO属性、申请引脚资源并完成初始化。

三、应用层测试代码

c 复制代码
fd = open("/dev/led", O_RDWR);
write(fd, &val, 1);
close(fd);

写入1点亮LED,写入0熄灭LED。

四、完整实操流程

  1. 修改dts添加led节点,编译生成dtb并更新到开发板
  2. 编写platform驱动,Makefile编译生成ko模块
  3. 开发板insmod加载驱动,内核匹配设备树,自动创建设备节点
  4. 运行应用程序控制LED;测试完毕rmmod卸载驱动

五、两种方案对比

传统字符设备:代码简单,适合初学;硬件写死,移植性差。

设备树+platform驱动:工业主流方案,硬件描述和驱动逻辑分离,换硬件只需修改设备树,不用改动驱动代码。

六、常见问题

  1. compatible字符串驱动和设备树必须完全一致,大小写敏感,字符串不匹配会导致probe不执行
  2. GPIO电平极性容易颠倒,GPIO_ACTIVE_LOW代表低电平点亮
  3. 修改设备树后需要重新编译dtb,只编译ko不会更新硬件配置
  4. 内核模块版本要和开发板内核版本保持一致,否则加载模块报错
相关推荐
Linux界最忧郁之人5 小时前
华为云ECS&IMS&AS实战|弹性云服务器、私有镜像、弹性伸缩完整实验
linux·运维·服务器·centos·华为云·openstack
whyutianict_vv5 小时前
零基础转 AI 运维:投入清单、技术路线与核对表
linux·运维·人工智能·ai
无言听风雨丶5 小时前
systemd 与信号 / 僵尸进程:Linux 进程管理的底层逻辑与排错
linux·服务器·网络
DevOpenClub5 小时前
高考一分一段 API:分数查位次、科类枚举与历史对照
linux·数据库·高考
世微 如初6 小时前
24V 输入转 9V/0.8A 输出:基于 AP5190 的 LED 降压恒流驱动方案设计与 BOM 清单
驱动开发·芯片·led电源驱动·降压恒流ic
小贾要学习6 小时前
【C++后端开发项目】Reactor 模型 / C++ 仿写 muduo HTTP 服务器:让底层网络库真正跑起网页
linux·服务器·c++·http·网络编程·muduo·reactor模型
Blockbuater_drug6 小时前
OpenMM分子动力学模拟02 安装:Linux:conda 一条命令装通 GPU 加速的分子模拟环境
linux·conda·cuda·gpu驱动·pythonpath·openmm安装
程序员JerrySUN6 小时前
PCIe Gen5 SSD 为什么读得快、写得慢?从存储原理到 Linux 性能实测
linux·服务器·网络
Android系统攻城狮6 小时前
Linux FFmpeg深度解析之avcodec_parameters_copy调用流程与实战(二十五)
linux·运维·服务器·ffmpeg·音视频·车载音频
ITKEY_7 小时前
emacs 文件管理Dired, the Directory Editor
linux·编辑器·emacs