一、框架
1、编写驱动程序的套路:
- 确定主设备号,也可以让内核分配。
- 定义自己的file_operations结构体。
- 实现对应的drv_open/drv_read/drv_write 等函数,填入file_operations结构体。
- 把file_operations 结构体告诉内核:register_chrdev。
- 谁来注册驱动程序啊?得有一个入口函数:安装驱动程序时,就会去调用这 个入口函数。
- 有入口函数就应该有出口函数:卸载驱动程序时,出口函数调用unregister_chrdev。
- 其他完善:提供设备信息,自动创建设备节点:class_create,device_create。
2、驱动怎么操作硬件?
1、通过 ioremap 映射寄存器的物理地址得到虚拟地址,读写虚拟地址。
3、驱动怎么和APP传输数据?
1、通过copy_to_user、copy_from_user这2个函数。
4、驱动程序:
1、 实现led_open函数,在里面初始化LED引脚。
2、实现led_write函数,在里面根据APP传来的值控制LED。
二、 IMX6ULL的GPIO介绍
GPIO的控制涉及3大模块:CCM、IOMUXC、GPIO模块本身
1、CCM_CCGR寄存器
GPIOx要用CCM_CCGRy寄存器中的2位来决定该组GPIO是否使能。哪组GPIO用哪个CCM_CCGR寄存器来设置,请看上图红框部分。
CCM_CCGR寄存器中某2位的取值含义如下:
① 00:该GPIO模块全程被关闭
② 01:该GPIO模块在CPU run mode情况下是使能的;在WAIT或STOP模式下,关闭
③ 10:保留
④ 11:该GPIO模块全程使能
2、IOMUXC:引脚的模式(Mode、功能)
对于某个/某组引脚,IOMUXC中有2个寄存器用来设置它:
① 选择功能:
IOMUXC_SW_MUX_CTL_PAD_<PADNAME> :Mux pad xxx,选择某个pad的功能
IOMUXC_SW_MUX_CTL_GRP_<GROUP NAME>:Mux grp xxx,选择某组引脚的功能
某个引脚,或是某组预设的引脚,都有8个可选的模式(alternate (ALT) MUX_MODE),
比如:
② 设置上下拉电阻等参数:
IOMUXC_SW_PAD_CTL_PAD_<PAD_NAME>:pad pad xxx,设置某个pad的参数
IOMUXC_SW_PAD_CTL_GRP_<GROUP NAME>:pad grp xxx,设置某组引脚的参数
比如:
3、GPIO模块
① GPIOx_GDIR:
设置引脚方向,每位对应一个引脚,1-output,0-input
② GPIOx_GDIR:
设置输出引脚的电平,每位对应一个引脚,1-高电平,0-低电平
③ GPIOx_PSR:
读取引脚的电平,每位对应一个引脚,1-高电平,0-低电平
三、最简单的操作IMX6ULL点亮一个灯的驱动程序
1、定义寄存器地址
①:IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3
地址:0x02290000 + 0x14
②:GPIO5_GDIR
地址:0x020AC004
③:GPIO5_DR
地址:0x020AC000
2、映射寄存器地址
用ioremap函数来映射,这个函数特点如下:
虚拟地址 = ioremap(物理地址, 相映射多少个字节);
IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = ioremap(0x02290000 + 0x14, 4);GPIO5_GDIR = ioremap(0x020AC004, 4);GPIO5_DR = ioremap(0x020AC000, 4);
注:虽然只是映射了4个字节,但是会映射一页。
3、配置GPIO
①:使能GPIO5
默认使能
②:配置GPIO5_IO3为GPIO模式
设置IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3寄存器后四位为0101
代码实现:
*IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 &= ~0xf;*IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 |= 0x05;
③:配置GPIO5_IO3为输出模式
由于IO3是Bit3,所以将GDIR的第三位制一
代码如下:
*GPIO5_GDIR |= (1<<3);
4、通过寄存器GPIO5_DR控制灯亮灭
由于是LED是低电平点亮
代码如下:
亮:
*GPIO5_DR &= ~(1<<3);
灭:
*GPIO5_DR |= (1<<3);
5、清除映射地址
虚拟地址 = ioremap(物理地址, 相映射多少个字节);
iounmap(IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 );iounmap(GPIO5_GDIR );iounmap(GPIO5_DR );