一、基本概念
1.驱动是内核态程序,运行在内核空间,负责硬件控制 + 向上提供接口;
2.从编程的角度来看驱动的本质是:
1)向上:给应用层提供文件接口(/dev/xxx),应用层通过 open/read/write/ioctl 操作驱动;
2)向下:直接操作硬件寄存器(物理地址需映射为虚拟地址),实现对硬件的控制;
3)核心:驱动是内核与硬件之间的中间层,屏蔽硬件差异,提供统一接口;
4)必须遵守内核编程规则,例如不能用printf,要用printk;不能用malloc,要用kmalloc。
3.驱动程序分类:
1)字符设备驱动:按字节流、顺序方式访问,例如LED、按键、串口、I2C;
2)块设备驱动:按块、随机方式访问,例如eMMC、SD卡、硬盘;
3)网络设备驱动:按数据包方式访问,例如网卡、WiFi。
4.驱动程序的加载方式:
1)静态编译:驱动编译进内核镜像(zImage/uImage),系统启动时自动加载(适合核心驱动,如UART);
2)动态加载:驱动编译为内核模块(.ko),系统运行时通过 insmod/rmmod 加载/卸载(适合自定义驱动,灵活,常用)。
二、驱动开发关键知识点
1.container_of宏:实现从成员变量反向获取包含它的结构体指针的关键,是内核中大量数据结构操作的基础。
2.内核链表使用;
3.动态申请内核空间:kmalloc、kcalloc、krealloc、kzalloc kfree,vmalloc,vzalloc,vfree;
4.物理地址映射:操作硬件寄存器,例如ioremap、oread32、iowrite32函数;
5.内核/用户空间数据拷贝:copy_from_user、copy_to_user函数;
6.中断机制:响应硬件事件,例如request_irq、free_irq函数;
7.等待队列(阻塞I/O):让进程休眠、唤醒,例如wait_queue_head_t结构体、wait_event_interruptible、wake_up_interruptible函数;
8.内核休眠机制(定时器、高精度定时器);
9.内核线程(kthread_create/kthread_run);
10.内核锁机制(Mutex、Spinlock);
11.设备树(Device Tree):描述硬件,驱动不硬编码,例如of_get_named_gpio、irq_of_parse_and_map函数;
12.Platform驱动模型:为无物理总线的外设设计的虚拟总线驱动框架,核心是
总线(Bus) → 设备(Device) → 驱动(Driver)分离:
1)虚拟总线(platform_bus):内核内置的虚拟总线,负责匹配设备和驱动;
2)设备(platform_device):描述硬件资源(寄存器地址、中断号、GPIO等),嵌入式中通常由设备树自动生成(无需手动定义);
3)驱动(platform_driver):实现硬件操作逻辑(初始化、读写、控制),通过compatible 字符串匹配设备。