1. 初始化DRM设备驱动框架

初始化DRM设备驱动框架 学习卡片

任务目标

编写一个最小DRM驱动,完成以下闭环:注册platform_driver,在probe回调中初始化DRM设备并注册,实现基本的open/close回调。驱动加载后,用户空间可通过/dev/dri/card0访问设备节点。

环境与依赖

  • Linux内核源码树(本文以5.15版本为例)
  • 内核配置启用DRM:CONFIG_DRM=y或=m
  • 编译所需头文件:drm/drm_device.h、drm/drm_drv.h、drm/drm_file.h

完整实现

创建文件minidrm.c,代码如下:

```c #include #include #include #include #include static int minidrm_open(struct drm_device *dev, struct drm_file *file) { /* 最小实现:仅返回成功,可在此分配文件级私有数据 */ return 0; } static void minidrm_close(struct drm_device *dev, struct drm_file *file) { /* 最小实现:释放文件级私有数据(如有) */ } static const struct drm_driver minidrm_driver = { .driver_features = DRIVER_GEM, .open = minidrm_open, .close = minidrm_close, .name = "minidrm", .desc = "Minimal DRM driver", .major = 1, .minor = 0, }; static int minidrm_probe(struct platform_device *pdev) { struct drm_device *drm; int ret; drm = drm_dev_alloc(&minidrm_driver, &pdev->dev); if (IS_ERR(drm)) return PTR_ERR(drm); platform_set_drvdata(pdev, drm); ret = drm_dev_register(drm, 0); if (ret) goto err_free; dev_info(&pdev->dev, "minidrm registered\n"); return 0; err_free: drm_dev_put(drm); return ret; } static int minidrm_remove(struct platform_device *pdev) { struct drm_device *drm = platform_get_drvdata(pdev); drm_dev_unregister(drm); drm_dev_put(drm); return 0; } static const struct platform_device_id minidrm_id_table[] = { { .name = "minidrm" }, { } }; MODULE_DEVICE_TABLE(platform, minidrm_id_table); static struct platform_driver minidrm_platform_driver = { .probe = minidrm_probe, .remove = minidrm_remove, .id_table = minidrm_id_table, .driver = { .name = "minidrm", }, }; module_platform_driver(minidrm_platform_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("Minimal DRM platform driver"); ```

编译与加载

创建Makefile:

```makefile obj-m += minidrm.o KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) all: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: $(MAKE) -C $(KDIR) M=$(PWD) clean ```

编译并加载:

```bash make sudo insmod minidrm.ko # 绑定platform设备(若设备树未定义,需手动创建) echo "minidrm" | sudo tee /sys/bus/platform/drivers/minidrm/bind ```

若设备树中已定义compatible = "minidrm"节点,则probe会自动触发,无需手动bind。

验证方法

  1. 驱动加载:执行dmesg | tail,应看到minidrm registered日志。
  2. 设备节点:执行ls -l /dev/dri/,应出现card0节点。
  3. open/close验证:执行以下命令,若返回0且无错误输出,说明open/close回调正常工作:
```bash sudo cat /dev/dri/card0 > /dev/null echo "exit code: $?" ```

通过条件:以上三步全部成功,即驱动注册、设备节点创建、文件操作回调均正常。

常见问题

  • insmod报错Unknown symbol:确认内核已启用DRM核心(CONFIG_DRM),且版本与编译头文件一致。
  • bind失败:确认platform设备名称与id_table中.name一致,或设备树节点compatible属性匹配驱动driver.name。
  • 打开设备节点返回ENODEV:检查drm_dev_register是否成功,以及driver_features是否包含必要特性(如DRIVER_GEM)。