通过之前的学习,了解到linux驱动编写的流程是:先通过注册函数注册我们编写的入口函数,然后在入口函数中获取设备号->注册字符设备->自动创建设备节点->获取设备树信息,最后通过销毁函数将出口函数中需要释放的资源进行释放,想知道具实现的小伙伴可以查看我之前的文章。完成之前的学习,这篇文章所涉及的知识就比较简单了,现在我们开始led驱动的学习。
一、准备材料开发环境:VMware
操作系统:ubuntu
开发版:湃兔i2S-6UB
库文件:linux开发板或ubuntu的内核源码
我用的是i2C-6ULX-B开发版,想要了解更多开发版的信息可以查看i2C-6ULX-B开发套件,外观如下图所示:
通过湃兔官方提供的原理图,可以知道开发板上的两个LED,有一个是电源指示灯通电就亮,所以我们能使用的只有一个,具体如下图所示:
从原理图中可知led是低电平亮,高电平熄,然后接着查看湃兔核心板的引脚图,如下图所示:
最后在查看湃兔官方提供的引脚定义,具体如下图所以:
现在不用我多说小伙伴们都知道i2C-6ULX-B开发版上的led灯接的是芯片的gpio5.IO[5],在Linux中的GPIO计算方法是,GPIO_num = (<imx6ul_gpio_port> - 1) * 32 + <imx6ul_gpio_pin>,所以湃兔i2C-6ULX-B开发板的led接的是133引脚。 三、GPIO配置
了解led的硬件原理后,需要在设备树中进行配置,有需要的小伙伴可以了解湃兔官方的GPIO配置教程,好吧说得比较简单,没有学习过设备树的小伙伴可能看不懂,需要的可以百度搜索下相关教程。在配置之前我们还需要了解一下什么是GPIO子系统和pinctrl子系统,需要的朋友可以了解一下gpio子系统和pinctrl子系统(上)。
好吧,赶紧回来扯远了,看不明白不要紧,我们主要是先实践再理论,只学理论知识可能很让人绝望啊,等用多了,再回头学习自然就明白了。现在我们开始在设备树中配置gpio,打开'arch/arm/boot/dts'目录下的'i2c6ulxb-i2s6ull-emmc.dtsi'文件,在跟节点中添加如下信息
如下图所示:
细心的小伙伴可以已经看出来了,去注释了一行信息,因为湃兔的这个开发板只有一个led灯,然后被系统用于心跳灯使用,为了更好的验证,所以我们把系统使用的心跳灯给注释了,如下图所示:
最后在'iomuxc_snvs'这个节点中添加如下信息: pinctrl_dtsled: dtsled { fsl,pins = < MX6ULL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x1b0b0 >; };
如下图所示:
到此我们的设备树已经更改完成了,接下来编写驱动程序。 四、led驱动程序
其他的函数我就不过多介绍了,有需要的小伙伴可以查看我直接的文章,我使用led的驱动函数是如下所示
/* 获取GPIO */ int of_get_named_gpio(struct device_node *np, const char *propname, int index) /* 检查gpio number是否合法 */ int gpio_to_irq(unsigned gpio) /* 申请IO */ int gpio_request(unsigned gpio, const char *label) /* 释放IO */ void gpio_free(unsigned gpio) /* 设置gpio 为输入*/ int gpio_direction_input(unsigned gpio) /* 设置IO为输出模式 */ int gpio_direction_output(unsigned gpio, int value) /* 设置IO输出电平 */ gpio_set_value(unsigned gpio, int value) /* 设置gpio的消抖时间 */ int gpio_set_debounce(unsigned gpio, unsigned debounce) /* 获取gpio对应的中断线路 */ int gpio_to_irq(unsigned gpio) /* gpio中断 */ int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char * name, void * dev)