0 前言
本文描述如果通过文件IO sysfs方式控制3516 GPIO端口。通过sysfs方式控制GPIO,先访问/sys/class/gpio目录,向export文件写入GPIO编号,使得该GPIO的操作接口从内核空间暴露到用户空间,GPIO的操作接口包括direction和value等,direction控制GPIO方向,而value可控制GPIO输出或获得GPIO输入。
用户空间访问gpio,即通过sysfs接口访问gpio,下面是/sys/class/gpio目录下的三种文件:
—export/unexport文件
—gpioN指代具体的gpio引脚
—gpio_chipN指代gpio控制器
开始之前,首先看看系统中有没有“/sys/class/gpio”这个文件夹。
如果没有请在编译内核的时候加入 Device Drivers —> GPIO Support —> /sys/class/gpio/… (sysfs interface)
(1) export/unexport文件接口:
/sys/class/gpio/export,该接口只能写不能读。
用户程序通过写入gpio的编号来向内核申请将某个gpio的控制权导出到用户空间
比如 echo 19 > export
上述操作会为19号gpio创建一个节点gpio19,此时/sys/class/gpio目录下边生成一个gpio19的目录
/sys/class/gpio/unexport和导出的效果相反。
比如 echo 19 > unexport
上述操作将会移除gpio19这个节点。
(2) /sys/class/gpio/gpioN
指代某个具体的gpio端口,里边有如下属性文件
direction 表示gpio端口的方向,读取结果是in或out。该文件也可以写,写入out 时该gpio设为输出同时电平默认为低。写入low或high则不仅可以设置为输出 还可以设置输出的电平。 当然如果内核不支持或者内核代码不愿意,将不会存在这个属性,比如内核调用了gpio_export(N,0)就表示内核不愿意修改gpio端口方向属性 。
value 表示gpio引脚的电平,0(低电平)1(高电平),如果gpio被配置为输出,这个值是可写的,记住任何非零的值都将输出高电平, 如果某个引脚能并且已经被配置为中断,则可以调用poll(2)函数监听该中断,中断触发后poll(2)函数就会返回。
edge 表示中断的触发方式,edge文件有如下四个值:”none”, “rising”, “falling”,”both”。
none 表示引脚为输入,不是中断引脚;
rising 表示引脚为中断输入,上升沿触发;
falling 表示引脚为中断输入,下降沿触发;
both 表示引脚为中断输入,边沿触发;
这个文件节点只有在引脚被配置为输入引脚的时候才存在。 当值是none时可以通过如下方法将变为中断引脚。echo “both” > edge;对于是both,falling还是rising依赖具体硬件的中断的触发方式。此方法即用户态gpio转换为中断引脚的方式。
(3)/sys/class/gpio/gpiochipN
gpiochipN 表示的就是一个gpio_chip,用来管理和控制一组gpio端口的控制器,该目录下存在一下属性文件:
base 和N相同,表示控制器管理的最小的端口编号;
lable 诊断使用的标志(并不总是唯一的);
ngpio 表示控制器管理的gpio端口数量(端口范围是:N ~ N+ngpio-1)。
1 步骤解析与代码
首先需要了解:
引脚编号 = 控制引脚的寄存器基数 + 控制引脚寄存器位数
3516 GPIO口是分组的,一组8个口,例如GPIO9_3为 9组3口,其编号pin:9*8+3=75.
本文描述如果通过文件IO sysfs方式控制3516 GPIO端口。通过文件IO方式控制GPIO,完整的操作需要四个步骤:
- 访问/sys/class/gpio/export目录,向export文件写入GPIO编号,使得该GPIO的操作接口从内核空间暴露到用户空间;
- 选择GPIO接口方向(direction)输入/输出;
- 读取\写入GPIO寄存器的值;
- unexportq取消移除GPIO节点,与第一步相反。
1.1 向export文件写入GPIO编号
int GPIO_export(int pin){FILE* fp;char file_name[50];sprintf(file_name, "/sys/class/gpio/export");fp = fopen(file_name, "w");if (fp == NULL) {printf("Cannot open %s.\n", file_name);return -1;}fprintf(fp, "%d", pin);fclose(fp);return 0;}
1.2 选择GPIO接口方向
int GPIO_direction(int pin){FILE* fp;char file_name[50];sprintf(file_name, "/sys/class/gpio/gpio%d/direction", pin);fp = fopen(file_name, "rb+");if (fp == NULL) {printf("Cannot open %s.\n", file_name);return -1;}fprintf(fp, "in"); //输出则为“out”fclose(fp);return 0;}
1.3 读取或输入数值
int GPIO_value(int pin){FILE* fp;char file_name[50];int value;unsigned char buf[10];sprintf(file_name, "/sys/class/gpio/gpio%d/value", pin);fp = fopen(file_name, "rb+");if (fp == NULL) {printf("Cannot open %s.\n", file_name);return -1;}memset(buf, 0, 10);fread(buf, sizeof(char), sizeof(buf) - 1, fp);// 读取1字节数据,0/1.//printf("%s: gpio%d_%d = %d\n", __func__,gpio_chip_num, gpio_offset_num, buf[0]-48);value = buf[0] - 48;// 0的ASCII码为48,1的是49。这样将将字符串转化为数值fclose(fp);return value;}
int GPIO_value(int pin,int gpio_out_val ){FILE* fp;char file_name[50];int value;unsigned char buf[10];sprintf(file_name, "/sys/class/gpio/gpio%d/value", gpio_num);fp = fopen(file_name, "rb+");if (fp == NULL) {printf("Cannot open %s.\n", file_name);return -1;}if (gpio_out_val)strcpy(buf,"1");elsestrcpy(buf,"0");fwrite(buf, sizeof(char), sizeof(buf) - 1, fp);//写入1字节数据,0/1.//printf("%s: gpio%d_%d = %s\n", __func__,gpio_chip_num, gpio_offset_num, buf);fclose(fp);return 0;}
1.4 取消GPIO节点unexport
int GPIO_unexport(int pin){FILE* fp;char file_name[50];sprintf(file_name, "/sys/class/gpio/unexport");fp = fopen(file_name, "w");if (fp == NULL) {printf("Cannot open %s.\n", file_name);return -1;}fprintf(fp, "%d", pin);fclose(fp);return 0;}
2 全部代码
FILE* fp;char file_name[50];unsigned char buf[10];int GPIO_export(int pin){sprintf(file_name, "/sys/class/gpio/export");fp = fopen(file_name, "w");if (fp == NULL) {printf("Cannot open %s.\n", file_name);return -1;}fprintf(fp, "%d", pin);fclose(fp);return 0;}/******************************************* DIRECTION* ***************************************/int GPIO_direction(int pin){sprintf(file_name, "/sys/class/gpio/gpio%d/direction", pin);fp = fopen(file_name, "rb+");if (fp == NULL) {printf("Cannot open %s.\n", file_name);return -1;}fprintf(fp, "in");fclose(fp);return 0;}/******************************************* VALUE* ***************************************/int GPIO_value(int pin){int value;sprintf(file_name, "/sys/class/gpio/gpio%d/value", pin);fp = fopen(file_name, "rb+");if (fp == NULL) {printf("Cannot open %s.\n", file_name);return -1;}memset(buf, 0, 10);fread(buf, sizeof(char), sizeof(buf) - 1, fp);//printf("%s: gpio%d_%d = %d\n", __func__,gpio_chip_num, gpio_offset_num, buf[0]-48);value = buf[0] - 48;fclose(fp);return value;}int GPIO_unexport(int pin){sprintf(file_name, "/sys/class/gpio/unexport");fp = fopen(file_name, "w");if (fp == NULL) {printf("Cannot open %s.\n", file_name);return -1;}fprintf(fp, "%d", pin);fclose(fp);return 0;}void detect_GPIO(void){HI_S32 ret;HI_U32 SDI_GPIO_control_0 = 0;//GPIO9_3HI_U32 SDI_GPIO_control_1 = 0;//GPIO14_3HI_U32 SDI_GPIO_control_2 = 0;//GPIO14_2float fpga_bitrate = 0.0;unsigned int gpio_num9_3;unsigned int gpio_num14_3;unsigned int gpio_num14_2;while (1){gpio_num9_3 = 9 * 8 + 3;GPIO_export(gpio_num9_3);GPIO_direction(gpio_num9_3);SDI_GPIO_control_0 = GPIO_value(gpio_num9_3);GPIO_unexport(gpio_num9_3);/**************************************************************************************/gpio_num14_3 = 14 * 8 + 3;GPIO_export(gpio_num14_3);GPIO_direction(gpio_num14_3);SDI_GPIO_control_1 = GPIO_value(gpio_num14_3);GPIO_unexport(gpio_num14_3);/**************************************************************************************/gpio_num14_2 = 14 * 8 + 2;GPIO_export(gpio_num14_2);GPIO_direction(gpio_num14_2);SDI_GPIO_control_2 = GPIO_value(gpio_num14_2);GPIO_unexport(gpio_num14_2);// ret = HI_MPI_SYS_GetReg(0x201D0010, &SDI_GPIO_control_0);// if (ret != 0)// {// printf("GPIO9_3 -- SDI_GPIO_control[0] GetReg failed\n");// }// ret = HI_MPI_SYS_GetReg(0x20220010, &SDI_GPIO_control_1);// if (ret != 0)// {// printf("GPIO14_3 -- SDI_GPIO_control[1] GetReg failed\n");// }// ret = HI_MPI_SYS_GetReg(0x20220001, &SDI_GPIO_control_2);// if (ret != 0)// {// printf("GPIO14_2 -- SDI_GPIO_control[2] GetReg failed\n");// }fpga_bitrate = (SDI_GPIO_control_2 * 4 + SDI_GPIO_control_1 * 2 + SDI_GPIO_control_0) * 0.5;printf("++++++++++\n");printf("SDI_GPIO_control_0 : %d\n", SDI_GPIO_control_0);printf("SDI_GPIO_control_1 : %d\n", SDI_GPIO_control_1);printf("SDI_GPIO_control_2 : %d\n", SDI_GPIO_control_2);printf("fpga_bitrate : %f\n", fpga_bitrate);printf("----------\n");sleep(2);}}int main(){detect_GPIO();return 0;}
