这里会显示出您选择的修订版和当前版本之间的差别。
jaysnote:gpio_libc [2019/04/26 17:13] jaylee |
jaysnote:gpio_libc [2021/06/22 23:14] |
||
---|---|---|---|
行 1: | 行 1: | ||
- | < | ||
- | # gpio | ||
- | |||
- | 对linux c app里面的一个gpio操作云里雾里半天,是时候好好理理了。 | ||
- | |||
- | * https:// | ||
- | * https:// | ||
- | |||
- | 主要是这gpio number是如何同pin number 一一对应的。 | ||
- | |||
- | ```shell | ||
- | 256 | ||
- | root@mxj-zbcs-310:# | ||
- | . | ||
- | |-- export | ||
- | |-- gpio120 -> ../ | ||
- | |-- gpio228 -> ../ | ||
- | |-- gpio229 -> ../ | ||
- | |-- gpio232 -> ../ | ||
- | |-- gpio32 -> ../ | ||
- | |-- gpio33 -> ../ | ||
- | |-- gpio359 -> ../ | ||
- | |-- gpio64 -> ../ | ||
- | |-- gpiochip0 -> ../ | ||
- | |-- gpiochip1024 -> ../ | ||
- | |-- gpiochip352 -> ../ | ||
- | `-- unexport | ||
- | ``` | ||
- | |||
- | 奇怪,今天发现`sys/ | ||
- | |||
- | ```shell | ||
- | fd = open("/ | ||
- | len = snprintf(buffer, | ||
- | if (write(fd, buffer, len) < 0) { | ||
- | } | ||
- | ``` | ||
- | |||
- | 这里的`export`和`unport`以及之后对 io number value的`read write` 操作都是在`gpiolibc` 上实现的。 | ||
- | |||
- | ```c | ||
- | snprintf(path, | ||
- | fd = open(path, O_WRONLY); | ||
- | if (fd < 0) { | ||
- | } | ||
- | |||
- | if (write(fd, & | ||
- | } | ||
- | ``` | ||
- | |||
- | 接下来需要理一理`gpiolibc` 的实现, | ||
- | ```c | ||
- | static struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; | ||
- | ``` | ||
- | 这个结构体的实现主要是是通过`gpio_chip`来操作的,例如`gpiod_set_value` 是通过`gpio_desc` 获取到`gpio_chip` 然后在通过`gpio_chip-> | ||
- | |||
- | ```c | ||
- | static void gpiod_set_value(struct gpio_desc *desc, int value) { | ||
- | struct gpio_chip *chip; | ||
- | |||
- | if (!desc) | ||
- | return; | ||
- | chip = desc-> | ||
- | /* Should be using gpio_set_value_cansleep() */ | ||
- | WARN_ON(chip-> | ||
- | trace_gpio_value(desc_to_gpio(desc), | ||
- | if (test_bit(FLAG_OPEN_DRAIN, | ||
- | _gpio_set_open_drain_value(desc, | ||
- | else if (test_bit(FLAG_OPEN_SOURCE, | ||
- | _gpio_set_open_source_value(desc, | ||
- | else | ||
- | chip-> | ||
- | } | ||
- | ``` | ||
- | |||
- | 所以对于`gpio_chip` 的初始化就很重要了。然而我并没有找。 | ||
- | |||
- | ```c | ||
- | static inline u32 sunxi_data_reg(u16 pin) { | ||
- | u8 bank = pin / PINS_PER_BANK; | ||
- | u32 offset = bank * BANK_MEM_SIZE; | ||
- | offset += DATA_REGS_OFFSET; | ||
- | offset += pin % PINS_PER_BANK / DATA_PINS_PER_REG * 0x04; | ||
- | return round_down(offset, | ||
- | } | ||
- | |||
- | #define PINS_PER_BANK | ||
- | ``` | ||
- | 对于如上计算的`bank` | ||
- | `8` 对应`PL` | ||
- | |||
- | ![](http:// | ||
- | |||
- | ![](http:// | ||
- | |||
- | > | ||
- | |||
- | `pin % PINS_PER_BANK` 对于Port 尾号,例如pin=32,对应 `PB0` | ||
- | |||
- | ```c | ||
- | # | ||
- | # | ||
- | # | ||
- | # | ||
- | # | ||
- | # | ||
- | # | ||
- | # | ||
- | ``` | ||
- | |||
- | |||
- | |||
- | shell 脚本转换 | ||
- | |||
- | ```shell | ||
- | num2name(){ | ||
- | local num=$1 | ||
- | local h=$[$num/ | ||
- | local l=$[$num%32] | ||
- | |||
- | local H=$(echo -e `printf ' | ||
- | echo P$H$l | ||
- | } | ||
- | name2num(){ | ||
- | local name=$1 | ||
- | name=${name# | ||
- | local H=${name: | ||
- | local l=${name:1} | ||
- | local h=$[`printf ' | ||
- | |||
- | echo $[h*32+l] | ||
- | } | ||
- | |||
- | ``` | ||
- | </ | ||