gpio是一种非常灵活的接口,可以简单的做输入输出控制设备或采集信号,也可以模拟各种协议。作者就是因为要用gpio模拟一种自定义的协议完成通信,所以才有了本篇文章。调试期间也是遇到了各种问题,好在成功控制。
第一步:menuconfig
老样子,不论是使用DM模型的uboot版本,还是老版本,先使能GPIO控制器驱动:
make menuconfig
如图,在设备驱动路径下找到GPIO Support,我的uboot使用了DM驱动模型,所以使能上,另外还要使能所用控制器厂商的驱动。
第二步:设备树
一般来说,半导体厂商提供的SDK会帮我们把所有控制器的设备树节点都写好,MT7621也不例外,我们一般可以在dtsi文件中找到gpio节点描述:
可以看到,gpio节点已经写好了,其实我们早在使用gpio模拟各种协议的时候已经使用过gpio了,这说明gpio驱动已经是正常工作的状态了,那我们岂不是什么都不用做了?这里可能会产生误区,dtsi描述的gpio节点是控制器的信息,但是我们要作为gpio去使用,就要有一个与之对应的驱动,比如我们前面模拟的spi,i2c,具体的IO会在这个驱动中去初始化,但是我们现在不是用作这种已经写好的驱动,所以该怎么办呢?
1.使用传统方法,直接操作gpio控制器的寄存器(使用此方法不用做前面这些步骤)
2.在设备树中自定义gpio信息,使用dm驱动模型框架获取设备树中的gpio信息,并最终调用dm框架定义的gpio操作函数!
显然,我们使用了第二种方法:这样就可以将gpio控制器和要使用的gpio的信息糅合起来在uboot中使用,因此我们在 / 节点下定义如下信息:
节点名、compatible、具体IO名都是可以自定义的,因为等下我们也是根据这些名字去获取这个节点的信息。定义好该节点后,我们开始写代码。
第三步:编程
如图,我们只使用设备树中定义的其中一个io来举例,定义一个gpio_desc类型的结构体,该结构体用来描述一个gpio所带的属性,驱动通过解析desc的信息来控制物理层的io。
接下来我们需要定位在设备树中描述的io节点信息,通过compatible属性查找,找到节点之后我们就能访问节点定义的信息啦,使用gpio_request_by_name_nodev函数依次将自定义的io信息取出并进行注册申请,如果申请成功,将信息存储在对应的gpio_desc中,该函数最后一个参数用于指定IO的方向。使用之前,先使用dm_gpio_is_valid函数判断该io的描述符是否有效,然后使用dm驱动模型定义的一系列函数进行io操作,当然了,这些dm操作函数最终还是对应mt7621原厂驱动中提供的ops函数,此处我们不做过多分析。
第四步:编译、下载、测试
我们在测试部分除了控制IO的电平,还进行了1/2的打印,对于接口部分,可以使用示波器、逻辑分析仪、或者一颗led灯来测试。这里仅放出打印信息:
可以看到,终端进行了5次打印,和程序运行5次相符,并且在我的pcb上的led也正确闪烁,至此,我们就学会了如何在uboot中使用gpio了!
注:如果IO不受控,请仔细检查是否有其他外设占用此接口!!!