zoukankan      html  css  js  c++  java
  • GPIO使用总结

    一、GPIO重要概念

    要想操作GPIO引脚,需要先把所用引脚配置成GPIO功能,这个通过pinctrl子系统来实现。然后可以根据设置的引脚的方向来读取引脚的值和设置输出值。GPIO子系统存在之前,我们驱动需要在代码中配置寄存器来使用GPIO引脚。再BSP工程师实现好GPIO子系统后,我们就可以在设备树中指定GPIO引脚,在驱动中使用GPIO子系统的标准函数来获取GPIO、设置GPIO方向、读取/设置GPIO的值。这样的驱动代码是于单板无关的。

    二、GPIO内核相关文档

    Documentationdevicetreeindingspinctrlpinctrl-bindings.txt
    Documentationgpiogpio.txt
    Documentationdevicetreeindingsgpiogpio.txt

    三、GPIO设备树配置

    1. BSP工程师实现的gpio驱动,驱动工程师直接在设备树中配置使用。

    //client节点
    device {
        led-gpios = <组, 哪个几个,flag>; //"组"是必须要有的元素,为gpio控制器的描述,这里除了组之外还有几个域是由组中的#gpio-cells的值决定的。
    };
    
    //service端,设备树中对一个gpio控制器的表示:
    gpio1 {
        ......
        gpio-controller;
        #gpio-cells = <2>; //表示client使用gpio1这一组中的某个引脚时,除了组之外还需要使用2个整数来表示。
    };

    2. 举个例子:

    foo_device {
        compatible = "acme,foo";
        ......
        led-gpios = <&gpio 15 GPIO_ACTIVE_HIGH> /*red*/ //一般这里可能为&gpioX
            <&gpio 16 GPIO_ACTIVE_HIGH> /*green*/
            <&gpio 17 GPIO_ACTIVE_HIGH>; /*blue*/
        
        power-gpios = <&gpio, 1 GPIO_ACTIVE_LOW>; //注意这里使用了avtive_low属性了
    };

    驱动代码中:

    gpiod_get_index(dev, "led", 0, GOIOD_OUT_HIGH); //取出设备树中名为led的gpio中的第0个引脚,也就是red。
    gpiod_get_index(dev, "led", 1, GOIOD_OUT_HIGH); //取出第1个

    若在设备树中只定义了一个引脚,就可以使用:

    gpiod_get(dev, "power", GPIO_OUTPUT_HIGH); //把这个设备下名为power的那个引脚给取出来。

    三、在驱动中使用GPIO

    1.GPIO子系统有两套接口

    (1) 一是基于描述符(descriptor-based)的,相关api函数都是以"gpiod_"为前缀,它使用gpio_desc结构来表示一个引脚。
    (2) 另一种是老(legency)的,相关api函数都是以"gpio_"为前缀,它使用一个整数来表示一个引脚。

    要操作一个引脚,首先要get引脚,然后设置方向,然后读取、写值。

    2.列举操作GPIO常使用的函数

    //1.获取GPIO
    gpiod_get  //legency为gpio_request
    gpiod_get_index
    gpiod_get_array //legency为gpio_request_array
    devm_gpiod_get
    devm_gpiod_get_index
    devm_gpiod_get_array
    
    //2.设置方向
    gpiod_direction_input  //legency为gpio_direction_input
    gpiod_direction_output //legency为gpio_direction_input
    
    //3.读值、写值
    gpiod_get_value //legency为gpio_get_value
    gpiod_set_value //legency为gpio_set_value
    
    //4.释放GPIO
    gpio_free //gpio_free
    gpiod_put //gpio_free_array
    gpiod_put_array
    devm_gpiod_put
    devm_gpiod_put_array

      前缀为"devm_"的含义是设备资源管理,这是一种自动释放资源的机制。它的思想是“资源是属于设备的,设备不存在时资源就可以自动释放”。在Linux驱动开发过程中,先申请了GPIO,再申请内存,如果内存申请失败,那么在返回之前就需要先释放GPIO资源。如果使用的是devm相关函数,在内存申请失败时可以直接返回,设备的销毁函数会自动地释放已经申请了的GPIO资源。建议使用devm相关函数操作GPIO。

    3.如何通过GPIO号来使用GPIO

    比如要通过gpio号来操作原理图上的GPIO5_14这个gpio引脚,那么得先知道这个gpio引脚的number是多少。那么得先找到gpio5组的基gpio number是多少。

    /sys/class/gpio/# ls
    export gpio30 gpiochip0 gpiochip32 gpiochip64 gpiochip96 gpiochip128 gpiochip504 unexport //gpiochip96 这一组gpio的基gpio号是96
    /sys/class/gpio/gpiochip128# ls
    base device label ngpio power subsystem uevent
    /sys/class/gpio/gpiochip128# cat label //可以看出设备树节点名为gpio@20ac000,20ac000就是这一组gpio寄存器的基地址,可通过它查看每一组gpio的基gpio号
    20ac000.gpio
    /sys/class/gpio/gpiochip128# cat base //表示这一组gpio的基gpio号为128
    128
    /sys/class/gpio/gpiochip128# cat ngpio //表示这一组gpio的个数
    32

    在dtsi文件中检索20ac000就可以看到如下设备树配置,所以知道gpio5这一组gpio的基gpio号是128

    gpio5: gpio@20ac000 {
        compatible = "fsl,im6ul-gpio", "fsl,imx35-gpio";
        reg = <0x020ac000 0x4000>;
        interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
        gpio-controller;
        #gpio-cells = <0x2>;
        interrupt-controller;
        #interrupt-cells = <0x2>;
    };

    那么GPIO5_14,其gpio号就是128+14=142,然后可以将这个gpio给导出来,设置其方向,配置其值,进行验证。

    /sys/class/gpio# echo 142 > export
    /sys/class/gpio# ls
    export unexport gpio142  ... //此时可以看到多了一个gpio142目录
    /sys/class/gpio/gpio142# ls
    active_low direction power uevent device edge subsystem value //此时可以cat active_low 看是否具有active_low属性
    /sys/class/gpio/gpio142# echo in > direction //设置为输入引脚
    /sys/class/gpio/gpio142# cat value //读取其值
    1
    /sys/class/gpio# echo 142 > unexport //取消映射

    如果某个引脚已经被使用了,再次export就会报错:“resource busy”。算出引脚号后就可以在驱动中使用legency函数来通过gpio号来操作gpio引脚了。

    注意: Qcom平台,如果内核级驱动程序通过of_get_named_gpio()函数或类似函数获取,请求并使用该GPIO,则无法将该GPIO导出以进行sysfs控制。


    五、active_low属性

      注意,设置的逻辑电平并不一定等于物理电平,因为有active_low属性,若在获取GPIO的时候指定了active_low属性,那么设置为1就是低电平,设置为0才是高电平。但是也有一些函数直接忽略active_low属性,整理如下:

    unction(example)               active-low属性        物理电平
    gpiod_set_raw_value(desc, 0)    don't care             0
    gpiod_set_raw_value(desc, 1)    don't care             1
    gpiod_set_value(desc, 0)        是                     1
    gpiod_set_value(desc, 0)        否                     0
    gpiod_set_value(desc, 1)        是                     0
    gpiod_set_value(desc, 1)        否                     1
  • 相关阅读:
    JS,JQ及时监听input值的变化,MUI的input搜索框里的清除按钮的点击监听事件
    MUI 底部弹出的选择框
    MUI 拍照或选取照片上传作为头像
    多行文本文本输入框 textarea 可点击任意地方编辑的问题
    mui dtpicker 时间的设置 以及MUI的弹窗
    MUI 样式按钮的禁用
    利用渐变实现书本的效果
    调用sqlserver中的存储过程
    XmlHelper
    面试题 数据库sql
  • 原文地址:https://www.cnblogs.com/hellokitty2/p/12500546.html
Copyright © 2011-2022 走看看