缺
通过在用户空间上来操作GPIO,控制入口在:/sys/class/gpio/。
首先确认内核里是否已选择上gpiolib的sysfs接口功能(默认是已选择上的)
make kernel_menuconfig
->Device Drivers->GPIO Support
->/sys/class/gpio/... (sysfs nterface)。
在linux内核源码里gpio口对应的序号,这个是由芯片厂家自定义的,通常在”arch/arm/mach-xxx/include/mach/gpio.h”里.
h3的gpio口定义在”arch/arm/mach-sunxi/include/mach/gpio.h”
#define SUNXI_BANK_SIZE 32
#define SUNXI_PA_BASE 0
#define SUNXI_PB_BASE 32
#define SUNXI_PC_BASE 64
#define SUNXI_PD_BASE 96
#define SUNXI_PE_BASE 128
#define SUNXI_PF_BASE 160
#define SUNXI_PG_BASE 192
#define SUNXI_PH_BASE 224
#define SUNXI_PI_BASE 256
#define SUNXI_PJ_BASE 288
#define SUNXI_PK_BASE 320
#define SUNXI_PL_BASE 352
#define SUNXI_PM_BASE 384
#define SUNXI_PN_BASE 416
#define SUNXI_PO_BASE 448
#define AXP_PIN_BASE 1024
#define SUNXI_PIN_NAME_MAX_LEN 8
/* pin group base number name space,
* the max pin number : 26*32=832.
*/
#define SUNXI_PINCTRL "sunxi-pinctrl"
#define SUNXI_BANK_SIZE 32
#define SUNXI_PA_BASE 0
#define SUNXI_PB_BASE 32
#define SUNXI_PC_BASE 64
#define SUNXI_PD_BASE 96
#define SUNXI_PE_BASE 128
#define SUNXI_PF_BASE 160
#define SUNXI_PG_BASE 192
#define SUNXI_PH_BASE 224
#define SUNXI_PI_BASE 256
#define SUNXI_PJ_BASE 288
#define SUNXI_PK_BASE 320
#define SUNXI_PL_BASE 352
#define SUNXI_PM_BASE 384
#define SUNXI_PN_BASE 416
#define SUNXI_PO_BASE 448
#define AXP_PIN_BASE 1024
#define SUNXI_PIN_NAME_MAX_LEN 8
/* sunxi gpio name space */
#define GPIOA(n) (SUNXI_PA_BASE + (n))
#define GPIOB(n) (SUNXI_PB_BASE + (n))
#define GPIOC(n) (SUNXI_PC_BASE + (n))
#define GPIOD(n) (SUNXI_PD_BASE + (n))
#define GPIOE(n) (SUNXI_PE_BASE + (n))
#define GPIOF(n) (SUNXI_PF_BASE + (n))
#define GPIOG(n) (SUNXI_PG_BASE + (n))
#define GPIOH(n) (SUNXI_PH_BASE + (n))
#define GPIOI(n) (SUNXI_PI_BASE + (n))
#define GPIOJ(n) (SUNXI_PJ_BASE + (n))
#define GPIOK(n) (SUNXI_PK_BASE + (n))
#define GPIOL(n) (SUNXI_PL_BASE + (n))
#define GPIOM(n) (SUNXI_PM_BASE + (n))
#define GPION(n) (SUNXI_PN_BASE + (n))
#define GPIOO(n) (SUNXI_PO_BASE + (n))
#define GPIO_AXP(n) (AXP_PIN_BASE + (n))
gpio口的操作过程,如控制status-led(接在PA15)的亮灭.
1 让gpiolib导出PA15的控制文件. 可根据上面检出PA15引脚对应的gpio口序号为15
echo 15 > /sys/class/gpio/export
操作完成后,应会在/sys/class/gpio/目录下生成一个gpio15的子目录.
2 在/sys/class/gpio/gpio15目录有文件:
/mnt/kernel_coding # ls /sys/class/gpio/gpio15/
active_low direction edge value
//通过direction文件可控制gpio口是作输入或输出功能
// echo "high" > /sys/class/gpio/gpio15/direction 是让gpio口作输出,并输出高电平
// echo "out" > /sys/class/gpio/gpio15/direction 是作输出功能,并输出低电平
// echo "in" > /sys/class/gpio/gpio15/direction 是作输入功能
//通过value文件可以获取和控制gpio口的电平(当gpio口作输出时,可以通过写操作改变电平。当作输入时,可以通过读操作获取电平)
// echo "1" > /sys/class/gpio/gpio15/value 让gpio口输出高电平
// echo "0" > /sys/class/gpio/gpio15/value 让gpio口输出低电平
//通过edge文件, 可以指定gpio作中断功能,并指定它的触发电平和获取. 触发电平方式有("none", "falling", "rising", "both")
//通过active_low文件,可以指定往value文件写1时为有效电平.
如: echo "1" > /sys/calss/gpio/gpio15/value时是输出高电平的
当echo "1" > /sys/calss/gpio/gpio15/active_low后, 再往value写1是就是输出低电平了.
int init_gpio_export(int gpio)
{
FILE *p = NULL;
p = fopen(GPIO_EXPORT_PATH, "w");
if(p == NULL)
{
GPIO_KEY_DEBUG("gpio%d init_gpio_key_export error!!\n", gpio);
}
else
{
fprintf(p, "%d", gpio);
fclose(p);
}
return 0;
}
int set_gpio_direction(int gpio, int direction)
{
FILE *p = NULL;
char gpio_direction_path[50];
sprintf(gpio_direction_path, GPIO_DIRECTION_PATH, gpio);
p = fopen(gpio_direction_path, "w");
if(p != NULL)
{
if(direction == DIRECTION_IN)
{
fprintf(p, "in");
}
else
{
fprintf(p, "out");
}
fclose(p);
}
else
{
GPIO_KEY_DEBUG("gpio%d set_gpio_direction error", gpio);
}
return 0;
}
int set_gpio_value(int gpio, int value)
{
FILE *p = NULL;
char gpio_value_path[50];
sprintf(gpio_value_path, GPIO_VALUE_PATH, gpio);
p = fopen(gpio_value_path, "w");
if(p != NULL)
{
fprintf(p, "%d", value);
fclose(p);
}
return 0;
}
int get_gpio_value(int gpio)
{
FILE *p = NULL;
char gpio_value_path[50];
char i[100]={0,};
int value = 1;
sprintf(gpio_value_path, GPIO_VALUE_PATH, gpio);
p = fopen(gpio_value_path, "r");
if(p != NULL)
{
fseek(p , 0 , 0);
fread(i , 1, 1 ,p);
//GPIO_KEY_DEBUG("gpio state = %c \r\n",i[0]);
if(i[0] == '0')
{
value = 0;
}
else
{
value = 1;
}
/*Note that you must close it here, then re-open it when you read it again,
so that only the content will be updated.*/
fclose(p);
}
else
{
value = -1;
GPIO_KEY_DEBUG("gpio%d get_gpio_value value failed\n", gpio);
}
return value;
}