GPIO子系统

1.GPIO子系统框架

 2.GPIO子系统相关API

#include<linux/of_gpio.h>
1.解析设备树节点信息
struct device_node *of_find_node_by_path(const char *path)
    功能:通过路径获取设备树节点信息
path:设备树节点路径  ("/mynode@0x12345678")
返回值:成功返回目标节点首地址,失败返回NULL
2.获取对应的GPIO编号
int of_get_named_gpio(struct device_node *np,
                                   const char *propname, int index)
功能:根据gpio相关节点的解析得到对应gpio的编号
参数:
np:设备树节点首地址
proname:键名
index:索引号
返回值:成功返回gpio编号,失败返回错误码       
3. 申请要使用的gpio编号
 int gpio_request(unsigned gpio, const char *label) 
 功能:申请要使用的gpio编号
 参数:
 gpio:要申请的gpio编号
 label:填写任意字符串都可以,默认填NULL
 返回值:成功返回0,失败返回错误码
 4.int gpio_direction_input(unsigned gpio)
 功能:将gpio设置为输入功能
 参数:
 gpio:gpio编号
 返回值:成功返回0,失败返回错误码
 5. int gpio_direction_output(unsigned gpio, int value)     
 功能:将gpio设置为输出功能并且输出一个指定电平
 gpio:gpio编号
 value:  1高电平  0低电平
 返回值:成功返回0,失败返回错误码
 
 6.void gpio_set_value(unsigned gpio, int value)
 功能:设置gpio输出的电平值
  gpio:gpio编号
 value:  1高电平  0低电平
 
 7. int gpio_get_value(unsigned gpio)
功能:获取gpio引荐状态值
参数:
    gpio:gpio编号
返回值:此时的引脚状态值
                                                                                                                                                                                                                           
8.void gpio_free(unsigned gpio)
功能:释放申请的gpio编号
参数:gpio:目标gpio编号
返回值:无

3.GPIO设备树的编写方式 

3.1led的硬件连接图

 3.2 GPIO控制器的设备树

stm32mp157a-fsmp1a.dts->stm32mp157.dtsi->stm32mp153.dtsi->stm32mp151.dtsi

    
    pinctrl: pin-controller@50002000 {
        #address-cells = <1>;
        #size-cells = <1>;
        gpioe: gpio@50006000 {
            gpio-controller;//空属性,标识这个节点是gpio控制器节点
            #gpio-cells = <2>;//在引用gpio控制器节点时,值的个数
            
            reg = <0x4000 0x400>;//控制器的地址和长度
            clocks = <&rcc GPIOE>;//引用gpioe控制器的时钟设备树节点
            st,bank-name = "GPIOE";//gpio控制器的名字GPIOE
            status = "disabled";//控制器的状态  disable不工作  okay工作
            };
   };
    vi stm32mp15xxac_pinctrl.dtsi         
&pinctrl {
    gpioe: gpio@50006000 {
        status = "okay";//将上面gpioe中的status属性值覆盖
        ngpios = <16>;//这个控制器一共16个管脚
        gpio-ranges = <&pinctrl 0 64 16>;//gpioe在整个gpio中的编号
    };

 };

3.3 led的设备树节点编写

内核顶层目录/Documentation/devicetree/bindings/gpio

vi gpio.txt

gpioe: gpio@50006000 {
        gpio-controller;
        #gpio-cells = <2>;
    };    

    
 
 
 在linux-5.10.61/arch/arm/boot/dts/stm32mp157a-fsmp1a.dts文件中添加下面内容:
             myleds{
                 // &gpioe表示引用gpioe控制器,10表示管脚是gpioe10  0表示默认状态
                  led1= <&gpioe 10 0>;
           led2= <&gpiof 10 0>;
           led3= <&gpioe 8 0>;
         };

4.GPIO子系统的使用实例

#include <linux/init.h>
#include <linux/module.h>
#include<linux/of.h>
#include<linux/of_gpio.h>
#include<linux/gpio.h>
/*  myleds{
    // &gpioe表示引用gpioe控制器,10表示管脚是gpioe10  0表示默认状态
     led1= <&gpioe 10 0>;
   led2= <&gpiof 10 0>;
   led3= <&gpioe 8 0>;
 };
 };*/

 struct device_node *node;
int gpiono;
static int __init mycdev_init(void)
{
   int ret;
    //通过路径获取设备树节点信息
    node=of_find_node_by_name(NULL,"myleds");
    if(node==NULL)
    {
        printk("通过路径解析设备树节点信息失败\n");
        return -ENODATA;
    }
      printk("通过路径解析设备树节点信息成功\n");
      //获取gpio编号
      gpiono=of_get_named_gpio(node,"led1",0);
      if(gpiono<0)
      {
        printk("获取gpio编号失败\n");
        return gpiono;
      }
      printk("获取gpio编号成功\n");
      //申请gpio编号的使用权
    ret=gpio_request(gpiono,NULL);
    if(ret)
    {
        printk("申请gpio编号失败\n");
        return ret;
    }
    printk("申请gpio编号成功\n");
    //设置gpio的方向为输出并给一个低电平初始值
    gpio_direction_output(gpiono,0);
    //将led1点亮
    gpio_set_value(gpiono,1);
    
     return 0;
}
static void __exit mycdev_exit(void)
{
    //卸载驱动前先关灯
    gpio_set_value(gpiono,0);
    //释放gpio编号
    gpio_free(gpiono);

}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

5.GPIO子系统新版API

老版本的函数是gpio_***,新版本的接口名字,gpiod_***

1.struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
                     const char *propname, int index,
                     enum gpiod_flags dflags,
                     const char *label)
功能:获取gpio编号并且申请gpio编号的使用权
参数:
node:设备树节点信息结构体指针
propname:键名
index:索引号
dflags:设置使用的gpio的状态
        GPIOD_IN:输入
        GPIOD_OUT_LOW:输出模式并且为低电平
        GPIOD_OUT_HIGH:输出模式并且为高电平
label:填NULL
返回值:成功返回gpio结构体指针,失败返回错误码指针  IS_ERR
2. int gpiod_direction_input(struct gpio_desc *desc)
3. int gpiod_direction_output(struct gpio_desc *desc, int value)
4.  int gpiod_get_value(const struct gpio_desc *desc)
5. void gpiod_set_value(struct gpio_desc *desc, int value)
6.void gpiod_put(struct gpio_desc *desc)

使用实例

#include <linux/init.h>
#include <linux/module.h>
#include<linux/of.h>
#include<linux/of_gpio.h>
#include<linux/gpio.h>
/*  myleds{
    // &gpioe表示引用gpioe控制器,10表示管脚是gpioe10  0表示默认状态
    led1= <&gpioe 10 0>;
   led2= <&gpiof 10 0>;
   led3= <&gpioe 8 0>;
 };
 };*/

 struct device_node *node;
 struct gpio_desc *desc;

static int __init mycdev_init(void)
{
   int ret;
    //通过路径获取设备树节点信息
    node=of_find_node_by_name(NULL,"myleds");
    if(node==NULL)
    {
        printk("通过路径解析设备树节点信息失败\n");
        return -ENODATA;
    }
      printk("通过路径解析设备树节点信息成功\n");
      //获取gpio编号
    desc=gpiod_get_from_of_node(node,"led1",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(desc))
    {
      printk("申请gpio编号失败\n");
      return PTR_ERR(desc);
    }
    printk("申请gpio编号成功\n");
    //亮灯
     gpiod_set_value(desc,1);
     
     return 0;
}
static void __exit mycdev_exit(void)
{
   //灭灯
    gpiod_set_value(desc,0);
    //释放gpio编号
    gpiod_put(desc);

}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值