【linux内核驱动day03】
怎么写驱动程序?
驱动程序:操作硬件的程序就是驱动程序,驱使(硬件)设备工作
- 实现open/read/write/close等操作方法(操作硬件)
- 向内核注册该驱动程序(以设备号的方式)
- 建立设备号和设备节点(设备名)之间的对应关系
设备号:
代表一个具体的设备(驱动程序),是无符号32位
主设备号:高12位:区分设备类型 例如SPI IIC
次设备号:低20位:区分同类的设备 SPI0 SPI1 SPI2
确定设备号:高12位和低20位
cat /proc/devices 可以查看系统当前加载的驱动
驱动程序分类:
- 字符设备驱动:数据访问按字节流(按顺序)的形式,绝大多数都是字符型设备
- 块设备驱动:数据访问是块(随机)的,例如存储设备
- 网络设备驱动:集成比较复杂的协议栈 例如网卡
字符设备和块设备都是按照设备号来管理,设备号是独立管理的
网络设备是按照设备名管理,没有设备号
设备的设备号是独立管理的 cat /proc/devices 可以查看
ctags追踪:
光标停留在函数名字的位置
按 ctrl + ] 跳转函数定义的位置
按 ctrl +o 回到调用函数的位置
编写驱动程序流程:
以demo.c为例:
- 以下所有路径都默认在顶层目录下,在/drivers/char下写demo.c文件
- make -j8编译,生成zImage文件
- 将zImage文件拷贝到tftpboot目录下
- cp arch/arm/boot/zImage ~/tftpboot
- cp arch/arm/boot/dts/imx6ull-alientek-emmc.dtb ~/tftpboot
- 回到rootfs目录下,编译应用程序 arm-linux-gnueabihf-gcc demo_app.c -o demo_app
- 在uboot中,tftp 0x80800000 zImage tftp 0x83000000 imx6ull-alientek-emmc.dtb bootz 0x80800000 - 0x83000000
- 启动内核后,在开发板终端中执行 mknod /dev/demo c 255 0创建一个设备节点
- mknod 手动创建设备节点
- /dev/demo 设备节点名
- c 字符设备
- 255 主设备号
- 0 次设备号
- ls /dev/ -l 出现设备号为255, 0 的demo
- 在rootfs目录下编写
- 在开发板段运行应用程序调用驱动接口,运行 ./demo_app
添加led文件:
- 在/drivers/char下写led.c文件
- 以下默认在顶层目录下:vim /drivers/char/Makefile 加一行
- obj-$(CONFIG_LED1) +=led.o
- vim /drivers/char/Kconfig 增加配置
- make menuconfig
- make -j8编译
- 拷贝:将zImage文件拷贝到tftpboot目录下
- cp arch/arm/boot/zImage ~/tftpboot
- cp arch/arm/boot/dts/imx6ull-alientek-emmc.dtb ~/tftpboot
- uboot中三部曲,启动内核
- cat /proc/devices 中出现led的设备号
- ls /dev/ -l 中没有led
- 添加设备节点:mknod /dev/led c 248 0
- ls /dev/ -l 有led
- 在rootfs目录下编写led_app.c文件,并编译
- 在开发板终端里运行./led_app
杂项设备驱动框架:(字符设备驱动)
主设备号10
编译模块(动态加载):
- Kconfig中定义配置类型为tristate ,修改bool (三种模式 y m n)
- make menuconfig 选项配置为M
- make zImage 只编译选为y的配置选项
- make modules 编译内核模块 (只编译所有被配置为M的模块)
- 再驱动文件的同层目录下生成 .ko内核模块
- 将生成的/drivers/char/ .ko 文件拷贝到/nfs/rootfs目录下
- 拷贝zImage和 .dtb 文件到tftpboot目录下
使用:
- uboot中tftp三部曲,驱动内核
- insmod led.ko 加载led.ko驱动模块
- lsmod 查看动态加载的驱动模块
- rmmod led 卸载动态加载的驱动模块
驱动和设备分离:
驱动:操作方法 在led里,ON/OFF 对应高电平/低电平
设备:设备资源
led,key,adc没有总线,弄一个虚拟的总线,才可以分离
设备资源和操作方法独立注册
驱动里加led,设备里也加led,才能match匹配到
匹配成功后,执行probe, 注册字符设备驱动
创建2个文件,
vim /drivers/char/led_drivers.c
vim /drivers/char/led_device.c
写好之后,在开发板里insmod led_derivers.ko insmod led_device.ko
随时添加和卸载都不影响,动态加载的