若该文为原创文章,转载请注明原文出处
记录T31 GPIO控制过程, 此方法也适用海思等芯片。
1、硬件:T31X+SC5235
2、开发环境: ubuntu16.04-64bit
3、编译器:mips-gcc540-glibc222-32bit-r3.3.0.tar.gz
注:板子和和WIFI模块是某淘上淘的,使用的是RTL8188,使用的是USB接口,uboot和内核是自己裁剪移植的,内核默认自带WIFI驱动,所以不用移植可以直接使用。
GPIO具有输入输出,复用的功能。ISVP使用Linux标准的GPIOLIB接口。GPIOLIB提供了统一的GPIO申请/释放/设置/获取接口。
如果是User space 需要操作GPIO,有两种 方法可以选择:
A. 通过sysfs GPIO 接口进行操作
B. 应用程序调用相关的驱动,驱动中实现GPIO的设置
个人使用的是A方法sysfs GPIO,只记录sysfs GPIO的操作过程。
执行make menuconfig命令
- Device Drivers --->
- -*- GPIO Support --->
- [*] /sys/class/gpio/... (sysfs interface)
一般情况下,内核默认配置。
申请GPIO
- $ cd /sys/class/gpio
- $ echo [gpio_num] > export #申请 GPIO
释放GPIO
- $ cd /sys/class/gpio
- $ echo [gpio_num] > unexport #释放 GPIO
注:gpio_num即GPIO号,计算公式为:
PA(n) = 0*32 + n
PB(n) = 1*32 + n
...
申请后会在/sys/class/gpio目录下生成 gpioN目录,进入其目录,
- $ echo out > direction #设置 PB10 为输出模式
- $ echo in > direction #设置 PB10 为输入模式
设置电平
在gpioN目录下有active_low节点,直接操作就可以
- $ echo 0 > active_low #value 是 0,表示低电平。value 是 1,表示高电平
- $ echo 1 > active_low #value 是 1,表示低电平。value 是 0,表示高电平
读取电平
在gpioN目录下有value节点。
- $ cat value #读取电平(输入模式)
- $ echo 0 > value #设置电平(输出模式)
此程序只是一个架构,需要根据实际情况修改GPIO, 只作参考。
- 涉及函数:
- gpio_read();
- gpio_write();
- gpio_devmem();
- gpio_init();
- gpio_deInit();
源码:
- #include <unistd.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include <stdlib.h>
- #include <pthread.h>
-
- #include "gpio.h"
-
- static int g_gpio_state = 0;
- pthread_mutex_t g_gpio_mutex;
-
- /* GPIO结构体定义 */
- struct __gpio_t
- {
- int pins_name;
- int addr;
- int bit_mask;
- int value;
- int direction;
- };
-
- static struct __gpio_t gpio[1] =
- {
- {0, 0x99000050, 0x3, 0x0, GPIO_DIRECTION_OUTPUT}, // 0
- };
-
- int gpio_init()
- {
- qgpio_deInit();
- pthread_mutex_init(&g_gpio_mutex, NULL);
-
- pthread_mutex_lock(&g_gpio_mutex);
- g_gpio_state = 1;
-
-
- sprintf(cmd, "devmem 0x%x", gpio[0].addr);
- if (gpio_devmem(cmd, &num) != 0)
- {
- printf("i(%d) qh_gpio_devmem() error!\n", i);
- continue;
- }
- num &= (~(gpio[0].bit_mask));
- num |= gpio[0].value;
-
- sprintf(cmd, "devmem 0x%x 32 0x%x", gpio[0].addr, num);
- system(cmd);
-
- pin_num = 0;
- sprintf(cmd, "echo %d > /sys/class/gpio/export", pin_num); /* 申请GPIO */
- system(cmd);
-
- if (gpio[0].direction == GPIO_DIRECTION_OUTPUT) /* 设置为输出模式 */
- {
- sprintf(cmd,"echo out > /sys/class/gpio/gpio%d/direction", pin_num);
- system(cmd);
- }
- else if (gpio[0].direction == GPIO_DIRECTION_INPUT) /* 设置为输入模式 */
- {
- sprintf(cmd,"echo in > /sys/class/gpio/gpio%d/direction", pin_num);
- system(cmd);
- }
-
-
- pthread_mutex_unlock(&g_gpio_mutex);
-
- /* IO初始化 */
-
-
- return 0;
- }
-
- int qh_gpio_deInit(void)
- {
- if (g_gpio_state)
- {
- pthread_mutex_destroy(&g_gpio_mutex);
- g_gpio_state = 0;
- }
-
- return 0;
- }
-
- int gpio_read(int pins_name, char *value)
- {
- char open_cmd[50];
- memset(open_cmd, 0, sizeof(open_cmd));
- sprintf(open_cmd, "/sys/class/gpio/gpio%d/value", pins_name);
-
- pthread_mutex_lock(&g_gpio_mutex);
- FILE* fp = fopen(open_cmd, "r");
- if (fp == NULL)
- {
- fprintf(stderr, "open /sys/class/gpio/gpio/value error\n");
- pthread_mutex_unlock(&g_gpio_mutex);
- return -1;
- }
- char level = -1;
- int size = fread(&level, 1, 1, fp);
- if (size < 1)
- {
- fprintf(stderr, "fread error\n");
- fclose(fp);
- pthread_mutex_unlock(&g_gpio_mutex);
- return -1;
- }
- *value = level;
- fclose(fp);
- pthread_mutex_unlock(&g_gpio_mutex);
- return 0;
- }
-
- int gpio_write(int pins_name,char value)
- {
- char open_cmd[50];
- char buf[8];
- memset(buf, 0, sizeof(buf));
- sprintf(buf, "%d", value);
- memset(open_cmd, 0, sizeof(open_cmd));
- sprintf(open_cmd, "/sys/class/gpio/gpio%d/value", pins_name);
-
- pthread_mutex_lock(&g_gpio_mutex);
-
- int fd = open(open_cmd, O_RDWR);
- if (fd < 0)
- {
- fprintf(stderr, "open /sys/class/gpio/gpio/value error\n");
- pthread_mutex_unlock(&g_gpio_mutex);
- return -1;
- }
- int size = write(fd, buf, 1);
- if (size < 1)
- {
- fprintf(stderr, "write error\n");
- close(fd);
- pthread_mutex_unlock(&g_gpio_mutex);
- return -1;
- }
- close(fd);
- pthread_mutex_unlock(&g_gpio_mutex);
- return 0;
- }
-
- int gpio_devmem(char* str_cmd, int* value)
- {
- FILE* p_file = NULL;
- char buf[12] = {0};
- int tmp = 0;
- if (str_cmd == NULL)
- {
- fprintf(stderr, "str_cmd is NULL\n");
- return -1;
- }
- if((p_file = popen(str_cmd, "r")) == NULL)
- {
- printf("popen() error!\n");
- pclose(p_file);
- return -1;
- }
- if (fgets(buf, 12, p_file) == NULL)
- {
- printf("fgets() error!\n");
- pclose(p_file);
- return -1;
- }
- tmp = strtol(buf, NULL, 16);
- *value = tmp;
- pclose(p_file);
- return 0;
- }
程序只是一个思路,并未测试。代码有在T31X测试过,需要修改GPIO的相关参数,个人原因不公布,使时时需要把初始化相关的参数修改成所使用的GPIO相关参数。
1、system函数使用,在嵌入式中很常用到。
2、pthread_mutex_t的使用。
如有侵权,请及时联系博主删除,VX:18750903063