GPIO控制程序说明
1.概述¶
本文档主要介绍PCUPID上如何通过配置padmux来实现gpio的复用功能,主要参考了《 GPIO使用说明》。
2.关键字¶
dts/dtsi:
Linux设备树文件,通常用于描述CPU所支持的外设,外设节点中包含的属性值可用于外设的配置。
padmux:
引脚复用,用于将模块功能引脚连接到具体的外部引脚上面,打通信号连接。
表1:PCUPID GPIO index与PAD对应表
Pad Name | GPIO Index | Pad Name | GPIO Index | Pad Name | GPIO Index | Pad Name | GPIO Index |
---|---|---|---|---|---|---|---|
PAD_UART0_TX | 0 | PAD_GPIOE_28 | 37 | PAD_GPIOB_04 | 74 | PAD_SAR_ADC0_05 | 111 |
PAD_PWM_OUT00 | 1 | PAD_GPIOA_00 | 38 | PAD_GPIOB_05 | 75 | PAD_SAR_ADC0_06 | 112 |
PAD_PWM_OUT01 | 2 | PAD_GPIOA_01 | 39 | PAD_GPIOB_06 | 76 | PAD_SAR_ADC0_07 | 113 |
PAD_SPI_CK | 3 | PAD_GPIOA_02 | 40 | PAD_GPIOB_07 | 77 | PAD_SAR_ADC0_08 | 114 |
PAD_SPI_HLD | 4 | PAD_GPIOA_03 | 41 | PAD_GPIOB_08 | 78 | PAD_SAR_ADC0_09 | 115 |
PAD_SPI_CZ | 5 | PAD_GPIOA_04 | 42 | PAD_OUTP_RX0_CH0 | 79 | PAD_SAR_ADC0_10 | 116 |
PAD_SPI_WPZ | 6 | PAD_GPIOA_05 | 43 | PAD_OUTN_RX0_CH0 | 80 | PAD_SAR_ADC0_11 | 117 |
PAD_SPI_DI | 7 | PAD_GPIOA_06 | 44 | PAD_OUTP_RX0_CH1 | 81 | PAD_SAR_ADC0_12 | 118 |
PAD_SPI_DO | 8 | PAD_GPIOA_07 | 45 | PAD_OUTN_RX0_CH1 | 82 | PAD_SAR_ADC0_13 | 119 |
PAD_GPIOE_00 | 9 | PAD_GPIOA_08 | 46 | PAD_OUTP_RX0_CH2 | 83 | PAD_SAR_ADC0_14 | 120 |
PAD_GPIOE_01 | 10 | PAD_GPIOA_09 | 47 | PAD_OUTN_RX0_CH2 | 84 | PAD_PWM_ADC01 | 121 |
PAD_GPIOE_02 | 11 | PAD_GPIOA_10 | 48 | PAD_OUTP_RX0_CH3 | 85 | PAD_PWM_ADC00 | 122 |
PAD_GPIOE_03 | 12 | PAD_GPIOA_11 | 49 | PAD_OUTN_RX0_CH3 | 86 | PAD_GPIOD_01 | 123 |
PAD_GPIOE_04 | 13 | PAD_EMMC_RST | 50 | PAD_GPIOC_00 | 87 | PAD_GPIOD_02 | 124 |
PAD_GPIOE_05 | 14 | PAD_EMMC_CLK | 51 | PAD_GPIOC_01 | 88 | PAD_GPIOD_03 | 125 |
PAD_GPIOE_06 | 15 | PAD_EMMC_CMD | 52 | PAD_GPIOC_02 | 89 | PAD_GPIOD_00 | 126 |
PAD_GPIOE_07 | 16 | PAD_EMMC_DS | 53 | PAD_GPIOC_03 | 90 | PAD_UART0_RX | 127 |
PAD_GPIOE_08 | 17 | PAD_EMMC_D3 | 54 | PAD_GPIOC_04 | 91 | PAD_PM_GPIO4 | 128 |
PAD_GPIOE_09 | 18 | PAD_EMMC_D4 | 55 | PAD_GPIOC_05 | 92 | PAD_PM_GPIO5 | 129 |
PAD_GPIOE_10 | 19 | PAD_EMMC_D0 | 56 | PAD_GPIOC_06 | 93 | PAD_PM_PWM1_OUT | 130 |
PAD_GPIOE_11 | 20 | PAD_EMMC_D5 | 57 | PAD_GPIOC_07 | 94 | PAD_PM_I2C_SDA | 131 |
PAD_GPIOE_12 | 21 | PAD_EMMC_D1 | 58 | PAD_GPIOC_08 | 95 | PAD_PM_PWM0_OUT | 132 |
PAD_GPIOE_13 | 22 | PAD_EMMC_D6 | 59 | PAD_OUTP_CH0 | 96 | PAD_PM_I2C_SCL | 133 |
PAD_GPIOE_14 | 23 | PAD_EMMC_D2 | 60 | PAD_OUTN_CH0 | 97 | PAD_PM_GPIO1 | 134 |
PAD_GPIOE_15 | 24 | PAD_EMMC_D7 | 61 | PAD_OUTP_CH1 | 98 | PAD_PM_GPIO3 | 135 |
PAD_GPIOE_16 | 25 | PAD_GPIOA_12 | 62 | PAD_OUTN_CH1 | 99 | PAD_PM_UART1_TX | 136 |
PAD_GPIOE_17 | 26 | PAD_GPIOA_13 | 63 | PAD_OUTP_CH2 | 100 | PAD_PM_GPIO2 | 137 |
PAD_GPIOE_18 | 27 | PAD_GPIOA_14 | 64 | PAD_OUTN_CH2 | 101 | PAD_PM_GPIO7 | 138 |
PAD_GPIOE_19 | 28 | PAD_GPIOA_15 | 65 | PAD_OUTP_CH3 | 102 | PAD_PM_GPIO6 | 139 |
PAD_GPIOE_20 | 29 | PAD_GPIOA_16 | 66 | PAD_OUTN_CH3 | 103 | PAD_PM_UART1_RX | 140 |
PAD_GPIOE_21 | 30 | PAD_GPIOA_17 | 67 | PAD_OUTP_CH4 | 104 | PAD_PM_ADC00_IN | 141 |
PAD_GPIOE_22 | 31 | PAD_GPIOA_18 | 68 | PAD_OUTN_CH4 | 105 | PAD_PM_GPIO0 | 142 |
PAD_GPIOE_23 | 32 | PAD_GPIOA_19 | 69 | PAD_SAR_ADC0_00 | 106 | ||
PAD_GPIOE_24 | 33 | PAD_GPIOB_00 | 70 | PAD_SAR_ADC0_01 | 107 | ||
PAD_GPIOE_25 | 34 | PAD_GPIOB_01 | 71 | PAD_SAR_ADC0_02 | 108 | ||
PAD_GPIOE_26 | 35 | PAD_GPIOB_02 | 72 | PAD_SAR_ADC0_03 | 109 | ||
PAD_GPIOE_27 | 36 | PAD_GPIOB_03 | 73 | PAD_SAR_ADC0_04 | 110 |
3.Uboot配置¶
3.1、uboot config配置如下
[*] SigmaStar drivers ---> [*] SigmaStar GPIO [*] SigmaStar padmux
3.2、dts配置如下,compatible一般不会修改,status根据需要配置 okay/disabled.
gpio: gpio { compatible = "sstar,gpio"; tatus = "okay"; };
3.3、uboot cmd使用
gpio input <gpio#> --> gpio input 69 // gpio69 set as input gpio set <gpio#> --> gpio set 10 // gpio10 set as output high gpio clear <gpio#> --> gpio clear 49 // gpio49 set as output low gpio toggle <gpio#> --> gpio toggle 49 // gpio49 level toggle gpio status <gpio#> --> gpio status 20 // gpio20 status
4.kernel相关配置¶
4.1、kernel config配置说明
Device Drivers ---> [*] GPIO Support ---> [*] /sys/class/gpio/... (sysfs interface) [*] SStar SoC platform drivers ---> [*] Sstar GPIO driver [*] Sstar PADMUX driver
4.2 、dts参数配置说明
gpio: gpio { compatible = "sstar,gpio"; #gpio-cells = <2>; status = "okay"; };
属性 | 描述 | 备注 |
---|---|---|
compatible | 用于匹配驱动进行驱动注册 | 禁止修改 |
#gpio-cells | 声明设备节点gpio cells的个数 | 配置为2表示第一个cell为gpio号,第二个cell表示gpio有效电平 |
status | 驱动开关 | 根据需要配置,ok/disabled |
5.复用功能介绍¶
当需要使用GPIO的复用功能时候,首先需要获取所要操作的PIN脚的name、所要复用的mux mode,将他们配置在xxx-padmux.dtsi中:
<PAD_GPIOC_02 PINMUX_FOR_I2S0_MCK_MODE_1 MDRV_PUSE_I2S0_MCK>, <PAD_GPIOC_03 PINMUX_FOR_I2S0_RX_MODE_1 MDRV_PUSE_I2S0_RX_BCK>, <PAD_GPIOC_04 PINMUX_FOR_I2S0_RX_MODE_1 MDRV_PUSE_I2S0_RX_WCK>, <PAD_GPIOC_05 PINMUX_FOR_I2S0_RX_MODE_1 MDRV_PUSE_I2S0_RX_SDI>, <PAD_GPIOC_06 PINMUX_FOR_I2S0_TX_MODE_1 MDRV_PUSE_I2S0_TX_SDO>, <PAD_GPIOC_07 PINMUX_FOR_I2S0_TX_MODE_1 MDRV_PUSE_I2S0_TX_BCK>, <PAD_GPIOC_08 PINMUX_FOR_I2S0_TX_MODE_1 MDRV_PUSE_I2S0_TX_WCK>,
如上I2S0的配置所示,第一列是pad name,可以在表1中获取(或者查阅/drivers/sstar/include/pcupid/gpio.h),第二列表示pad的复用模式(查阅/drivers/sstar/include/pcupid/padmux.h),第三列则是当前这组padmux配置的名字(查阅/drivers/sstar/include/drv_puse.h),也是该pad在当前mode下的功能。
以PAD_GPIOC_02为例,它支持的mode如表2,当该pad作为I2S0的MCLK输出主时钟信号时需要配置成 PINMUX_FOR_I2S0_MCK_MODE_1 ;而作为PWM2使用时需要配置为 PINMUX_FOR_PWM2_MODE_1 。
表2:PAD_GPIOC_02支持的mode一览
mode | mode | mode |
---|---|---|
PINMUX_FOR_GPIO_MODE | PINMUX_FOR_FUART_MODE_2 | PINMUX_FOR_FUART_2W_MODE_2 |
PINMUX_FOR_I2S0_MCK_MODE_1 | PINMUX_FOR_BT656_OUT_MODE_1 | PINMUX_FOR_TTL24_MODE_1 |
PINMUX_FOR_TTL18_MODE_1 | PINMUX_FOR_TTL18_MODE_2 | PINMUX_FOR_TTL16_MODE_1 |
PINMUX_FOR_TTL16_MODE_2 | PINMUX_FOR_TTL_SRGB8_MODE_1 | PINMUX_FOR_LCD8_MODE_1 |
PINMUX_FOR_LCD16_MODE_1 | PINMUX_FOR_LCD18_MODE_1 | PINMUX_FOR_PWM2_MODE_1 |
PINMUX_FOR_IR2_IN_MODE_1 | PINMUX_FOR_PSPI0_G_MODE_1 | PINMUX_FOR_PSPI1_4W_MODE_2 |
当配置完成后需要检查下是否有其他pad配置成了相同的mode,或者是相同的pad配置成其他的mode,这样会引发冲突,可能会导致配置的padmux失效,需要注释掉或者重新选择pad。
// 以DMIC为例,演示下冲突的情况 // SDMMC1 ... <PAD_GPIOA_07 PINMUX_FOR_GPIO_MODE MDRV_PUSE_SDIO0_PWR>, ... // DMIC <PAD_GPIOA_07 PINMUX_FOR_DMIC_8CH_MODE_3 MDRV_PUSE_DMIC0_CLK>, ...
如上所示,dtsi中同时配置了PAD_GPIO_07这个引脚,分别配置成GPIO模式和DMIC,用做SDIO的pwr和DMIC的clk,如果没有注释掉其中一个配置,由于引脚冲突注定有一个配置的功能是无法使用的。
总结一下需要注意的事项:
-
一个pad只能配置成一种mode,如果配置了多个mode会冲突;
-
一个MDRV_PUSE_XXX只能对应一组pad配置,不可以存在多组相同的MDRV_PUSE_XXX配置,否则也会冲突;
-
配置的pad和mode需要对应。
6.Sample code¶
用户空间控制gpio代码如下:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #define GPIO_93_PIN "93" #define GPIO_DIR_VAL "out" #define GPIO_VAL_H "1" #define GPIO_VAL_L "0" int main(int argc, char *argv[]) { char buff[2] = {0}; int gpio_val_fd = 0; int gpio_dir_fd = 0; int gpio_export_fd = 0; int pin_val = 0; gpio_export_fd = open("/sys/class/gpio/export", O_WRONLY); if (gpio_export_fd < 0) { printf("open gpio export failed\n"); return -1; } else { write(gpio_export_fd, GPIO_93_PIN, sizeof(GPIO_93_PIN)); } gpio_dir_fd = open("/sys/devices/gpiochip0/gpio/gpio93/direction", O_RDWR); if (gpio_val_fd < 0) { close(gpio_export_fd); printf("open direction failed\n"); return -2; } write(gpio_dir_fd, GPIO_DIR_VAL, sizeof(GPIO_DIR_VAL)); gpio_val_fd = open("/sys/class/gpio/gpio93/value", O_RDWR); if (gpio_val_fd == -1) { printf("gpio open failed\n"); close(gpio_export_fd); close(gpio_dir_fd); return -3; } else { printf("/sys/class/gpio/gpio93/value\n"); } memset(buff, 0, 2); read(gpio_val_fd, buff, 1); pin_val = atoi(buff); printf("first read gpio val %d, %s\n", pin_val, buff); write(gpio_val_fd, GPIO_VAL_H, sizeof(GPIO_VAL_H)); close(gpio_val_fd); gpio_val_fd = open("/sys/class/gpio/gpio93/value", O_RDWR); memset(buff, 0, 2); read(gpio_val_fd, buff, 1); pin_val = atoi(buff); printf("after write 1,second read gpio val %d, %s\n", pin_val, buff); write(gpio_val_fd, GPIO_VAL_L, sizeof(GPIO_VAL_L)); close(gpio_val_fd); gpio_val_fd = open("/sys/class/gpio/gpio93/value", O_RDWR); memset(buff, 0, 2); read(gpio_val_fd, buff, 1); pin_val = atoi(buff); printf("after write 0, third read gpio val %d, %s\n", pin_val, buff); close(gpio_export_fd); close(gpio_dir_fd); close(gpio_val_fd); return 0; }
GPIO 93对应PAD_GPIOC_06,padmux配置如下所示的PINMUX_FOR_GPIO_MODE,
<PAD_GPIOC_06 PINMUX_FOR_GPIO_MODE MDRV_PUSE_PSPI1_CS>,
demo中先给/sys/class/gpio/export写入控制的GPIO引脚,然后再设置/sys/devices/gpiochip0/gpio/gpio93/direction为输出,向/sys/class/gpio/gpio93/value写入输出的电平值为1,读取pin值后再写入0,最后再读取电平值。