Three ways to control GPIO under Linux

1. Application space control gpio

1.1 Introduction

        There is an export file under /sys/class/gpio/, write the GPIO number to be operated into the export file, so that the operation interface of the GPIO is exposed from the kernel space to the user space, and the operation interface of the GPIO includes direction and value, etc., direction Control GPIO input or output mode, and value can control the state of GPIO or read the state.

/sys/class/gpio/目录下各个文件说明:
/sys/class/gpio/export文件用于通知系统需要导出控制的GPIO引脚编号;
/sys/class/gpio/unexport 用于通知系统取消导出;
/sys/class/gpio/gpioX/direction文件,可以写入in(设置输入方向)或out(设置输出方向);
/sys/class/gpio/gpioX/value文件是可以读写GPIO状态;
/sys/class/gpio/gpiochipX目录保存系统中GPIO寄存器的信息,包括每个寄存器控制引脚的起始编号,寄存器名称,引脚总数;其中X表示具体的引脚编号。

1.2 operate gpio

        For example, if I want to operate GPIO8_A6 as a high-level output, then there are three operations:

1. 2.1 Convert the corresponding gpio number

        Information can be queried through /sys/kernel/debug/gpio:

root@rk3288:/sys/kernel/debug # cat gpio                                       
//snip
GPIOs 184-215, platform/ff770000.pinctrl, gpio6:
 gpio-193 (?                   ) in  hi
 gpio-194 (?                   ) in  hi
 
GPIOs 216-247, platform/ff770000.pinctrl, gpio7:
 gpio-218 (enable              ) out hi
 gpio-219 (lcd_en              ) in  hi
 gpio-220 (lcd_cs              ) in  hi
 gpio-221 (gslX680 wake pin    ) out hi
 gpio-222 (gslX680 irq pin     ) out lo
 gpio-223 (headset_gpio        ) in  hi
 gpio-233 (?                   ) in  hi
 gpio-234 (?                   ) in  hi
 GPIOs 248-279, platform/ff770000.pinctrl, gpio8:
 
 GPIOs 280-311, platform/ff770000.pinctrl, gpio15:

        It can be seen that gpio8 starts with nubmer as 248, then GPIO8_A6 is 248 + 6 = 254, and then you can export gpio.

root@rk3288:/sys/class/gpio # echo 254 > export                          
root@rk3288:/sys/class/gpio # ls
export
gpio254

1.2.2 Set as output

root@rk3288:/sys/class/gpio/gpio254 # echo out > direction                     
root@rk3288:/sys/class/gpio/gpio254 # cat direction                            
out

1.2.3 Output high level

root@rk3288:/sys/class/gpio/gpio254 # echo 1 > value                           
root@rk3288:/sys/class/gpio/gpio254 # cat value 

1.3 Summary

        This method is generally not used. For the safety of gpio use, the right to use gpio is generally not exposed to the application layer, that is, there is no gpio node under sys/class/.

2. Kernel space controls gpio

        There are two ways to control gpio in the kernel space, the first is to control gpio by calling the interface of gpiolib; the second is to control gpio through ioremap.

2.1 gpiolib controls gpio

2.1.1 Introduction to gpiolib

        The GPIO resources are abstracted in the Linux Kernel, and a thing called Gpiolib is abstracted.

        The middle layer is Gpiolib, which is used to manage GPIOs in the system. Gpiolib summarizes the general operations of GPIO. According to the characteristics of GPIO, Gpiolib provides a set of unified and general software interface for operating GPIO provided by other Drivers, shielding the specific implementation of different chips. Next, Gpiolib provides a set of frameworks for different chip operations. For different chips, you only need to implement the Specific Chip Driver, and then use the registration function provided by Gpiolib to hook it to Gpiolib, thus completing this set of things .

2.1.2 APIs provided by Gpiolib for other drivers

int gpio_request(unsigned gpio, const char *label);
/*向内核申请 gpio,要使用 GPIO 首先应该向内核进行申请,返回 0,代表申请成功,
 *可以进行后续操作*/

void gpio_free(unsigned gpio);
/*对应 gpio_request,是使用完gpio以后把gpio释放掉*/

int gpio_direction_input(unsigned gpio);
/*设置 GPIO 为输入*/

int gpio_direction_output(unsigned gpio, int value);
/*设置 GPIO 为输出*/

int gpio_get_value(unsigned gpio);
/*读取 GPIO 的值*/

int gpio_set_value(unsigned gpio);
/*设置 GPIO 的值*/

2.1.3 Operation gpio

        The function is the same as 1.2.

#define GPIO8_A6 254
ret = gpio_request(GPIO8_A6 , "gpio8_a6");
if (!ret) {
	printk("request for gpio8_a6 failed:%d\n", ret);
    	return 0;
}
gpio_direction_output(GPIO8_A6 ,1);//设置GPIO8_A6为输出功能且输出高电平

2.2 ioremap controls gpio

        This approach reduces program readability and is not recommended.

        The address accessed by the linux kernel space is a virtual address (3~4GB), so when operating a certain register in the kernel space, it is necessary to first map the physical address into a virtual address through the ioremap function.

        Use ioremap() to get the address of the register:

unsigned int __iomem  *base_addr1;  //__iomem可选择,告诉你为虚拟地址
#define  GPIO8_REGBASE  (0x20A0000)
#define  GPIO8_A6 (*(volatile unsigned int *)(base_addr1 + 6)) //指针unsigned int为4字节,指针加1,字节加4
base_addr1 = ioremap(GPIO8_REGBASE, 0x14)

        Directly manipulate the mapped address through the readl() or writel() function:

GPIO8_A6 |= (1<<8);

int temp;
temp = readl(GPIO8_A6);
temp |= (1<<8);
writel(temp, GPIO8_A6);

        When you're done using it, unmap it:

iounmap(base_addr1);

3. View all GPIO information

cat /sys/kernel/debug/pinctrl/pinctrl/pinmux-pins

Pinmux settings per pin
Format: pin (name): mux_owner gpio_owner hog?
pin 0 (gpio0-0): wireless-wlan (GPIO UNCLAIMED) function wireless-wlan group wifi-wake-host
pin 1 (gpio0-1): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 2 (gpio0-2): (MUX UNCLAIMED) gpio0:2
pin 3 (gpio0-3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 4 (gpio0-4): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 5 (gpio0-5): (MUX UNCLAIMED) gpio0:5
pin 6 (gpio0-6): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 7 (gpio0-7): (MUX UNCLAIMED) gpio0:7
pin 8 (gpio0-8): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 9 (gpio0-9): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 10 (gpio0-10): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 11 (gpio0-11): ff050000.i2c (GPIO UNCLAIMED) function i2c1 group i2c1-xfer
pin 12 (gpio0-12): ff050000.i2c (GPIO UNCLAIMED) function i2c1 group i2c1-xfer
pin 13 (gpio0-13): (MUX UNCLAIMED) (GPIO UNCLAIMED)

        According to the comparison experiment, "MUX UNCLAIMED" seems to mean that the multiplexing pin has not been configured. It is only a small personal experiment and does not have absolute accuracy.

Guess you like

Origin blog.csdn.net/qq_41076734/article/details/124669908