> For the complete documentation index, see [llms.txt](https://amobile-solutions.gitbook.io/yocto-developer-guide/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://amobile-solutions.gitbook.io/yocto-developer-guide/test-and-use-the-interface/gpios/gpios-iot-800n-g420.md).

# GPIOs - IOT-800N-G420

## Overview

The board exposes GPIO through two interfaces:

| Interface                  | Path               | Best for              |
| -------------------------- | ------------------ | --------------------- |
| libgpiod, character device | `/dev/gpiochipN`   | new code, C or Python |
| sysfs, legacy              | `/sys/class/gpio/` | existing scripts      |

The device tree declares `gpio-line-names`, so lines can be addressed by name rather than by number.

{% hint style="warning" %}
The image ships **libgpiod v2**, whose command syntax differs from v1. Scripts written for v1 fail, sometimes silently. See [Version differences](#version-differences) below.
{% endhint %}

## Listing the lines

```
gpioinfo
gpioinfo | grep -v unnamed
```

```
line   3:  "NFC_SEN"       output  consumer="..."
line   4:  "NFC_PWR_EN"    output  consumer="regulator"
line  80:  "DI_2"          input
line 106:  "DO_0"          input
line 153:  "SER_MODE2"     output  consumer="gpioset"
```

A line showing a `consumer` is claimed by a driver or another process and cannot be taken by userspace.

## Reading and writing

```
gpioget DI_0
gpioget DI_0 DI_1 DI_2
gpioget -c gpiochip0 80
```

```
gpioset DO_0=1 &
```

{% hint style="info" %}
`gpioset` in libgpiod v2 **blocks while it holds the line**, so it has to be backgrounded. When the process exits the line is released.

To set a value and return immediately:

```
gpioset --toggle 0 DO_0=1
```

The MediaTek output register retains the value, but `gpioinfo` will then show the line as unused. For "set it and walk away", sysfs is simpler.
{% endhint %}

## Watching for changes

```
gpiomon DI_0
gpiomon --edges=rising DI_0
```

## sysfs

```
echo 106 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio106/direction
echo 1 > /sys/class/gpio/gpio106/value
cat /sys/class/gpio/gpio106/value
echo 106 > /sys/class/gpio/unexport
```

## Named lines on this board

| Name                             | GPIO            | Purpose                   |
| -------------------------------- | --------------- | ------------------------- |
| `DI_0` / `DI_1` / `DI_2`         | 108 / 110 / 80  | Isolated digital inputs   |
| `DO_0` / `DO_1` / `DO_2`         | 106 / 107 / 109 | Isolated digital outputs  |
| `SER_MODE0` / `1` / `2`          | 155 / 154 / 153 | DB9 protocol selection    |
| `NFC_SEN`                        | 3               | PTX130R chip enable       |
| `NFC_PWR_EN`                     | 4               | PTX130R supply enable     |
| `GPS_WAKEUP`                     | 6               | GNSS wakeup               |
| `GYRO_INT`                       | 5               | BMI270 interrupt          |
| `SD_CD`                          | 2               | micro SD card detect      |
| `DLKEY`                          | 44              | Download key              |
| `LTE_RING0`                      | 105             | LTE ring / wake           |
| `PCIE_MODULE_ON`                 | 152             | LTE module power          |
| `CAN_PWR3V3_EN` / `CAN_PWR5V_EN` | 33 / 38         | CAN supplies              |
| `DIO_EN`                         | 68              | Isolated 3.3 V for DIO    |
| `RS232_EN`                       | 67              | Serial transceiver supply |

{% hint style="info" %}
The supply lines are raised and held by fixed regulators at boot, so userspace cannot claim them. Making one customer-controllable — switching CAN off to save power, for instance — means removing `always-on` from the corresponding regulator node.
{% endhint %}

## Version differences

| Operation    | libgpiod v1                                 | libgpiod v2                                  |
| ------------ | ------------------------------------------- | -------------------------------------------- |
| Read         | `gpioget gpiochip0 3`                       | `gpioget -c gpiochip0 3`, or by name         |
| Write        | `gpioset gpiochip0 3=1` returns immediately | `gpioset NFC_SEN=1` blocks while holding     |
| Find by name | `gpiofind NAME`                             | names work directly in `gpioget` / `gpioset` |
| Hold a line  | `gpioset --mode=wait`                       | default behaviour                            |

```
gpioset --version
```

{% hint style="danger" %}
`--banner` only exists from v2.2. On v2.1 the command fails outright, and if stderr is redirected the failure is invisible while the line is never driven — a script appears to succeed while doing nothing.
{% endhint %}

## Python

```python
import gpiod

with gpiod.request_lines(
    "/dev/gpiochip0",
    consumer="my-app",
    config={106: gpiod.LineSettings(direction=gpiod.line.Direction.OUTPUT)},
) as request:
    request.set_value(106, gpiod.line.Value.ACTIVE)
    input("holding, press enter to release")
```

The line is held for as long as the `request` object exists.
