zoukankan      html  css  js  c++  java
  • Linux 内核层和 用户层 配置 GPIO 引脚

      Linux BSP 开发的基础就是和GPIO打交道, 下面总结下这几天对某家开发板的GPIO控制的知识。

      公司的开发板用的是 DTB  模式 ,首先,进入 dts,dtsi文件查看关于GPIO 的模块。

    soc {
                    .
                    .
                    .
            gpio0: gpio@****addr {
                compatible = "**********";
                reg = <0 0x****addr 0 0x50>;
                interrupts = <SPI 4 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 0 16>;
                #interrupt-cells = <2>;
                interrupt-controller;
                clocks = <&cpg CPG_MOD 912>;
                power-domains = <*****>;
            };
                   .
                   .
                   .
    
    };

      可以看到 GPIO 节点 挂在 SOC node 下 ,手上这块开发板 把GPIO分成了8个 bank  :  gpio0 - gpio7

        reg =<0 地址 0 长度> 

             #gpio-cells  =<2> 表示 要用2个cell描述一个 GPIO引脚 

        如 I2C中定义 :  pwd-gpios  = <&gpio6 7 GPIO_ACTIVE_HIGH>;

        表示 bank 6 的gpio  用 2个cell 描述  :7,GPIO_ACTIVE_HIGH (7表示bank 6 下的第七个引脚一般是 GP 6_07表示  ;GPIO_ACTIVE_HIGH则为高电平有效)     

        gpio-controller;  interrupt-controller; 表示 bank 0 下的引脚 既可以作为中断引脚 ,也可以作为 通用的GPIO引脚 

             gpio-ranges = <&pfc 0 0 16>;  表示 bank 0下有16个 GPIO引脚 

       GPIO 使用 pinctrl 方式来驱动 ,pin control subsystem 会 :

        1. 枚举所有可用的pin 脚   ,于是每个引脚就有的唯一的 ID (num) ,这个ID 很关键,对于以后的操作。

        

    enum {
        PINMUX_RESERVED = 0,
    
        PINMUX_DATA_BEGIN,
        GP_ALL(DATA), /* add GP_0_1_DATA  ,GP_0_1_DATA..... */
        PINMUX_DATA_END,
    
    #define F_(x, y)
    
    .....
    }

        2.管理 这些Pin脚的, 由于pin 可以复用 比如 SPI 和GPIO 复用一个pin脚 如:  GP2_08 / MISO,于是引申出 pin group 和 pin functon 两个概念:

        i2c2_pins: i2c2 {
            groups = "i2c2_a";
            function = "i2c2";
        };

        在dts 中如上所示 ,其中 i2c2_a 在 pinctl 源码中 如下所示,i2c的两根引脚使用 GP5_0 ,GP5_4. 

    static const unsigned int i2c2_a_pins[] = {
        /* SDA, SCL */
        GP_PIN(5, 0),GP_PIN(5, 4),
    };

        function 如下 : 

    struct sh_pfc_function {
        const char *name;
        const char * const *groups;
        unsigned int nr_groups;
    };
    #define SH_PFC_FUNCTION(n = i2c2)                
        {                        
            .name = #n,                
            .groups = n##_groups,            
            .nr_groups = ARRAY_SIZE(n##_groups),    
        }

    好了 ,基本概念就先写这么多  。

    内核层配置 GPIO 

    在 写内核驱动的时候 如果希望配置某个GPIO引脚 , 可以在dts中 添加:  pwd-gpios  = <&gpio0 7 GPIO_ACTIVE_HIGH>;

     在 driver 代码中 ,  需要包含 #include <linux/gpio.h>使用 : 

        gpio_id = of_get_named_gpio(your_driver->dev->of_node,"pwd-gpios", 0);

    获取 GP0_07的 ID号 ,然后申请 一个GPIO 操作对象。

        if (gpio_is_valid(gpio_id))  //判断一个IO是否合法

          devm_gpio_request_one(&platform_device->dev, gpio_id,GPIOF_OUT_INIT_LOW, name);

    设置GPIO的方向,如果是输出同时设置电平:
        /* set as input or output, returning 0 or negative errno */
        int gpio_direction_input(unsigned gpio);
        int gpio_direction_output(unsigned gpio, int value);

    获取输入引脚的电平:
        /* GPIO INPUT: return zero or nonzero */
        int gpio_get_value(unsigned gpio);

    设置输出: 
        void gpio_set_value(unsigned gpio, int value);

    释放申请的GPIO对象 

            void gpio_free(unsigned gpio);

    将GPIO映射为IRQ中断:
        /* map GPIO numbers to IRQ numbers */
        int gpio_to_irq(unsigned gpio);

        /* map IRQ numbers to GPIO numbers (avoid using this) */
        int irq_to_gpio(unsigned irq);

     设置GPIO IRQ中断类型:

        set_irq_type(gpio_to_irq( gpio), IRQ_TYPE_EDGE_FALLING);

    用户层配置 GPIO 

    需要确认  内核  menuconfig  中 Device Drivers -》  GPIO Support  设 y .

    在 /sys/class/gpio  目录下如下所示 : 

    root@salvator-x:/sys/class/gpio# ls
    export         gpiochip361  gpiochip419  gpiochip453  gpiochip496
    gpiochip357  gpiochip393  gpiochip437  gpiochip468  unexport

    gpiochip 后面的数字 是每个bank 的基地址  也就是  GP0 对应 gpiochip468

    那么  GP0_07 的 ID 就是  468 + 7 ;(可能不同的内核版本,或者 开发板不一样 )通过 :

    root@salvator-x:/sys/class/gpio# echo 475 > export

    会对应生成 gpio475 目录 

    root@salvator-x:/sys/class/gpio/gpio475# ls
    active_low  device  direction  edge  power  subsystem  uevent  value

    通过 

    root@salvator-x:/sys/class/gpio/gpio475# echo 1 >value 
    root@salvator-x:/sys/class/gpio/gpio475# echo 0 >value
    root@salvator-x:/sys/class/gpio/gpio475# echo "in" > direction 
    root@salvator-x:/sys/class/gpio/gpio475# echo "out" > direction 

    来控制输出输入  ,电平高低 。 

    最后,关于 Pinctrl 的内容还有太多要写,就先写到这把。。。。。

    来不及写 参考文档了,具体是 结合 wowotech 和 公司的设备,要下班了。。。

     ADD :..........................................................................

    获取GPIO不同组 基地址的 bash 命令 :

    for i in gpiochip* ; do echo `cat $i/label`: `cat $i/base` ; done

     

     

     

  • 相关阅读:
    JavaWeb笔记
    Session案例_登录注销
    会话
    Cookie入门
    jsp入门
    if else优化
    cheap-source-map--不显示源码 、source-map--显示源码 、 eval--最快的编译办法
    npm run dev 克隆报错
    $emit和$on的用法
    npm
  • 原文地址:https://www.cnblogs.com/hutiann/p/7780185.html
Copyright © 2011-2022 走看看