新闻  |   论坛  |   博客  |   在线研讨会
NXP iMX8 嵌入式Linux下Libgpiod 应用示例
toradex | 2020-07-01 11:38:58    阅读:303   发布文章

By Toradex秦海

1). 简介

NXP iMX8NXP去年底发布的基于Cortex-A72/A53Coretex-M4异构多核架构的ARM处理器,本文就基于嵌入式Linux演示GPIO相关应用示例。

 

本文所演示的ARM平台来自于Toradex 基于NXP iMX8QM ARM处理器的Apalis iMX8QM ARM嵌入式平台。

 

2). 准备

a). Apalis iMX8QM ARM核心版配合Apalis Evaluation Board载板,连接调试串口UART1(载板X29)到开发主机方便调试。

 

b). Apalis iMX8 Cortex-A核心安装Toradex Ycoto Linux Console image V3.04版本,详细信息请参考这里

 

d). Apalis Evaluation Board GPIO相关硬件连接

X2 MXM_3 <-> X34 LED1

X2 MXM_5 <-> X34 SW5

X2 MXM_11 <-> X34 SW1

 

 

3). GPIO 命令行测试

a). 嵌入式Linux系统下之前呗广泛应用的GPIO工具为sysfs GPIO接口(/sys/class/gpio),但是目前这个项目已经处于deprecated状态,经Linux Kernel Community确定其替代者就是GPIO字符设备API Libgpiod。因此,尽管本文测试使用的Toradex Ycoto Linux Console image V3.04版本依然支持sysfs GPIO接口,但是已经不建议使用,如果需要相关说明,可以参考这里。本文接下来的测试都是基于Libgpiod来进行。

 

b). GPIO 数字编码

./ ARM SOC定义GPIO管脚通常为一串字母数字的组合,之前sysfs API操作时候需要将不同SOC GPIO的字母数字命名转换为纯数字编码,对于不同的SOC转换规则的详细说明请见这里,而本文使用的libgpiod API则直接可以按照GPIO命名进行操作,更为直观和便利。

./ 首先根据 Apalis iMX8 datasheet 4.4章节的表格,找出所需要GPIO管脚的字母数字组合命名,比如本文涉及的三个GPIO管脚;在接下来的Libgpiod API中都需要使用对应的GPIO命名中的<controller><gpio>这两个参数来操作对应的GPIO管脚

### GPIO字符数次串命名规则:LSIO.GPIO<controller>.IO<gpio>

X2 MXM_3 -> LSIO.GPIO0.IO09

X2 MXM_5 -> LSIO.GPIO0.IO12

X2 MXM_11 -> LSIO.GPIO4.IO01

 

c). 在具体调试GPIO之前,还需要确认在Linux kernel device tree中,这个管脚被定义为GPIO且并没有被其他驱动功能占用,否则在具体操作GPIO的时候会出现冲突导致异常,关于device tree的说明本文不赘述,可以参考这里。本文所涉及的三个GPIO管脚默认即配置为GPIO,因此无需修改。

 

d). 调用Libgpiod API在命令行下进行GPIO测试

./ Apalis iMX8 上电开机进入嵌入式Linux系统,下面操作在调试串口下进行

./ 罗列GPIO banks,也就是对应的上面提到的controller。可以看到有8banks,每个banks包含32 lines,也就是32 gpio。当然,实际上结合具体的SOC和模块定义,不一定每个bankslines都有对应的GPIO管脚,有效的肯呢个只是一部分。

-----------------------------------

root@apalis-imx8:~# gpiodetect

gpiochip0 [5d080000.gpio] (32 lines)

gpiochip1 [5d090000.gpio] (32 lines)

gpiochip2 [5d0a0000.gpio] (32 lines)

gpiochip3 [5d0b0000.gpio] (32 lines)

gpiochip4 [5d0c0000.gpio] (32 lines)

gpiochip5 [5d0d0000.gpio] (32 lines)

gpiochip6 [5d0e0000.gpio] (32 lines)

gpiochip7 [5d0f0000.gpio] (32 lines)

-----------------------------------

./ 查看某个bank具体GPIO lines的情况,可以查看系统中当前哪些GPIO被占用了。

-----------------------------------

root@apalis-imx8:~# gpioinfo 0

gpiochip0 - 32 lines:

        line   0:      unnamed       unused   input  active-high

        line   1:      unnamed       unused   input  active-high

        line   2:      unnamed       unused   input  active-high

        line   3:      unnamed       unused   input  active-high

        line   4:      unnamed       unused   input  active-high

        line   5:      unnamed       unused   input  active-high

        line   6:      unnamed       unused   input  active-high

        line   7:      unnamed       unused   input  active-high

        line   8:      unnamed       unused  output  active-high

        line   9:      unnamed       unused  output  active-high

        line  10:      unnamed       unused   input  active-high

        line  11:      unnamed       unused   input  active-high

        line  12:      unnamed       unused   input  active-high

        line  13:      unnamed       unused   input  active-high

        line  14:      unnamed       unused   input  active-high

        line  15:      unnamed       unused   input  active-high

        line  16:      unnamed       unused   input  active-high

        line  17:      unnamed       unused   input  active-high

        line  18:      unnamed       unused   input  active-high

        line  19:      unnamed       unused   input  active-high

        line  20:      unnamed       unused   input  active-high

        line  21:      unnamed       unused   input  active-high

        line  22:      unnamed       unused   input  active-high

        line  23:      unnamed       unused   input  active-high

        line  24:      unnamed       unused   input  active-high

        line  25:      unnamed       unused   input  active-high

        line  26:      unnamed       unused   input  active-high

        line  27:      unnamed       unused   input  active-high

        line  28:      unnamed       unused   input  active-high

        line  29:      unnamed       unused   input  active-high

        line  30:      unnamed      "reset"  output   active-low [used]

        line  31:      unnamed "usb3503 connect" output active-high [used]

-----------------------------------

./ 测试X2 MXM_3 管脚GPIO output操作,gpioset命令的作用就是设置对应GPIO管脚为输出状态,并输出为设置的高或者低电平。

-----------------------------------

# 设置GPIO输出为高电平驱动LED点亮

root@apalis-imx8:~# gpioset 0 9=1

# 设置GPIO输出为低电平驱动LED熄灭                                                                                                                    

root@apalis-imx8:~# gpioset 0 9=0

# 通过 gpioinfo查看bank0 可以发现line 9output状态

root@apalis-imx8:~# gpioinfo 0

gpiochip0 - 32 lines:

        ……

        line   9:      unnamed       unused  output  active-high

        ……

-----------------------------------

 

./ 测试X2 MXM_11 管脚GPIO input操作,gpioget命令的作用就是设置对应GPIO管脚为输入状态,并读取当前的GPIO电平。

-----------------------------------

# SW1 拨至低电平位置(靠近载板边缘),读取连接的X2 MXM_11GPIO电平

root@apalis-imx8:~# gpioget 4 1

0

# SW1 拨至高电平位置(远离载板边缘),读取连接的X2 MXM_11GPIO电平                                                                                                                     

root@apalis-imx8:~# gpioget 4 1

1

# 通过 gpioinfo查看bank4 可以发现line 1input状态

root@apalis-imx8:~# gpioinfo 4

gpiochip4 - 32 lines:

        ……

        line   1:      unnamed       unused  input  active-high

        ……

-----------------------------------

 

./ 测试X2 MXM_5 管脚GPIO 中断操作,gpiomon命令的作用就是设置对应的GPIO为输入状态,并监测对应GPIO管脚的事件(。

-----------------------------------

# 设置X2 MXM_5 管脚中断监测

root@apalis-imx8:~# gpiomon 0 12

# 按下SW5按键

event:  RISING EDGE offset: 12 timestamp: [1609840088.602076625]

# 松开SW5按键

event: FALLING EDGE offset: 12 timestamp: [1609840089.268163875]

# 通过 gpioinfo查看bank0 可以发现line 12input状态

root@apalis-imx8:~# gpioinfo 0

gpiochip0 - 32 lines:

        ……

        line   12:      unnamed       unused  input  active-high

        ……

-----------------------------------

 

 

4). GPIO C代码示例程序测试

a). 首先先在开发Linux 主机安装SDKSDK为按照这里说明通过Ycoto project/OpenEmbedded 环境编译得到,安装过程中根据提示可以自行更改SDK安装目录

-----------------------------------

$ chmod +x tdx-xwayland-glibc-x86_64-Qt5-Wayland-Image-aarch64-toolchain-2.6.4.sh

$ ./tdx-xwayland-glibc-x86_64-Qt5-Wayland-Image-aarch64-toolchain-2.6.4.sh

TDX Wayland with XWayland SDK installer version 2.6.4

=====================================================

Enter target directory for SDK (default: /opt/tdx-xwayland/2.6.4): <SDK_install_dir>

You are about to install the SDK to "<SDK_install_dir>". Proceed[Y/n]? Y

-----------------------------------

 

b). c代码示例1 - 测试X2 MXM_3 管脚输出循环驱动LED亮和灭,时间间隔为1s

./ 源代码参考如下

https://github.com/simonqin09/Apalis_iMX8_Libgpiod/blob/master/gpio-toggle/gpio-toggle.c

 

./ 主要说明如下

-----------------------------------

### include libgpiod 头文件

#include <gpiod.h>

 

### 定义GPIO chipline 结构体

struct gpiod_chip *output_chip;

struct gpiod_line *output_line;

 

### 配置GPIO为输出

output_chip = gpiod_chip_open_by_name(chip);

output_line = gpiod_chip_get_line(output_chip, offset);

gpiod_line_request_output(output_line, "gpio-toggle", GPIOD_LINE_ACTIVE_STATE_HIGH);

 

### 切换GPIO输出状态

int line_value = 0; OR ine_value = 1;

gpiod_line_set_value(output_line, line_value);

-----------------------------------

 

./ 编译,本示例使用通过命令行编译方式,详细说明请参考这里

-----------------------------------

### export SDK 环境变量

$ source <SDK_install_dir>/environment-setup-aarch64-tdx-linux

### 编译,因为需要gpiod库,因此要再link选项加入 -lgpiod 选项,否则会出现 ”undefined reference to …” 错误

$ cd <work_dir>

$ ${CC} -Wall -lgpiod -lpthread gpio-toggle.c -o gpio-toggle

### 部署

$ scp gpio-toggle root@<apalis_imx8_ipaddress>:/home/root

-----------------------------------

 

./ 测试,在Apalis iMX8上面运行刚编译部署好的 gpio-toggle 二进制程序,载板上面的LED1 LED灯会1s间隔亮和灭

-----------------------------------

root@apalis-imx8:~# cd /home/root/

root@apalis-imx8:~# ./gpio-toggle

Usage by bank/pin number:

        gpio-toggle OUTPUT-BANK-NUMBER OUTPUT-GPIO-NUMBER

root@apalis-imx8:~# ./gpio-toggle 0 9

LED turns ON

LED turns OFF

LED turns ON

LED turns OFF

……

-----------------------------------

 

 

 

c). c代码示例2 - 测试X2 MXM_5 管脚通过按键输入,捕获上升沿事件后切换X2 MXM_3输出状态驱动LED亮和灭

./ 源代码参考如下

https://github.com/simonqin09/Apalis_iMX8_Libgpiod/blob/master/gpiotest/gpiotest.c

 

./ 主要说明如下

-----------------------------------

### include libgpiod 头文件

#include <gpiod.h>

 

### 定义GPIO chipline 以及event结构体

struct gpiod_chip *input_chip;

struct gpiod_line *input_line;

struct gpiod_line_event event;

 

### 配置GPIO为输入,中断事件为上升沿

input_chip = gpiod_chip_open_by_name(chip);

input_line = gpiod_chip_get_line(input_chip, offset);

gpiod_line_request_rising_edge_events(input_line, "gpiotest");

 

### GPIO输入事件响应

while (1) {

         gpiod_line_event_wait(input_line, NULL);

 

         if (gpiod_line_event_read(input_line, &event) != 0)

                   continue;

 

         /* this should always be a rising event in our example */

         if (event.event_type != GPIOD_LINE_EVENT_RISING_EDGE)

                   continue;

……

}

-----------------------------------

 

./ 编译,本示例使用通过Eclipse IDE工具进行编译,详细Eclipse IDE 下载安装以及SDK配置说明请参考这里

-----------------------------------

### export SDK 环境变量

$ source <SDK_install_dir>/environment-setup-aarch64-tdx-linux

### 在同一个终端中启动Eclopse IDE

$ cd <Eclipse_install_dir>

$ ./eclipse

### Eclipse IDE下参考上面的说明文档创建新的C/cross compile工程,并按照说明文档配置好SDK。同样因为linker需要gpiod相关库,因此要在下面位置增加相关库

菜单:

Project --> Properties

选项卡:

C/C++ Build --> Settings

选项:

Cross GCC Linker --> Libraries

Libraries (-l) 栏目下面增加:

gpiod

### Eclipse 点击build进行编译,根据选择是Debug还是Release,编译后的二进制文件会在对应的目录,本文使用Debug

### 部署

$ cd <Eclipse_workspace>/gpiotest/Debug

$ scp gpiotest root@<apalis_imx8_ipaddress>:/home/root

-----------------------------------

 

./ 测试,在Apalis iMX8上面运行刚编译部署好的 gpiotest 二进制程序,载板上面的LED1 LED灯初始状态为灭,随着按下SW5按键交替亮和灭

-----------------------------------

root@apalis-imx8:~# cd /home/root/

root@apalis-imx8:~# ./gpiotest

Usage by bank/pin number:

        gpio-test INPUT-BANK-NUMBER INPUT-GPIO-NUMBER OUTPUT-BANK-NUMBER OUTPUT-GPIO-NUMBER

root@apalis-imx8:~# ./gpiotest 0 12 0 9

LED initial status is OFF

button pressed 1 times

LED turns ON

button pressed 2 times

LED turns OFF

button pressed 3 times

LED turns ON

……

-----------------------------------

 

 

5). 总结

本文基于NXP iMX8示例了嵌入式Linux使用Libgpiod API来驱动GPIO,通过示例可见其直观性和便利性均大大优于传统的 sysfs API,因此会被 Linux Kernel Community确定为 sysfs API的替代者。


*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客