Peripheral Management on Linux: UART, GPIO, ADC, SPI, I2C
Introduction
Peripheral management on Linux is crucial for embedded systems, industrial applications, and hardware interfacing. Linux provides powerful tools and frameworks to interact with hardware peripherals such as UART, GPIO, ADC, SPI, and I2C. These peripherals can be accessed using sysfs, character devices, kernel modules, and user-space libraries.
This article provides a detailed guide on managing peripherals on Linux, including configuration, programming interfaces, and real-world applications.
1. General-Purpose Input/Output (GPIO) Management
Overview
GPIOs allow Linux systems to control external hardware such as LEDs, buttons, and sensors. The Linux kernel provides multiple ways to access GPIOs, including sysfs, libgpiod, and GPIO character devices.
GPIO Configuration via Sysfs (Deprecated)
echo 17 > /sys/class/gpio/export # Enable GPIO 17
echo out > /sys/class/gpio/gpio17/direction # Set as output
echo 1 > /sys/class/gpio/gpio17/value # Turn on
echo 0 > /sys/class/gpio/gpio17/value # Turn off
echo 17 > /sys/class/gpio/unexport # Disable GPIO 17
Using libgpiod (Recommended)
#include <gpiod.h>
#include <stdio.h>
#define GPIO_CHIP "/dev/gpiochip0"
#define GPIO_LINE 17
int main() {
struct gpiod_chip *chip = gpiod_chip_open_by_name(GPIO_CHIP);
struct gpiod_line *line = gpiod_chip_get_line(chip, GPIO_LINE);
gpiod_line_request_output(line, "example", 1);
gpiod_line_set_value(line, 0);
gpiod_chip_close(chip);
return 0;
}
Applications
- LED control.
- Reading button states.
- Controlling relays and motors.
2. Universal Asynchronous Receiver-Transmitter (UART) Management
Overview
UART is widely used for serial communication in Linux. It is managed through device files like /dev/ttySx
or /dev/ttyUSBx
.
Checking Available UART Ports
dmesg | grep tty # List available serial ports
ls /dev/ttyS* # Check UART devices
Configuring UART Using stty
stty -F /dev/ttyS0 115200 cs8 -cstopb -parenb # Set baud rate, character size, stop bits
UART Communication in C
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
int main() {
int uart_fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY);
struct termios options;
tcgetattr(uart_fd, &options);
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
tcsetattr(uart_fd, TCSANOW, &options);
write(uart_fd, "Hello UART", 10);
close(uart_fd);
return 0;
}
Applications
- Debugging through serial consoles.
- Communication with GPS, GSM, and Bluetooth modules.
- Interfacing with microcontrollers.
3. Analog-to-Digital Converter (ADC) Management
Overview
Many embedded Linux platforms support ADC through sysfs or character device interfaces.
Reading ADC Values (Sysfs)
cat /sys/bus/iio/devices/iio:device0/in_voltage0_raw
ADC Programming in C
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd = open("/sys/bus/iio/devices/iio:device0/in_voltage0_raw", O_RDONLY);
char buf[16];
read(fd, buf, sizeof(buf));
printf("ADC Value: %s", buf);
close(fd);
return 0;
}
Applications
- Sensor data acquisition.
- Battery monitoring.
- Analog joystick input.
4. Serial Peripheral Interface (SPI) Management
Overview
SPI allows high-speed communication with devices like sensors, displays, and memory chips.
Enabling SPI on Raspberry Pi
echo "dtparam=spi=on" | sudo tee -a /boot/config.txt
sudo reboot
Communicating via SPI Using spidev
#include <stdio.h>
#include <fcntl.h>
#include <linux/spi/spidev.h>
#include <sys/ioctl.h>
int main() {
int spi_fd = open("/dev/spidev0.0", O_RDWR);
uint8_t tx[] = {0xAA, 0xBB};
uint8_t rx[2];
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = 2
};
ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);
close(spi_fd);
return 0;
}
Applications
- Communicating with SD cards.
- Reading IMU sensors (MPU6050, BME280).
- Interfacing with high-speed memory devices.
5. Inter-Integrated Circuit (I2C) Management
Overview
I2C enables multi-device communication using two lines: SDA (data) and SCL (clock).
Listing I2C Devices
sudo i2cdetect -y 1 # List devices on bus 1
Communicating with I2C Devices
echo "0x40" > /sys/class/i2c-adapter/i2c-1/new_device
cat /sys/class/i2c-dev/i2c-1/device/0x40/name
I2C Communication in C
#include <stdio.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
int main() {
int i2c_fd = open("/dev/i2c-1", O_RDWR);
ioctl(i2c_fd, I2C_SLAVE, 0x40);
char buf[1] = {0x01};
write(i2c_fd, buf, 1);
close(i2c_fd);
return 0;
}
Applications
- Interfacing with EEPROMs and RTCs.
- Reading environmental sensors (temperature, humidity).
- Communicating with OLED displays.
Conclusion
Linux provides robust interfaces for managing peripherals, from GPIOs and UART to ADC, SPI, and I2C. Developers can use sysfs, character devices, or user-space libraries to interact with hardware efficiently. Understanding these interfaces enables seamless integration of Linux-based embedded systems with external components, making Linux a powerful platform for industrial and IoT applications.