LINUX GPIO 基操之应用层
注:所有文章基于linux-3.13 以上,本系列主要介绍 GPIO的一些基本知识,驱动操作GPIO的接口,应用层通过sysfs操作GPIO的接口,GPIO一些debug信息查看,以及对高通相关GPIO的寄存器操作。分享给刚刚接触外设bsp的小伙伴们。当然后面有时间还会分享GPIO子系统框架和pinctrl子系统框架,先知道黑盒怎么使用,然后咱再打开仔细瞅瞅。有错误不正当点,勿喷,还请指出,一起修改,谢谢!!
本篇为应用层控制接口篇,主要分享,应用层对gpio的操作和如何通过寄存器操作gpio(主要介绍高通的寄存器方式)。
应用层sysfs操作GPIO
相关文件节点介绍
1)导出节点
//下面的动作前提是要先导出对应的gpio,动态生成了对应的节点才能下一步操作
echo 1 > /sys/class/gpio/export
2) 设置输入方向,读取对应的值
echo in > /sys/class/gpio/gpio1/direction
cat /sys/class/gpio/gpio1/value
3)设置输出方向,设置对应的值
echo out > /sys/class/gpio/gpio1/direction
//拉高
echo 1 > /sys/class/gpio/gpio1/value
//拉低
echo 1 > /sys/class/gpio/gpio1/value
4) 设置中断触发方式
//设置的中断触发方式 none rising falling both,
echo none > /sys/class/gpio/gpio1/edge
// 要结合poll机制来获取对应gpio口的中断
5)销毁对应GPIO节点
echo 1 > /sys/class/gpio/unexport
如何编写应用程序操作GPIO
我们完全可以通过调用system的方式实现上面提到的前三种操作,但是无法实现中断的监控,而且system方式太消耗资源。linux里面万物皆文件,下面重点介绍如何通过open,write,poll等方式对gpio进行操作。
1)需要包含的头文件
#include stdlib.h
#include stdio.h
#include string.h
#include unistd.h
#include fcntl.h
#include poll.h
2)导出一个节点
tatic int gpio_export(int pin)
{
char buffer[64];
int len;
int fd;
fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd < 0) {
MSG("Failed to open export for writing!\n");
return(-1);
}
len = snprintf(buffer, sizeof(buffer), "%d", pin);
if (write(fd, buffer, len) < 0) {
MSG("Failed to export gpio!");
return -1;
}
close(fd);
return 0;
}
3)销毁一个节点
static int gpio_unexport(int pin)
{
char buffer[64];
int len;
int fd;
fd = open("/sys/class/gpio/unexport", O_WRONLY);
if (fd < 0) {
MSG("Failed to open unexport for writing!\n");
return -1;
}
len = snprintf(buffer, sizeof(buffer), "%d", pin);
if (write(fd, buffer, len) < 0) {
MSG("Failed to unexport gpio!");
return -1;
}
close(fd);
return 0;
}
4)读写一个节点
static int gpio_read(int pin)
{
char path[64];
char value_str[3];
int fd;
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
fd = open(path, O_RDONLY);
if (fd < 0) {
MSG("Failed to open gpio value for reading!\n");
return -1;
}
if (read(fd, value_str, 3) < 0) {
MSG("Failed to read value!\n");
return -1;
}
close(fd);
return (atoi(value_str));
}
//value: 0-->LOW, 1-->HIGH
static int gpio_write(int pin, int value)
{
static const char values_str[] = "01";
char path[64];
int fd;
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
fd = open(path, O_WRONLY);
if (fd < 0) {
MSG("Failed to open gpio value for writing!\n");
return -1;
}
if (write(fd, &values_str[value == 0 ? 0 : 1], 1) < 0) {
MSG("Failed to write value!\n");
return -1;
}
close(fd);
return 0;
}
5) 设置方向
//dir: 0-->IN, 1-->OUT
static int gpio_direction(int pin, int dir)
{
static const char dir_str[] = "in\0out";
char path[64];
int fd;
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", pin);
fd = open(path, O_WRONLY);
if (fd < 0) {
MSG("Failed to open gpio direction for writing!\n");
return -1;
}
if (write(fd, &dir_str[dir == 0 ? 0 : 3], dir == 0 ? 2 : 3) < 0) {
MSG("Failed to set direction!\n");
return -1;
}
close(fd);
return 0;
}
6)中断方式设置
// none表示引脚为输入,不是中断引脚
// rising表示引脚为中断输入,上升沿触发
// falling表示引脚为中断输入,下降沿触发
// both表示引脚为中断输入,边沿触发
// 0-->none, 1-->rising, 2-->falling, 3-->both
static int gpio_edge(int pin, int edge)
{
const char dir_str[] = "none\0rising\0falling\0both";
char ptr;
char path[64];
int fd;
switch(edge){
case 0:
ptr = 0;
break;
case 1:
ptr = 5;
break;
case 2:
ptr = 12;
break;
case 3:
ptr = 20;
break;
default:
ptr = 0;
}
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/edge", pin);
fd = open(path, O_WRONLY);
if (fd < 0) {
MSG("Failed to open gpio edge for writing!\n");
return -1;
}
if (write(fd, &dir_str[ptr], strlen(&dir_str[ptr])) < 0) {
MSG("Failed to set edge!\n");
return -1;
}
close(fd);
return 0;
}
7)监控一个gpio中断
如何通过寄存器操作GPIO
首先来看gt对应的寄存器解释
然后就是使用devmem命令来对寄存器进行操作。注意要使用devmem必须打开内核宏CONFIG_DEVMEM。
注:下面都是以sm6350为例
1)打开CONFIG_DEVMEM
CONFIG_DEVMEM=y
- 控制GPIO1为输出高
devmem 0xf101000 4 0x200
devmem 0xf101004 4 0x2
3)控制GPIO1 为输出低
devmem 0xf101000 4 0x200
devmem 0xf101004 4 0x0
4)控制GPIO1 为输出上拉和输出下拉
//上拉
devmem 0xf101000 4 0x203
//下拉
devmem 0xf101004 4 0x201
5)控制GPIO1 为输入,同时读取其值
devmem 0xf101000 4 0x0
devmem 0xf101004 //读取对应的值,第一位为1 就是高,为0就是低
bg thanks!! ay
今天的文章linux gpiolib_简要描述gpio的配置步骤分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/83506.html