GPIO主要功能:
1、配置管脚高低电平
2、模拟其他模块,例如I2C、SPI去发送对应模块协议的波形
3、去毛刺(滤波)
GPIO框架以及对应的子系统网上已经很多人介绍,在这里主要介绍工作中接触过的GPIO验证方法
gpio sysfs接口,是在gpiolib(gpiolib-sysfs.c)层注册的接口,可以通过该接口对gpio引出对应的管脚,配置对应管脚的电平、中断等。
sysfs路径:cd /sys/class/gpio/
前置条件:把两个gpio管脚对联(下面两个方法二选一即可)
物理上:需要用短接线把两个gpio管脚连起来
软件上:可以在CPLD里做好对接,需要哪两个管脚对联,但是这样方向好像是固定的(具体有点忘了)
验证方法:
1、把管脚引出来,这个目录下显示的是每个gpio controller的base num,如果需要把其他引脚引出来,可以通过export这个文件
echo XXX > /sys/class/gpio/export
2、设置方向(把一个管脚设置为输入,对联的另一个管脚设置为输出)
echo in > /sys/class/gpio/gpioXXX(输入管脚)/direction
echo out > /sys/class/gpio/gpioXXX(输出管脚)/direction
3、配置输入管脚中断,但是如果没记错的话,edge只能配置边沿触发的中断,高低电平是配置不了的
4、配置输出管脚的value,控制输入管脚的触发中断
低电平:echo 0 > /sys/class/gpio/gpioXXX(输出管脚)/value
高电平:echo 1 > /sys/class/gpio/gpioXXX(输出管脚)/value
中断相关:
1、可能管脚已经中断屏蔽,可查看中断屏蔽寄存器的值
2、需要打开组合中断寄存器,gpio管脚的中断可通过组合中断寄存器去管理,当多个管脚触发中断的时候,可通过组合中断寄存器一次性上报给CPU
3、如果高低电平中断的话,会触发中断风暴,可在中断处理函数,使用中断上下半部,上半部disable_irq去使能中断,下半部可以设置一个delay甚至更小的udelay的时间去enable_irq,这样中断还是会触发,并且是在你设置的时间间隔就会去触发一次,使中断风暴保持在一个可控范围内
GPIO测试驱动:(完整代码不记得了,只记得大致的步骤)
之前是写过一个测试驱动,在加载驱动的时候,是可以配置哪一个gpio管脚、并且可以配置gpio中断、输入输出方向,是否中断屏蔽,甚至还有去毛刺的功能,可通过加载驱动配置对应的寄存器实现
1、申请gpio管脚资源
gpio_request
2、配置对应的管脚的方向
gpio_direction_input/gpio_direction_output
3、通过管脚获取到gpio_desc,获取中断
gpiod_to_desc(获取到这个描述符,可通过该描述符配置中断屏蔽)
gpiod_to_irq
4、申请中断(中断上下半部)
devm_request_threaded_irq
linux devm_request_threaded_irq 函数接口说明-CSDN博客
5、中断屏蔽(这里可放在申请中断的步骤前面,比如管脚默认的电平是高电平,然后你配置的中断也是高电平触发,可能注册完中断立马就会产生中断风暴,当然你也可以提前通过sysfs接口把对应管脚的电平配为跟中断触发相反的电平)
6、释放资源
gpio_free
7、前面很多接口都需要知道gpio的管脚号,可设置一个加载驱动的配置参数
module_param
或者想要同时配几个gpio管脚,可用module_param_array
8、参考文档
《中断学习—— GPIO外部中断驱动实例》 - 一个不知道干嘛的小萌新 - 博客园 (cnblogs.com)
GPIO中断驱动(pin写死方法与dts方法)_iotable_init dts-CSDN博客
GPIO子系统层次与数据结构_gpio_desc-CSDN博客
Linux 驱动开发 / gpio子系统 / 快速入门 - 知乎 (zhihu.com)
9、问题
写这个驱动感觉最大的问题,就是中断的处理,因为gpio的管脚号是一个全局的变量,有可能会导致一个可重入的问题,所以要很好地解决这个问题的话,可能涉及到一些加锁的问题。如果一个gpio管脚可能并不需要这么麻烦,因为一时间只可能有一个管脚的中断,但是我当时写的是可以同时支持配置3个gpio管脚,因此我觉得比较麻烦,就没有用锁,而是直接在中断处理函数,在函数里对中断号进行一些处理,判断对应的中断是否来源此时正在去使能的中断号,同时enable_irq之前也做了判断。
以上仅代表个人的一些工作中的经验总结,可能有不正确的地方,多包涵理解,感谢!