1. PinMap

GPIO, 그게 뭔가요?
GPIO는 General Purpose Input/Output의 약자로, 번역하면 ‘범용 입출력 포트’.
말 그대로 “특별한 용도가 정해지지 않은” 핀(pin)들을 뜻합니다.
개발자가 원하면 입력(Input) 으로 써서 버튼·센서 값을 읽을 수도, 출력(Output) 으로 써서 LED 켜기, 모터 돌리기, 스피커 울리기도 가능합니다.
쉽게 말해, 마이크로컨트롤러의 ‘멀티탭’ 같은 존재죠.
2. G.PIO 상태 확인
sudo apt install gpiod sudo apt install python3-libgpiod gpio readall

sudo cat /sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pins
3. python 코드
GPIO4_A3을 컨트롤 한다고 할 시
a. gpio readall 로 해당 핀의 GPIO행 값을 보면 131이 보인다.
b. sudo cat /sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pins
하면 pin 131 값을 보면
pin 131 (gpio4-3) 3:gpio4 임을 알 수 있다.
c. 최종 아래 코드가 된다 즉
chip = gpiod.Chip(“gpiochip4”)
line = chip.get_line(3)
import gpiod
import time
chip = gpiod.Chip("gpiochip4")
line = chip.get_line(3)
line.request(consumer="test", type=gpiod.LINE_REQ_DIR_OUT)
while True:
line.set_value(1)
time.sleep(1)
line.set_value(0)
time.sleep(1)
4. C 코드
sudo apt update sudo apt install gpiod libgpiod-dev
libgpiod 라이브러리 사용
#include <gpiod.h>
#include <stdio.h>
#include <unistd.h>
#define CONSUMER "my-gpio-app"
#define GPIO_CHIP "/dev/gpiochip4" // bank4에 해당
#define GPIO_LINE 3 // A3 = 그룹 A, 오프셋 3
int main(void) {
struct gpiod_chip *chip;
struct gpiod_line *line;
int ret;
// GPIO 칩 열기
chip = gpiod_chip_open(GPIO_CHIP);
if (!chip) {
perror("Open chip failed");
return 1;
}
// 라인 얻기 (A3)
line = gpiod_chip_get_line(chip, GPIO_LINE);
if (!line) {
perror("Get line failed");
gpiod_chip_close(chip);
return 1;
}
// 출력으로 요청
ret = gpiod_line_request_output(line, CONSUMER, 0);
if (ret < 0) {
perror("Request line as output failed");
gpiod_chip_close(chip);
return 1;
}
// 토글 테스트
for (int i = 0; i < 10; i++) {
gpiod_line_set_value(line, 1);
printf("GPIO set HIGH\n");
sleep(1);
gpiod_line_set_value(line, 0);
printf("GPIO set LOW\n");
sleep(1);
}
gpiod_line_release(line);
gpiod_chip_close(chip);
return 0;
}
컴파일& 실행
gcc -o gpio_test gpio_test.c -lgpiod sudo ./gpio_test
보다 빠른 제어 필요 시
– 접근 방식별 속도 비교
| 방식 | 장점 | 단점 | 속도 |
|---|---|---|---|
| sysfs (/sys/class/gpio) | 단순, 예제 많음 | deprecated, 커널과 유저 공간 오버헤드 큼 | 수 kHz 수준 |
| libgpiod (gpiod_line_set_value) | 표준적, 안전 | 시스템콜 호출 오버헤드 존재 | 수십~수백 kHz |
| mmap(직접 메모리 접근, /dev/mem) | 가장 빠름 (레지스터 직접 접근) | 코드 복잡, 보드별 레지스터 오프셋 필요 | MHz 단위 가능 |
mmap(직접 메모리 접근, /dev/mem) C코드
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdint.h>
#define GPIO4_BASE fec50000 // RK3588 GPIO4 베이스 주소 (예시, DTB에서 확인 필요)
#define GPIO_SIZE 0x10000
#define GPIO_SWPORTA_DDR 0x0004 // direction
#define GPIO_SWPORTA_DR 0x0000 // data register
int main() {
int fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd < 0) {
perror("open");
return 1;
}
volatile uint32_t *gpio;
gpio = mmap(NULL, GPIO_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO4_BASE);
if (gpio == MAP_FAILED) {
perror("mmap");
close(fd);
return 1;
}
// A3 = bit 3
int bit = 3;
// 방향 설정: output
gpio[GPIO_SWPORTA_DDR/4] |= (1 << bit);
// 빠른 토글
for (int i = 0; i < 1000000; i++) {
gpio[GPIO_SWPORTA_DR/4] |= (1 << bit); // HIGH
gpio[GPIO_SWPORTA_DR/4] &= ~(1 << bit); // LOW
}
munmap((void*)gpio, GPIO_SIZE);
close(fd);
return 0;
}
RK3588 GPIO4 베이스 주소 확인하는법 (예시, DTB에서 확인)
cd /boot/dtb-6.1.99-rockchip-rk3588/rockchip/ rk3588s-orangepi-5.dtb dtc -I dtb -O dts -o rk3588s-orangepi-5.dts rk3588s-orangepi-5.dtb
DTS파일 확인 시
gpio@fec50000 {
compatible = "rockchip,gpio-bank";
reg = <0x00 0xfec50000 0x00 0x100>;
interrupts = <0x00 0x119 0x04>;
clocks = <0x02 0x83 0x02 0x84>;
gpio-controller;
#gpio-cells = <0x02>;
gpio-ranges = <0x1a8 0x00 0x80 0x20>;
interrupt-controller;
#interrupt-cells = <0x02>;
phandle = <0x107>;
};
reg = <0x00 0xfec50000 0x00 0x100>;
- 베이스 주소 =
0xfec50000 - 사이즈 =
0x100
root@orangepi5:/boot/dtb-6.1.99-rockchip-rk3588/rockchip# grep -n "gpio@" rk3588s-orangepi-5.dts
22: gpio0 = "/pinctrl/gpio@fd8a0000";
23: gpio1 = "/pinctrl/gpio@fec20000";
24: gpio2 = "/pinctrl/gpio@fec30000";
25: gpio3 = "/pinctrl/gpio@fec40000";
26: gpio4 = "/pinctrl/gpio@fec50000";
7862: gpio@fd8a0000 {
7875: gpio@fec20000 {
7888: gpio@fec30000 {
7901: gpio@fec40000 {
7914: gpio@fec50000 {
11493: gpio0 = "/pinctrl/gpio@fd8a0000";
11494: gpio1 = "/pinctrl/gpio@fec20000";
11495: gpio2 = "/pinctrl/gpio@fec30000";
11496: gpio3 = "/pinctrl/gpio@fec40000";
11497: gpio4 = "/pinctrl/gpio@fec50000";
또는
root@orangepi5:/boot/dtb-6.1.99-rockchip-rk3588/rockchip# cat /proc/iomem | grep gpio fd8a0000-fd8a00ff : fd8a0000.gpio gpio@fd8a0000 fec20000-fec200ff : fec20000.gpio gpio@fec20000 fec30000-fec300ff : fec30000.gpio gpio@fec30000 fec40000-fec400ff : fec40000.gpio gpio@fec40000 fec50000-fec500ff : fec50000.gpio gpio@fec50000
