# 實驗: GPIO 的存取

## GPIO 的硬體需求

GPIO 和硬體相關，因此，若是要能夠在 OpenWRT 上存取 GPIO，就需要硬體與韌體的支援。對於我們所使用的平台 (GL-AR300M 和 GL-AR750S) 來說，都支援 GPIO ，因此我們在這兩個平台上進行測試。以下是 GL-AR300M 和 GL-AR750S 的對應表。

|      | GL-AR300M | GL-AR750S |
| ---- | --------- | --------- |
| I2C  | GPIO16    | GPIO5     |
| I2C  | GPIO17    | GPIO21    |
| UART | GPIO9     | GPIO18    |
| UART | GPIO10    | GPIO22    |

## GPIO 的操作指令

以下指令以操作 GL-AR300M 的 GPIO16 為例。

初始化 GPIO16: `$ echo 16 > /sys/class/gpio/export`

設定 GPIO16 為輸出: `$ echo out > /sys/class/gpio/gpio16/direction`

設定 GPIO16 為輸入: `$ echo in > /sys/class/gpio/gpio16/direction`&#x20;

設定 GPIO16 為高電位: `$ echo 1 > /sys/class/gpio/gpio16/value`&#x20;

設定 GPIO16 為低電位: `$ echo 0 > /sys/class/gpio/gpio16/value`&#x20;

查看 GPIO16 的數值:&#x20;

```
$ cat /sys/class/gpio/gpio16/value
$ cat /sys/kernel/debug/gpio
```

解除 GPIO16 : `$ echo 16 > /sys/class/gpio/unexport`

{% hint style="info" %}
當 GPIO16 初始化之後，`/sys/class/gpio/gpio16/`資料夾才建立，同時，只有在 GPIO16 設定為輸出後，才可以設定 GPIO 的數值，GPIO為輸入或是輸出會保留之前設定。在解除 GPIO 之後，資料夾也會移除。
{% endhint %}

可以參考以下資訊:

* <https://wiki.openwrt.org/doc/hardware/port.gpio>&#x20;
* <https://wiki.openwrt.org/doc/hardware/port.i2c>

若是我們需要查看 GPIO 的目前設置，可以使用指令: `$ cat /sys/kernel/debug/gpio`

![GL-AR750S 的 GPIO 設置](/files/-LNsaq-hECKJm9Di65Ti)

## GPIO 輸出電壓值量測

當我們改變了 GPIO 輸出，在物理上就會改變其電壓數值，我們用電壓計來查詢改變後的電壓值，以下是我們的實驗內容，量測電位的的腳位可以參考"測試硬體與功能列表"的章節。

![GPIO9 的低電位](/files/-LNsh12tUr-seGTZYk0q)

![GPIO9 的高電位](/files/-LNsh5mQxlwwKpJwMV-O)

以下是我們對 GL-AR300M 的測試結果。

| GL-AR300M | LOW | HIGH  |
| --------- | --- | ----- |
| GPIO16    | 0V  | 2.56V |
| GPIO17    | 0V  | 3.30V |
| GPIO9     | 0V  | 2.53V |
| GPIO10    | 0V  | 2.56V |

## 將分配給 I2C 的腳位改回 GPIO

在 GL-AR750S 這塊板子上，我們可以看到 I2C 已經預設開啟。因此，原本能夠使用的 GPIO，也只剩下 18、22，而5, 21被指定為 I2C 的通訊介面 (SDA、SCL)。 因此，若是要使用 GPIO 5 和21，則必須先把 I2C 的功能關閉，否則就無法 export。若我們需要將原本分配給 I2C 的腳位 (GPIO 5) 改回 GPIO，則可以使用以下指令:

```
root@GL-AR750S:~# echo "i2c-gpio.0" > /sys/bus/platform/drivers/i2c-gpio/unbind

root@GL-AR750S:~# echo 5 > /sys/class/gpio/export
root@GL-AR750S:~# cat /sys/class/gpio/gpio5/direction
in
root@GL-AR750S:~# echo out > /sys/class/gpio/gpio5/direction
root@GL-AR750S:~# cat /sys/class/gpio/gpio5/value
0
root@GL-AR750S:~# echo 1 > /sys/class/gpio/gpio5/value
root@GL-AR750S:~# cat /sys/class/gpio/gpio5/value
1
```

相同的，對 pin 21 也可以進行一樣的操作。

```
root@GL-AR750S:~# echo 21 > /sys/class/gpio/export
root@GL-AR750S:~# cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 0-31, parent: platform/ath79-gpio, ath79-gpio:
 gpio-1   (                    |gl-ar750s:white:powe) out lo
 gpio-2   (                    |reset               ) in  hi
 gpio-5   (                    |sysfs               ) out hi
 gpio-7   (                    |gl-ar750s:white:usbp) out hi
 gpio-8   (                    |right               ) in  hi
 gpio-19  (                    |gl-ar750s:white:wlan) out hi
 gpio-20  (                    |gl-ar750s:white:wlan) out hi
 gpio-21  (                    |sysfs               ) in  hi
 gpio-22  (                    |sysfs               ) out hi

gpiochip1: GPIOs 489-511, parent: platform/qca956x_wmac, ath9k-phy1:
 gpio-490 (                    |ath9k-phy1          ) in  lo

```

重開機之後，就重新回到分配給 I2C 的設定:

```
root@GL-AR750S:~#  cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 0-31, parent: platform/ath79-gpio, ath79-gpio:
 gpio-1   (                    |gl-ar750s:white:powe) out lo
 gpio-2   (                    |reset               ) in  hi
 gpio-5   (                    |sda                 ) in  hi
 gpio-7   (                    |gl-ar750s:white:usbp) out hi
 gpio-8   (                    |right               ) in  hi
 gpio-19  (                    |gl-ar750s:white:wlan) out lo
 gpio-20  (                    |gl-ar750s:white:wlan) out hi
 gpio-21  (                    |scl                 ) in  hi

gpiochip1: GPIOs 489-511, parent: platform/qca956x_wmac, ath9k-phy1:
 gpio-490 (                    |ath9k-phy1          ) in  lo
```

我們可以寫一隻簡單的 script 來進行設定 unbind I2C 的設定，並測試 GPIO 的寫入結果。

```
echo "i2c-gpio.0" > /sys/bus/platform/drivers/i2c-gpio/unbind

echo 5 > /sys/class/gpio/export
echo 18 > /sys/class/gpio/export
echo 21 > /sys/class/gpio/export
echo 22 > /sys/class/gpio/export

echo out > /sys/class/gpio/gpio5/direction
echo out > /sys/class/gpio/gpio18/direction
echo out > /sys/class/gpio/gpio21/direction
echo out > /sys/class/gpio/gpio22/direction

echo "===== all gpio {5,18,21,22} set to LOW ====="

echo 0 > /sys/class/gpio/gpio5/value
echo 0 > /sys/class/gpio/gpio18/value
echo 0 > /sys/class/gpio/gpio21/value
echo 0 > /sys/class/gpio/gpio22/value
cat /sys/kernel/debug/gpio

echo "===== all gpio {5,18,21,22} set to HIGH ====="

echo 1 > /sys/class/gpio/gpio5/value
echo 1 > /sys/class/gpio/gpio18/value
echo 1 > /sys/class/gpio/gpio21/value
echo 1 > /sys/class/gpio/gpio22/value
cat /sys/kernel/debug/gpio
```

結果顯示， AR750S 的 GPIO {5、18、21} 腳位沒有問題，但是， GPIO 22 腳位無法寫入為 LOW 的數值。

```
# sh unbindi2c.sh
===== all gpio {5,18,21,22} set to LOW =====
gpiochip0: GPIOs 0-31, parent: platform/ath79-gpio, ath79-gpio:
 gpio-1   (                    |gl-ar750s:white:powe) out lo
 gpio-2   (                    |reset               ) in  hi
 gpio-5   (                    |sysfs               ) out lo
 gpio-7   (                    |gl-ar750s:white:usbp) out hi
 gpio-8   (                    |right               ) in  hi
 gpio-18  (                    |sysfs               ) out lo
 gpio-19  (                    |gl-ar750s:white:wlan) out lo
 gpio-20  (                    |gl-ar750s:white:wlan) out hi
 gpio-21  (                    |sysfs               ) out lo
 gpio-22  (                    |sysfs               ) out hi

gpiochip1: GPIOs 489-511, parent: platform/qca956x_wmac, ath9k-phy1:
 gpio-490 (                    |ath9k-phy1          ) in  lo
===== all gpio {5,18,21,22} set to HIGH =====
gpiochip0: GPIOs 0-31, parent: platform/ath79-gpio, ath79-gpio:
 gpio-1   (                    |gl-ar750s:white:powe) out lo
 gpio-2   (                    |reset               ) in  hi
 gpio-5   (                    |sysfs               ) out hi
 gpio-7   (                    |gl-ar750s:white:usbp) out hi
 gpio-8   (                    |right               ) in  hi
 gpio-18  (                    |sysfs               ) out hi
 gpio-19  (                    |gl-ar750s:white:wlan) out lo
 gpio-20  (                    |gl-ar750s:white:wlan) out hi
 gpio-21  (                    |sysfs               ) out hi
 gpio-22  (                    |sysfs               ) out hi

gpiochip1: GPIOs 489-511, parent: platform/qca956x_wmac, ath9k-phy1:
 gpio-490 (                    |ath9k-phy1          ) in  lo

```

以下是我們對 GL-AR750S 的電壓測試結果。

| GL-AR750S    | LOW | HIGH  |
| ------------ | --- | ----- |
| GPIO5 (SDA)  | 0V  | 2.56V |
| GPIO18       | 0V  | 2.56V |
| GPIO21 (SCL) | 0V  | 2.34V |
| GPIO22       | --  | 2.56V |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://openwrt-nctu.gitbook.io/project/experiment-io/exp-gpio.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
