通过这个LED驱动,应用程序可以选择指定第n个LED,使能并控制LED亮灭。并且该驱动程序被设计可以适应两个板卡的应用程序。IMX6ullPro 和 STM32MP157,是通过分层的思想实现的,如下介绍。
驱动大致流程按照如下进行:
第一步:分层
分为两层:
file_operations:注册驱动,实现对应的drv_open/drv_close/drv_read/drv_write函数。
led_operations:不同board实现硬件操作,不同板卡构建各自的led_operations结构体
第二步:分离 led.drv.h
在led_drv.h中,实现了一个led_operations,为LED引脚实现了初始化函数、控制函数:如果想更换引脚控制LED,只需要修改init和ctl函数内容即可。
第三步:写硬件的LED初始化和LED控制程序 board_imx6ull.c
首先定义GPIO的引脚IOMUX,和IMX6ULL的GPIO寄存器
初始化:static int board_demo_led_init(int which) /* 根据which初始化哪个led */
首先通过ioremap函数将物理地址转换为虚拟地址。参数1是物理地址,参数2是映射的物理内存的大小,以字节数为单位,通常为4字节
在该init函数中根据which值0~3,初始化4个LED灯.
以GPIO5_3为例:
首先是
使能gpio5这个模块
再把gpio5_3配置成gpio功能
gpio5_3配置输出功能
这样初始化就完成了
/* CCM_CGR1(CCM Clock Gating Register 1 )外设时钟使能寄存器 */
/* 设置对应位为0b'11,使得对应GPIOX时钟一直有效使能 */
所以GPIO1_3为
这样就对4个LED的GPIO配置初始化完成了。
LED控制:static int board_demo_led_ctl (int which, char status) /* 控制LED,which指哪个LED,status:1-高电平,0-低电平 */输出高低电平
然后将这些IMX6ULL的函数分配一下LED_Operations结构体,硬件的配置就完成了。
第四步:驱动编写 led_drv.c:程序的编写也是按照如下流程:
确定主设备号
定义自己的file_operations结构体
实现对应的open/read/write/close函数,填入file_operations结构体
主要功能在open_drv和write_drv函数里。
Open_drv函数调用了上文硬件定义的board_demo_init函数初始化LED
Write_drv函数调用了上文硬件定义的board_demo_ctl函数控制LED亮灭
把file_operations结构体告诉内核:注册驱动程序。写一个入口函数来注册驱动程序
编写出口函数,卸载驱动程序
至此LED驱动编写完毕。
第五步:对驱动编写应用程序和Makefile测试 对这个./ledtest /dev/xuwu_led0 on匹配
第六步:交叉编译make后,在IMX6ULL上测试
先将驱动装在到板卡上:insmod 100ask_led.ko
ls /dev/xuwu_led* 查询到有四个LED设备
./ledtest /dev/xuwu_led0 on 就点亮了LED0
./ledtest /dev/xuwu_led0 off 就熄灭了LED0
同理改变LED号,可控制其他LED灯。