Linux 内核层和 用户层 配置 GPIO 引脚

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

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

soc {
                .
                .
                .
        gpio0: [email protected]****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  目录下如下所示 :

[email protected]:/sys/class/gpio# ls
export         gpiochip361  gpiochip419  gpiochip453  gpiochip496
gpiochip357  gpiochip393  gpiochip437  gpiochip468  unexport

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

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

[email protected]:/sys/class/gpio# echo 475 > export

会对应生成 gpio475 目录

[email protected]:/sys/class/gpio/gpio475# ls
active_low  device  direction  edge  power  subsystem  uevent  value

通过

[email protected]:/sys/class/gpio/gpio475# echo 1 >value
[email protected]-x:/sys/class/gpio/gpio475# echo 0 >value
[email protected]-x:/sys/class/gpio/gpio475# echo "in" > direction
[email protected]-x:/sys/class/gpio/gpio475# echo "out" > direction 

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

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

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

时间: 2024-11-09 22:30:49

Linux 内核层和 用户层 配置 GPIO 引脚的相关文章

linux内核空间与用户空间信息交互方法

linux内核空间与用户空间信息交互方法 本文作者: 康华:计算机硕士,主要从事Linux操作系统内核.Linux技术标准.计算机安全.软件测试等领域的研究与开发工作,现就职于信息产业部软件与集成电路促进中心所属的MII-HP Linux软件实验室.如果需要可以联系通过[email protected]联系他. 摘要:在进行设备驱动程序,内核功能模块等系统级开发时,通常需要在内核和用户程序之间交换信息.Linux提供了多种方法可以用来完成这些任务.本文总结了各种常用的信息交换方法,并用简单的例子

向Windows内核驱动传递用户层定义的事件Event,并响应内核层的通知

完整的程序在下载:http://download.csdn.net/detail/dijkstar/7913249 用户层创建的事件Event是一个Handle句柄,和内核中的创建的内核模式下的KEVENT是一个东西.因此,在应用层创建的事件,可以在内核层获得并使用.这一部分的原理,见张帆编著的<Windows驱动技术详解>章节8.5.4,P237页: 程序是来自于<Windows驱动技术详解>章节8.5.4(驱动程序和应用程序交互事件对象)和章节10.2.1(DPC定时器). 首

Linux内核工程导论——用户空间设备管理

用户空间设备管理 用户空间所能见到的所有设备都放在/dev目录下(当然,只是一个目录,是可以变化的),文件系统所在的分区被当成一个单独的设备也放在该目录下.以前的2.4版本的曾经出现过devfs,这个思路非常好,在内核态实现对磁盘设备的动态管理.可以做到当用户访问一个设备的设备的时候,devfs驱动才会去加载该设备的驱动.甚至每个节点的设备号都是动态获得的.但是该机制的作者不再维护他的代码,linux成员经过讨论,使用用户态的udev代替内核态的devfs,所以现在的devfs已经废弃了.用户态

enc28j60网卡驱动模块添加进linux内核,Kconfig,Makefile配置过程

这里是要把http://www.cnblogs.com/hackfun/p/6260396.html中的enc28j60网卡驱动模块,添加到2.6.22.6内核中,这个模块代码不需要任何修改.只需要在内核目录下的相关配置脚本文件,如Makefile,Kconfig,.config等,修改某些配置就行. enc28j60网卡驱动模块使用到的几个文件: enc28j60.c enc28j60_hw.h spi_bitbang.c spi_s3c24xx.c spi_platform_dev.c 实际

Linux内核中断引入用户空间(异步通知机制)【转】

转自:http://blog.csdn.net/kingdragonfly120/article/details/10858647 版权声明:本文为博主原创文章,未经博主允许不得转载. 当Linux内核空间发生中断后怎么使用户空间的应用程序运行相应的函数呢,当芯片有数据到来时内核会产生一个中断,但是怎样通知应用程序来取数据,以前这个问题一直困扰我很长时间,后来发现linux中有异步通知机制,在用户程序中用signal注册一个响应SIGIO信号的回调函数,然后在驱动程序中向该进程发出SIGIO信号

Linux内核工程导论——用户空间进程使用内核资源

本文大部分转载和组装,只是觉得这些知识应该放到一起比较好. 进程系统资源的使用原理 大部分进程通过glibc申请使用内存,但是glibc也是一个应用程序库,它最终也是要调用操作系统的内存管理接口来使用内存.大部分情况下,glibc对用户和操作系统是透明的,所以直接观察操作系统记录的进程对内存的使用情况有很大的帮助.但是glibc自己的实现也是有问题的,所以太特殊情况下追究进程的内存使用也要考虑glibc的因素.其他操作系统资源使用情况则可以直接通过proc文件系统查看. 进程所需要的系统资源种类

【转】linux内核态和用户态的区别

原文网址:http://www.mike.org.cn/articles/linux-kernel-mode-and-user-mode-distinction/ 内核态与用户态是操作系统的两种运行级别,intel cpu提供Ring0-Ring3四种级别的运行模式.Ring0级别最高,Ring3最低. 当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态).此时处理器处于特权级最高的(0级)内核代码中执行.当进程处于内核态时,执行的内核代码会使用当前

Linux 内核信号量与用户态信号量(System V&amp;POSIX)总结

一.什么是信号量 信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有. 信号量的值为正的时候,说明它空闲.所测试的线程可以锁定而使用它.若为0,说明它被占用,测试的线程要进入睡眠队列中,等待被唤醒. 二.信号量的分类 在学习信号量之前,我们必须先知道——Linux提供两种信号量: (1) 内核信号量,由内核控制路径使用 (2) 用户态进程使用的信号量,这种信号量又分为POSIX信号量和SYSTEM V信号量. POSIX信号量又分为有名信号量和无名信号量. 有名信号

【转】 Linux 内核态与用户态

 内核态与用户态是操作系统的两种运行级别,一个运行在内核模式的进程可以执行指令集中的任何指令,并且可以访问系统中任何存储器位置.用户模式中的进程不允许执行特权指令,比如停止处理器.改变模式位,或者发起一个I/O操作.也不允许用户模式中的进程直接引用地址空间中内核区内的代码和数据. intel cpu提供Ring0-Ring3三种级别的运行模式.Ring0级别最高,Ring3最低.其中特权级0(Ring0)是留给操作系统代码,设备驱动程 序代码使用的,它们工作于系统核心态:而特权极3(Ring3)