Linux GPIO 使用说明


一、GPIO是什么?

GPIO 是 General-purpose input/output 的简写,意为通用的IO口,使用方法主要如下,一般情况下包含有如下的功能:

1. 电平输出功能,可以输出高电平和低电平。
2. 输入功能,可以作为输入口,用来检测外部电平。
3. 中断功能,可以作为中断口,配置后用来响应外部输入的中断的信号,用来触发对应的中断服务,一般包括:电平中断、边沿触发等。
4. 其他可复用的功能。

二、Linux 系统的GPIO控制代码在哪里?

标准头文件

<linux/gpio.h> <asm-generic/gpio.h>

实现文件为

<driver/gpio/gpiolib.c>

三、如何使用GPIO口?

1. GPIO的定义和获取GPIO号

1) GPIO的定义都是在dts文件中,类似以下的方式定义

    gpio_sensor_ctl {
        compatible = "sensor_ctl";
        sensor_ctl_io = <&gpio1 GPIO_B2 GPIO_ACTIVE_HIGH>;
        status = "okay";
    };
    

其中 sensor_ctl_io = <&gpio1 GPIO_B2 GPIO_ACTIVE_HIGH>; 行,为GPIO的定义。

2) 代码内获取GPIO口,代码如下:

   unsigned sensor_ctl_io;
   struct device_node *sensor_np = pdev->dev.of_node;
   unsigned long irq_flags;
   sensor_ctl_io = of_get_named_gpio_flags(sensor_np, "sensor_ctl_io", 0, &irq_flags);
   

其中sensor_ctl_io即获取到GPIO号,函数原型为:

   int of_get_named_gpio_flags(struct device_node *np, const char *propname,
                               int index, enum of_gpio_flags *flags);   
   

注意:要根据名字获取对应的GPIO号,还有匹配驱动的compatible值,此部分本文略过不说,下次说明。

2. 申请,释放GPIO,配置GPIO方向和电压

1) 申请GPIO

gpio_request(gpio_num, "xx gpio");  //申请GPIO, 返回0为申请成功,否则失败。

2) 配置GPIO方向

int gpio_direction_input(unsigned gpio);//设置为输入
   int gpio_direction_output(unsigned gpio, int value);//设置为输出,并初始化值为value.
   

3) 输入时,获取GPIO的值

int gpio_get_value(unsigned gpio);//返回value
   int gpio_get_value_cansleep(unsigned gpio);//输入端口:返回零或非零,可能睡眠
   

4) 输出时,配置输出值。

gpio_set_value(unsigned gpio, int value);//设置值
   void gpio_set_value_cansleep(unsigned gpio, int value);//输出端口设置值:可能睡眠
   

5) 释放GPIO

 void gpio_free(unsigned gpio);
   

6) 检查GPIO口是否有效

 int gpio_is_valid(int number);//检测此gpio口是否有效
   

7) GPIO作为中断使用,只有做为输入脚的GPIO才能做为中断脚,将GPIO配置成中断按照如下方式:

 gpio_to_irq(unsigned gpio);

Linux 内核 DTS ( Device Tree System ) 详解 — 基础篇


Linux Device Tree System (简称dts系统)是Linux社区的大牛们参考了PowerPC等体系架构中使用的Flattened Device Tree( FDT )采用Linux Device Tree System结构,许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码。

Linux Device Tree System是一种描述硬件的数据结构,由一系列被命名的节点(node)和属性(property)组成,而结点本身可包含子结点。所谓属性,其实就是成对出现的名称和值,在Linux Device Tree System中,可描述的信息包括:CPU的数量和类别,内存基地址和大小,总线和桥,外设连接,中断控制器和中断使用情况,GPIO控制器和GPIO使用情况,Clock控制器和Clock使用情况。

通常由.dts文件以文本方式对系统设备树进行描述,经过Device Tree Compiler(dtc)将dts文件转换成二进制文件binary device tree blob(dtb),.dtb文件可由Linux内核解析,有了device tree就可以在不改动Linux内核的情况下,对不同的平台实现无差异的支持,只需更换相应的dts文件,即可满足。
继续阅读“Linux 内核 DTS ( Device Tree System ) 详解 — 基础篇”

Linux 内核的编译详细说明


到www.kernel.org主页下载到需要的内核后,按照Android 编译环境的配置的方法配置好编译环境就可以进行内核的编译,这里针对内核部分进行详细说明。

主要步骤

解压内核:按照记录:常用的shell指令(持续更新)第七条所述解压的方法对已经下载好的内核进行解压,一般解压指令如下:

tar -zxvf  linux-xxx.xx.tar.gz -C ./


清除前期残留:一般初次编译不需要清除,但多次编译或者修改较大时需要清除后编译,输入:make mrproer,另外根据情况不同,会有三种不同的清除方式,第二条会详细讲解。


修改配置编译:执行make xconfig(图形化界面) 或者 make menuconfig (菜单界面),修改对应的配置并保存。


设置文件关联:make dep 建立文件依赖关系(Linux-2.6内核以后,编译内核不再需要先执行这个命令)。


编译:输入 make zImage -j12 进行编译,编译完成后在arch/<CPU>/boot目录下就能找到编译完成的image文件。


ARM平台编译步骤:

make clean
make meunconfig ARCH=arm
make uImage ARCH=arm CROSS_COMPILE=arm-linux-

make clean / mrproper /distclean的区别:

make clean — 删除多余的产生文件,保存.config

make mrporper — 删除所有的产生文件和.config

make distclean — 删除所有产生文件、.config和编辑备份文件补丁等。


 

Linux内核启动过程


在Bootloader将 Linux 内核映像拷贝到 RAM 以后,可以通过下例代码启动 Linux 内核:

call_linux(0, machine_type, kernel_params_base)

其中,machine_tpye 是Boot Loader检测出来的处理器类型, kernel_params_base 是启动参数在 RAM 的地址。通过这种方式将 Linux 启动需要的参数从 Boot Loader传递到内核。
继续阅读“Linux内核启动过程”