GPIO Programming
The LattePanda Mu compute module currently provides up to 17 GPIO pins that can be configured as either inputs or outputs. You can execute scripts within the system to control these GPIOs to read signals from or send signals to peripheral devices.
The pin locations and their default functions are listed in the table below:
GPIO Pinout Assignment¶
| Pin#(Edge Connector) | Pin Name | Default Function |
|---|---|---|
| 126 | GPP_F12 | GPIO |
| 124 | GPP_F13 | GPIO |
| 122 | GPP_F14 | GPIO |
| 120 | GPP_F15 | GPIO |
| 118 | GPP_F16 | GPIO |
| 119 | GPP_E0 | WWAN_PWR_EN |
| 121 | GPP_A12 | CAM_PWR_EN |
| 139 | SOC_UART0_TXD / GPP_H11 | UART0_TXD |
| 137 | SOC_UART0_RXD / GPP_H10 | UART0_RXD |
| 143 | SOC_UART1_TXD / GPP_D18 | UART1_TXD |
| 141 | SOC_UART1_RXD / GPP_D17 | UART1_RXD |
| 138 | SOC_UART2_TXD / GPP_F2 | UART2_TXD |
| 140 | SOC_UART2_RXD / GPP_F1 | UART2_RXD |
| 128 | GPP_D0 | WWAN_PWR_EN |
| 130 | GPP_D1 | WWAN_RST |
| 132 | GPP_D2 | IT8851_INT |
| 134 | GPP_D3 | CAM_PWR_EN |
GPIO Features¶
-
3.3V I/O voltage levels
-
Floating input or push-pull output
-
Defaults to high-impedance state after OS boot or reboot
-
Routed directly from the processor PCH
Warning
Since these GPIOs originate directly from the processor's PCH, special care must be taken during use.
Overvoltage, overcurrent, and short circuits are strictly prohibited, as any damage to the pins is irreparable.
BIOS Requirements¶
GPIO function requires BIOS support. Please ensure that the BIOS version used by your LattePanda Mu module is S70NC1R200-8G/16G-A or higher.
If you are using an older version such as LP-BS-S70NC1R200-SR/DR-B, please refer to the Update BIOS Firmware section to complete a BIOS update.
Switch Multiplexed Pins to GPIO Mode¶
GPP_F12 to GPP_F16 pins can be used directly as GPIOs without requiring any BIOS configuration.
The remaining pins are not set to GPIO by default and must be switched to GPIO mode in the BIOS.
Switching Steps:
-
Power-on or restart LattePanda board, press Del to enter the BIOS setup.
-
Navigate to the
GPIO Configurationoption via the following path:Advanced -> GPIO Configuration. -
Configure the required pins to GPIO mode.
For example: If you do not need to use UART2 but wish to use the UART2 TXD and RXD pins as GPIOs, select "GPIO" as shown in the figure below.

-
Navigate to the
Save & Exit pageand selectSave Changes and Exitoption to save the BIOS settings and restart the LattePanda board.
GPIO Address¶
For LattePanda Mu modules (Intel N100 or N305 processor), the underlying GPIO controller is mapped to gpiochip0 with the device identifier [INTC1057:00].
You can verify the controller status using the gpiodetect command from the terminal:
sudo apt update
sudo apt install gpiod
sudo gpiodetect
| Pin Name | Line Offset |
|---|---|
| GPP_F12 | 300 |
| GPP_F13 | 301 |
| GPP_F14 | 302 |
| GPP_F15 | 303 |
| GPP_F16 | 304 |
| GPP_E0 | 320 |
| GPP_A12 | 76 |
| SOC_UART0_TXD / GPP_H11 | 171 |
| SOC_UART0_RXD / GPP_H10 | 170 |
| SOC_UART1_TXD / GPP_D18 | 210 |
| SOC_UART1_RXD / GPP_D17 | 209 |
| SOC_UART2_TXD / GPP_F2 | 290 |
| SOC_UART2_RXD / GPP_F1 | 289 |
| GPP_D0 | 192 |
| GPP_D1 | 193 |
| GPP_D2 | 194 |
| GPP_D3 | 195 |
GPIO Programming in Linux¶
In Linux OS, the Python or C version of the libgpiod can be used for GPIO programming.
The following demonstration uses an Ubuntu OS(either version 22.04 or 24.04) to control the GPP_F12 pin as an example.
libgpiod Python¶
Environment Preparation¶
- Install the Python gpiod library
sudo apt update
sudo apt install python3-libgpiod
apt install python3-libgpiod — not the PyPI version installed via pip install gpiod. Outputting High and Low Signals¶
The following code sets the GPP_F12 pin to output mode and toggles the output level signal every second.
- Save the following code as a Python file, for example,
gpio_toggle_demo.py.
import gpiod
import time
import sys
# ================= Configuration =================
# Hardware: LattePanda Mu (Intel N100/N305)
# Chip: [INTC1057:00] -> gpiochip0
CHIP_NAME = 'gpiochip0'
# Pin Definition (Mapping Name to Line Offset)
PIN_GPP_F12 = 300
# Select the target pin for this demo
TARGET_LINE_OFFSET = PIN_GPP_F12
# ===============================================
def main():
chip = None
line = None
try:
# 1. Initialize Chip
chip = gpiod.Chip(CHIP_NAME)
# 2. Get the specific line (GPP_F12)
line = chip.get_line(TARGET_LINE_OFFSET)
# 3. Request Control
# Set direction to OUTPUT
line.request(consumer="GPIO_Toggle_Demo", type=gpiod.LINE_REQ_DIR_OUT)
print(f"Demo Started: Blinking Pin GPP_F12 (Line {TARGET_LINE_OFFSET})...")
print("Press Ctrl+C to stop.")
# 4. Main Loop
while True:
# Set High Level
line.set_value(1)
print(f"[{time.strftime('%H:%M:%S')}] GPIO -> HIGH (1)")
time.sleep(1)
# Set Low Level
line.set_value(0)
print(f"[{time.strftime('%H:%M:%S')}] GPIO -> LOW (0)")
time.sleep(1)
except KeyboardInterrupt:
print("\nDemo stopped by user (Ctrl+C).")
except Exception as e:
print(f"An error occurred: {e}")
finally:
# 5. Clean up resources
# The 'finally' block GUARANTEES this runs even after Ctrl+C
if line:
line.release()
print("GPIO Line released.")
if chip:
chip.close()
print("GPIO Chip closed.")
if __name__ == "__main__":
main()
- Navigate to the directory containing the
gpio_toggle_demo.pyfile and run the following command in the terminal. You will observe the GPP_F12 pin outputting high and low signals at approximately 1-second intervals.
sudo python3 gpio_toggle_demo.py
Reading High and Low Signals¶
The following code sets the GPP_F12 pin to input mode and read its level status at one-second intervals.
import gpiod
import time
# ================= Configuration =================
# Hardware: LattePanda Mu
# Chip: gpiochip0
# Pin: GPP_F12 -> Line Offset 300
CHIP_NAME = 'gpiochip0'
PIN_GPP_F12 = 300
# ===============================================
def main():
chip = None
line = None
try:
# 1. Initialize Chip
chip = gpiod.Chip(CHIP_NAME)
# 2. Get the line
line = chip.get_line(PIN_GPP_F12)
# 3. Request Control as INPUT
# We specify LINE_REQ_DIR_IN for input mode
line.request(consumer="GPIO_Input_Demo", type=gpiod.LINE_REQ_DIR_IN)
print(f"Demo Started: Reading Input from GPP_F12 (Line {PIN_GPP_F12})...")
print("Connect this pin to GND or VCC (3.3V) to see changes.")
print("Press Ctrl+C to stop.")
# 4. Main Loop
while True:
# Read current value (0 or 1)
value = line.get_value()
print(f"[{time.strftime('%H:%M:%S')}] Input Value: {value}")
# Wait 1 second
time.sleep(1)
except KeyboardInterrupt:
print("\nDemo stopped by user.")
except Exception as e:
print(f"Error: {e}")
finally:
# 5. Cleanup
if line:
line.release()
if chip:
chip.close()
print("Resources released.")
if __name__ == "__main__":
main()
libgpiod C¶
Environment Preparation¶
- Install the C gpiod library
sudo apt update
sudo apt install libgpiod-dev
Outputting High and Low Signals¶
The following code sets the GPP_F12 pin to output mode and toggles the output level signal every second.
- Save the following code as a C file, for example,
gpio_toggle_demo.c.
#include <gpiod.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdbool.h>
// ================= Configuration =================
// Hardware: LattePanda Mu (Intel N100/N305)
// Chip: gpiochip0
// Pin: GPP_F12 -> Line Offset 300
// ===============================================
#define CHIP_NAME "gpiochip0"
#define PIN_GPP_F12 300
// Flag for the main loop, modified by signal handler
static volatile sig_atomic_t keep_running = 1;
// Signal Handler for Ctrl+C
void signal_handler(int sig) {
keep_running = 0;
}
int main(void) {
struct gpiod_chip *chip;
struct gpiod_line *line;
int ret;
// 1. Register signal handler (Ctrl+C)
signal(SIGINT, signal_handler);
// 2. Open the GPIO Chip
chip = gpiod_chip_open_by_name(CHIP_NAME);
if (!chip) {
perror("Open chip failed");
return 1;
}
// 3. Get the specific line
line = gpiod_chip_get_line(chip, PIN_GPP_F12);
if (!line) {
perror("Get line failed");
gpiod_chip_close(chip);
return 1;
}
// 4. Request the line as OUTPUT
// "LattePanda_C_Demo" is the consumer label visible in gpioinfo
ret = gpiod_line_request_output(line, "GPIO_Toggle_Demo", 0);
if (ret < 0) {
perror("Request line as output failed");
gpiod_chip_close(chip);
return 1;
}
printf("Demo Started: Blinking Pin GPP_F12 (Line %d)...\n", PIN_GPP_F12);
printf("Press Ctrl+C to stop.\n");
// 5. Main Loop
while (keep_running) {
// Set High
gpiod_line_set_value(line, 1);
printf("GPIO -> HIGH (1)\n");
sleep(1);
if (!keep_running) break;
// Set Low
gpiod_line_set_value(line, 0);
printf("GPIO -> LOW (0)\n");
sleep(1);
}
// 6. Cleanup Resources
printf("\nReleasing resources...\n");
gpiod_line_release(line);
gpiod_chip_close(chip);
printf("Done.\n");
return 0;
}
- Navigate to the directory containing the
gpio_toggle_demo.cfile and run the following command in the terminal. You will observe the GPP_F12 pin outputting high and low signals at approximately 1-second intervals.
gcc -o gpio_toggle_demo gpio_toggle_demo.c -lgpiod
sudo ./gpio_toggle_demo
Reading High and Low Signals¶
The following code sets the GPP_F12 pin to input mode and read its level status at one-second intervals.
#include <gpiod.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
// ================= Configuration =================
#define CHIP_NAME "gpiochip0"
#define PIN_GPP_F12 300
// ===============================================
static volatile sig_atomic_t keep_running = 1;
// Signal Handler for graceful exit
void signal_handler(int sig) {
keep_running = 0;
}
int main(void) {
struct gpiod_chip *chip;
struct gpiod_line *line;
int value;
int ret;
signal(SIGINT, signal_handler);
// 1. Open Chip
chip = gpiod_chip_open_by_name(CHIP_NAME);
if (!chip) {
perror("Open chip failed");
return 1;
}
// 2. Get Line
line = gpiod_chip_get_line(chip, PIN_GPP_F12);
if (!line) {
perror("Get line failed");
gpiod_chip_close(chip);
return 1;
}
// 3. Request as INPUT
ret = gpiod_line_request_input(line, "GPIO_Input_Demo");
if (ret < 0) {
perror("Request input failed");
gpiod_chip_close(chip);
return 1;
}
printf("Demo Started: Reading Input from GPP_F12 (Line %d)...\n", PIN_GPP_F12);
printf("Press Ctrl+C to stop.\n");
// 4. Main Loop
while (keep_running) {
// Read Value
value = gpiod_line_get_value(line);
if (value < 0) {
perror("Read value failed");
} else {
printf("Input Value: %d\n", value);
}
sleep(1);
}
// 5. Cleanup
printf("\nReleasing resources...\n");
gpiod_line_release(line);
gpiod_chip_close(chip);
return 0;
}
libgpiod Programming Reference¶
GPIO Sysfs Interface¶
The libgpiod project provides a low-level C library, bindings to high-level languages and tools for interacting with the GPIO (General Purpose Input/Output) lines on Linux systems.
It replaces the older, legacy GPIO sysfs interface, which has been deprecated in the Linux kernel. The newer GPIO character device interface (introduced in Linux kernel version 4.8) provides a more flexible and efficient way to interact with GPIO lines, and libgpiod is the primary tool for working with this interface.
However, if you still want to use the legacy GPIO sysfs interface, please follow the steps below.
GPIO Number¶
The sysfs interface uses a global GPIO numbering scheme. The formula is:
GPIO Number = Base Address + Offset Address
The base address of gpiochip0 [INTC1057:00] is fixed at 512.
Example:
If the target pin is GPP_F12 and its offset address is 300.
So its global GPIO number is: 812
Output Control¶
Writing to the GPIO sysfs interface requires root privileges. It is recommended to switch to the root user first.
sudo -i
The following commands configure the GPP_F12 pin as an output and toggle the voltage level.
cd /sys/class/gpio
echo 812 > export
cd gpio812
echo out > direction
# Set output to High (Logic 1)
echo 1 > value
# Set output to Low (Logic 0)
echo 0 > value
Read Input¶
The following commands configure the pin as an input and read the current level status.
# Ensure you are inside the gpio812 directory
echo in > direction
# Read current value(0 or 1) every 1 second
watch -n 1 cat value
Release Resource¶
After finishing your operations, it is good practice to release the GPIO pin:
cd /sys/class/gpio
echo 812 > unexport