如何确定为各类硬件编写Linux驱动时应选用的驱动类型及对应函数?
如何为不同硬件选择合适的Linux驱动类型及注册函数
1. 片上(On-Chip)硬件设备
这类设备是SoC集成的固定外设,比如UART、I2C控制器、GPIO、内置ADC/DAC等,首选平台驱动(Platform Driver):
- 核心注册函数:
platform_driver_register(),注销用platform_driver_unregister() - 为什么选它:平台驱动专为无标准总线的片上设备设计,设备信息通常通过Device Tree或板级代码传递,能精准匹配SoC内部固定地址、中断的硬件
- 完整流程:定义
platform_driver结构体(实现probe/remove等回调),在probe中完成硬件初始化(比如I/O映射ioremap()、申请中断request_irq());若需向用户空间提供访问接口,可搭配字符设备框架(alloc_chrdev_region()+cdev_init()+cdev_add()),并通过class_create()创建设备类以生成/dev节点
2. 可插拔外设(USB、PCIe、SDIO等)
这类设备遵循标准总线协议,具备热插拔能力,直接使用对应总线的专用驱动框架即可:
USB设备
- 核心注册函数:
usb_register_driver(),注销用usb_deregister_driver() - 驱动结构体为
usb_driver,需实现probe/disconnect回调;USB子系统会自动处理热插拔、枚举流程,可通过usb_class_driver自动生成设备节点
PCIe设备
- 核心注册函数:
pci_register_driver(),注销用pci_unregister_driver() - 驱动结构体为
pci_driver,PCI子系统负责枚举设备,probe中可通过pci_resource_start()获取硬件地址,pci_enable_device()激活设备;按需添加字符/块设备接口即可
SDIO设备
- 核心注册函数:
sdio_register_driver(),注销用sdio_unregister_driver() - 驱动结构体为
sdio_driver,适配SDIO总线的可插拔外设(如WiFi模块)
3. MPSoC可编程硬件模块(如FPGA逻辑、可配置加速器)
这类硬件兼具固定地址和可编程特性,分两种场景选择:
- 若模块被映射为内存地址空间的外设,使用平台驱动:流程与片上设备一致,
probe中通过ioremap()访问寄存器、配置可编程逻辑(如加载bitstream到FPGA),再提供用户空间访问接口 - 若模块支持动态重构或有专用总线(如AXI),可结合misc驱动或自定义字符设备:
- 用
misc_register()注册misc设备(适合简单单实例设备);或用alloc_chrdev_region()+cdev框架实现完整字符设备,在file_operations中实现可编程逻辑的配置、数据交互函数
- 用
4. 通用字符设备(无总线关联的简单硬件)
如果硬件是独立的、无标准总线的简单外设(如自定义GPIO扩展板),直接使用字符设备框架:
- 流程:
alloc_chrdev_region()分配设备号 →cdev_init()初始化字符设备 →cdev_add()添加到系统 →class_create()+device_create()生成/dev节点 - 无需平台驱动,适合逻辑简单、无需总线匹配的场景
关键选择原则
- 优先用对应总线的专用驱动框架:比如USB用USB驱动、PCIe用PCIe驱动,这类框架已封装总线枚举、热插拔、电源管理等逻辑,减少重复代码
- 无标准总线的固定硬件用平台驱动:借助Device Tree传递硬件参数,适配不同SoC板卡
- 简单单实例的小硬件用misc驱动:比完整字符设备实现更简洁
- 需要完全自定义用户空间交互的用字符设备框架:灵活度最高,但需手动处理设备号、节点创建等细节
内容的提问来源于stack exchange,提问作者Galux Trabakoulas
相关产品推荐
相关产品推荐

