00 Eski sysfs GPIO vs chardev
Linux'un eski /sys/class/gpio arayüzü, kernel 4.8'den itibaren deprecated olarak işaretlenmiş ve yerine character device (/dev/gpiochipN) tabanlı yeni API gelmiştir.
Sysfs GPIO'nun sorunları
Chardev avantajları
| Özellik | sysfs (/sys/class/gpio) | chardev (/dev/gpiochipN) |
|---|---|---|
| GPIO tanımlama | Global sayısal ID | chip + offset (taşınabilir) |
| Sahiplik | Yok | fd sahipliği — process ölünce serbest |
| Edge detection | poll() hack | Kernel event queue, nanosaniye timestamp |
| Bulk işlem | Yok | Atomik çoklu GPIO okuma/yazma |
| Active low | Manuel | FLAG_ACTIVE_LOW ile kernel düzeyinde |
| Open drain | Yok | LINE_DRIVE_OPEN_DRAIN |
Chardev arayüzü
# GPIO chip'leri listele
ls -la /dev/gpiochip*
# crw-rw---- 1 root gpio 254, 0 Jan 15 10:00 /dev/gpiochip0
# crw-rw---- 1 root gpio 254, 1 Jan 15 10:00 /dev/gpiochip1
# Chip bilgisi
gpiodetect
# gpiochip0 [pinctrl-bcm2711] (58 lines)
# gpiochip1 [raspberrypi-exp-gpio] (8 lines)
# Kullanıcıyı gpio grubuna ekle
sudo usermod -aG gpio $USER
01 libgpiod v2 API
libgpiod v2 (2.x), v1'e göre tamamen yeniden tasarlanmış bir C API sunar. Temel nesne hiyerarşisi: chip → line_info → request → line_config şeklindedir.
Kurulum
# Debian/Ubuntu (v2.x)
sudo apt install libgpiod-dev gpiod
# Sürüm kontrolü
pkg-config --modversion libgpiod
# 2.1.3
# Derleme
gcc -o myapp myapp.c $(pkg-config --cflags --libs libgpiod)
# veya
gcc -o myapp myapp.c -lgpiod
Temel nesne hiyerarşisi
Chip açma ve line_info sorgulama
#include <gpiod.h>
#include <stdio.h>
int main(void) {
/* Chip aç */
struct gpiod_chip *chip = gpiod_chip_open("/dev/gpiochip0");
if (!chip) {
perror("gpiod_chip_open");
return 1;
}
/* Chip bilgisi */
struct gpiod_chip_info *info = gpiod_chip_get_info(chip);
printf("Chip: %s (%s) — %u lines\n",
gpiod_chip_info_get_name(info),
gpiod_chip_info_get_label(info),
gpiod_chip_info_get_num_lines(info));
gpiod_chip_info_free(info);
/* Hat bilgisi */
struct gpiod_line_info *linfo = gpiod_chip_get_line_info(chip, 18);
printf("Line 18: name=%s consumer=%s direction=%d\n",
gpiod_line_info_get_name(linfo),
gpiod_line_info_get_consumer(linfo),
gpiod_line_info_get_direction(linfo));
gpiod_line_info_free(linfo);
gpiod_chip_close(chip);
return 0;
}
02 Output operasyonları
GPIO hatlarını çıkış olarak yapılandırmak ve değer yazmak için libgpiod v2'nin request mekanizması kullanılır. Tek hat veya atomik çoklu hat çıkışı desteklenir.
Tek GPIO çıkışı
#include <gpiod.h>
#include <stdio.h>
#include <unistd.h>
int main(void) {
struct gpiod_chip *chip = gpiod_chip_open("/dev/gpiochip0");
/* Line settings: çıkış, başlangıç değeri LOW */
struct gpiod_line_settings *settings = gpiod_line_settings_new();
gpiod_line_settings_set_direction(settings,
GPIOD_LINE_DIRECTION_OUTPUT);
gpiod_line_settings_set_output_value(settings,
GPIOD_LINE_VALUE_INACTIVE); /* LOW */
/* Line config: offset 18 için settings uygula */
struct gpiod_line_config *lconfig = gpiod_line_config_new();
unsigned int offset = 18;
gpiod_line_config_add_line_settings(lconfig, &offset, 1, settings);
/* Request config: consumer adı */
struct gpiod_request_config *rconfig = gpiod_request_config_new();
gpiod_request_config_set_consumer(rconfig, "led-control");
/* Hat'ı talep et */
struct gpiod_line_request *request =
gpiod_chip_request_lines(chip, rconfig, lconfig);
/* LED yanıp söndür */
for (int i = 0; i < 10; i++) {
gpiod_line_request_set_value(request, 18,
(i % 2) ? GPIOD_LINE_VALUE_ACTIVE
: GPIOD_LINE_VALUE_INACTIVE);
usleep(500000); /* 500 ms */
}
/* Temizlik */
gpiod_line_request_release(request);
gpiod_line_config_free(lconfig);
gpiod_line_settings_free(settings);
gpiod_request_config_free(rconfig);
gpiod_chip_close(chip);
return 0;
}
Çoklu GPIO atomik çıkış
/* 3 LED'i aynı anda kontrol et — atomik bulk write */
unsigned int offsets[] = {17, 18, 27}; /* RGB LED */
enum gpiod_line_value values[] = {
GPIOD_LINE_VALUE_ACTIVE, /* R: on */
GPIOD_LINE_VALUE_INACTIVE, /* G: off */
GPIOD_LINE_VALUE_ACTIVE /* B: on */
};
/* Settings — tüm hatlar için aynı */
struct gpiod_line_settings *settings = gpiod_line_settings_new();
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_OUTPUT);
struct gpiod_line_config *lconfig = gpiod_line_config_new();
gpiod_line_config_add_line_settings(lconfig, offsets, 3, settings);
struct gpiod_line_request *request =
gpiod_chip_request_lines(chip, rconfig, lconfig);
/* Atomik yazma */
gpiod_line_request_set_values_subset(request, 3, offsets, values);
Active low ve open drain
/* Active-low çıkış (ör: aktif LOW röle) */
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_OUTPUT);
gpiod_line_settings_set_active_low(settings, true);
/* ACTIVE → LOW, INACTIVE → HIGH */
/* Open-drain çıkış (I2C benzeri wired-AND) */
gpiod_line_settings_set_drive(settings,
GPIOD_LINE_DRIVE_OPEN_DRAIN);
/* Open-source (wired-OR) */
gpiod_line_settings_set_drive(settings,
GPIOD_LINE_DRIVE_OPEN_SOURCE);
03 Input ve polling
GPIO hatlarını giriş olarak yapılandırmak, anlık değer okumak ve edge detection ile değişimleri beklemek için input API'si.
Giriş konfigürasyonu
#include <gpiod.h>
/* Buton girişi — pull-up, rising edge */
struct gpiod_line_settings *settings = gpiod_line_settings_new();
/* Yön: giriş */
gpiod_line_settings_set_direction(settings,
GPIOD_LINE_DIRECTION_INPUT);
/* Pull-up bias */
gpiod_line_settings_set_bias(settings,
GPIOD_LINE_BIAS_PULL_UP);
/* Edge detection: her iki kenar */
gpiod_line_settings_set_edge_detection(settings,
GPIOD_LINE_EDGE_BOTH);
/* Debounce period: 5 ms (kernel düzeyinde) */
gpiod_line_settings_set_debounce_period_us(settings, 5000);
/* Bias sabitleri:
* GPIOD_LINE_BIAS_PULL_UP — pull-up direnci
* GPIOD_LINE_BIAS_PULL_DOWN — pull-down direnci
* GPIOD_LINE_BIAS_DISABLED — floating (yüksek empedans)
* GPIOD_LINE_BIAS_AS_IS — mevcut durumu koru */
Anlık değer okuma
/* Tek hat okuma */
enum gpiod_line_value val =
gpiod_line_request_get_value(request, offset);
if (val == GPIOD_LINE_VALUE_ACTIVE)
printf("HIGH\n");
else if (val == GPIOD_LINE_VALUE_INACTIVE)
printf("LOW\n");
else
printf("Error: %d\n", val);
/* Çoklu hat okuma (atomik) */
unsigned int offsets[] = {4, 5, 6};
enum gpiod_line_value values[3];
int ret = gpiod_line_request_get_values_subset(
request, 3, offsets, values);
if (ret < 0)
perror("get_values");
Blocking wait — edge detection
#include <gpiod.h>
#include <stdio.h>
/* Edge event bekle (blocking) */
struct gpiod_edge_event_buffer *buf =
gpiod_edge_event_buffer_new(64); /* 64 event kapasitesi */
/* Blokla: event gelene kadar bekle */
int n = gpiod_line_request_read_edge_events(request, buf, 1);
if (n < 0) {
perror("read_edge_events");
return -1;
}
struct gpiod_edge_event *event =
gpiod_edge_event_buffer_get_event(buf, 0);
printf("Event: %s on offset %u at %llu ns\n",
gpiod_edge_event_get_event_type(event) ==
GPIOD_EDGE_EVENT_RISING_EDGE ? "RISING" : "FALLING",
gpiod_edge_event_get_line_offset(event),
(unsigned long long)gpiod_edge_event_get_timestamp_ns(event));
gpiod_edge_event_buffer_free(buf);
04 Event handling
Gerçek zamanlı edge event işleme için gpiod_edge_event_buffer ve poll()/select() ile event loop kurulumu. Nanosaniye hassasiyetinde timestamp.
Event loop — poll() ile
#include <gpiod.h>
#include <poll.h>
#include <stdio.h>
#include <signal.h>
static volatile int running = 1;
static void sighandler(int sig) { running = 0; }
int main(void) {
struct gpiod_chip *chip = gpiod_chip_open("/dev/gpiochip0");
struct gpiod_line_settings *settings = gpiod_line_settings_new();
gpiod_line_settings_set_direction(settings,
GPIOD_LINE_DIRECTION_INPUT);
gpiod_line_settings_set_bias(settings,
GPIOD_LINE_BIAS_PULL_UP);
gpiod_line_settings_set_edge_detection(settings,
GPIOD_LINE_EDGE_BOTH);
gpiod_line_settings_set_debounce_period_us(settings, 3000);
struct gpiod_line_config *lconfig = gpiod_line_config_new();
unsigned int offset = 17;
gpiod_line_config_add_line_settings(lconfig, &offset, 1, settings);
struct gpiod_request_config *rconfig = gpiod_request_config_new();
gpiod_request_config_set_consumer(rconfig, "button-monitor");
struct gpiod_line_request *request =
gpiod_chip_request_lines(chip, rconfig, lconfig);
/* Request fd'sini al — poll() için */
int fd = gpiod_line_request_get_fd(request);
struct gpiod_edge_event_buffer *evbuf =
gpiod_edge_event_buffer_new(16);
struct pollfd pfd = { .fd = fd, .events = POLLIN };
signal(SIGINT, sighandler);
printf("Buton izleniyor (Ctrl+C ile çık)...\n");
while (running) {
int ret = poll(&pfd, 1, 1000); /* 1 sn timeout */
if (ret < 0) break;
if (ret == 0) continue; /* timeout */
int n = gpiod_line_request_read_edge_events(request, evbuf, 16);
for (int i = 0; i < n; i++) {
struct gpiod_edge_event *ev =
gpiod_edge_event_buffer_get_event(evbuf, i);
uint64_t ts = gpiod_edge_event_get_timestamp_ns(ev);
int type = gpiod_edge_event_get_event_type(ev);
printf("[%llu ns] %s\n", (unsigned long long)ts,
type == GPIOD_EDGE_EVENT_RISING_EDGE ?
"RISING (buton bırakıldı)" :
"FALLING (buton basıldı)");
}
}
gpiod_edge_event_buffer_free(evbuf);
gpiod_line_request_release(request);
gpiod_line_config_free(lconfig);
gpiod_line_settings_free(settings);
gpiod_request_config_free(rconfig);
gpiod_chip_close(chip);
return 0;
}
Birden fazla GPIO'dan event toplama
/* 3 buton için ayrı request'ler → 3 fd → poll */
unsigned int btn_offsets[] = {17, 22, 27};
struct pollfd pfds[3];
struct gpiod_line_request *requests[3];
for (int i = 0; i < 3; i++) {
/* Her buton için ayrı request */
struct gpiod_line_config *cfg = gpiod_line_config_new();
gpiod_line_config_add_line_settings(cfg,
&btn_offsets[i], 1, settings);
requests[i] = gpiod_chip_request_lines(chip, rconfig, cfg);
pfds[i].fd = gpiod_line_request_get_fd(requests[i]);
pfds[i].events = POLLIN;
gpiod_line_config_free(cfg);
}
/* Hepsini aynı anda bekle */
poll(pfds, 3, -1);
05 gpiotools CLI
gpiod paketi ile gelen komut satırı araçları, GPIO'ları shell script ve hızlı test için kullanmanızı sağlar.
gpiodetect ve gpioinfo
# Tüm GPIO chip'leri listele
gpiodetect
# gpiochip0 [pinctrl-bcm2711] (58 lines)
# gpiochip1 [raspberrypi-exp-gpio] (8 lines)
# Chip'teki tüm hatları listele
gpioinfo gpiochip0
# gpiochip0 - 58 lines:
# line 0: "ID_SDA" unused input active-high
# line 1: "ID_SCL" unused input active-high
# line 2: "SDA1" unused input active-high
# line 17: unnamed unused input active-high
# line 18: unnamed unused input active-high
# Belirli hat
gpioinfo --chip gpiochip0 17
# JSON çıktısı (gpiod 2.x)
gpioinfo --json | python3 -m json.tool
gpioget — değer okuma
# Hat 17'yi oku
gpioget --chip gpiochip0 17
# 1 (HIGH)
# Çoklu hat
gpioget --chip gpiochip0 17 18 22
# 1 0 1
# Active-low
gpioget --active-low --chip gpiochip0 17
# Bias
gpioget --bias=pull-up --chip gpiochip0 17
gpioget --bias=pull-down --chip gpiochip0 17
gpioset — değer yazma
# Hat 18'i HIGH yap
gpioset --chip gpiochip0 18=1
# LOW yap
gpioset --chip gpiochip0 18=0
# Çoklu
gpioset --chip gpiochip0 17=1 18=0 27=1
# Belirli süre HIGH tut, sonra serbest bırak
gpioset --mode=time --sec=2 --chip gpiochip0 18=1
# Tek sinyal darbesi (toggle)
gpioset --mode=signal --chip gpiochip0 18=1
# Ctrl+C = serbest bırak
gpiomon — edge event izleme
# Hat 17'deki edge event'leri izle
gpiomon --chip gpiochip0 17
# 2026-01-15T14:23:10.123456789Z rising gpiochip0 17
# 2026-01-15T14:23:10.987654321Z falling gpiochip0 17
# Sadece rising edge
gpiomon --rising-edge --chip gpiochip0 17
# Falling edge, 5 event'den sonra çık
gpiomon --falling-edge --num-events=5 --chip gpiochip0 17
# Birden fazla hat
gpiomon --chip gpiochip0 17 22 27
# Debounce period
gpiomon --debounce-period=5ms --chip gpiochip0 17
06 Pinctrl subsystem
Pinctrl, GPIO dışında pin multiplexing (pin'in UART mı, SPI mi, GPIO mu olacağı) ve pull-up/down, drive-strength gibi elektriksel parametreleri Device Tree üzerinden yapılandırır.
Pinctrl temel kavramlar
Device Tree binding
/* Pinctrl driver tanımı (SoC DTSI içinde) */
pinctrl: pinctrl@30330000 {
compatible = "fsl,imx8mp-iomuxc";
reg = <0x30330000 0x10000>;
/* UART2 pinleri için group tanımı */
uart2_pins_default: uart2grp {
fsl,pins = <
MX8MP_IOMUXC_UART2_RXD 0x140 /* pull-up, 100k */
MX8MP_IOMUXC_UART2_TXD 0x140
>;
};
uart2_pins_sleep: uart2grp_sleep {
fsl,pins = <
MX8MP_IOMUXC_UART2_RXD 0x100 /* floating */
MX8MP_IOMUXC_UART2_TXD 0x100
>;
};
};
/* UART2 cihaz node'u — pinctrl state'lerini kullanır */
&uart2 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&uart2_pins_default>; /* state 0 = "default" */
pinctrl-1 = <&uart2_pins_sleep>; /* state 1 = "sleep" */
status = "okay";
};
Pinctrl debugfs ile inceleme
# Pinctrl debugfs (CONFIG_DEBUG_FS gerekli)
ls /sys/kernel/debug/pinctrl/
# 30330000.pinctrl
cat /sys/kernel/debug/pinctrl/30330000.pinctrl/pins | head -20
# pin 0 (GPIO1_IO00)
# pin 1 (GPIO1_IO01)
# ...
cat /sys/kernel/debug/pinctrl/30330000.pinctrl/pingroups
# group: uart2grp
# pin 100 (UART2_RXD)
# pin 101 (UART2_TXD)
cat /sys/kernel/debug/pinctrl/30330000.pinctrl/pinmux-functions
# Aktif state'leri gör
cat /sys/kernel/debug/pinctrl/30330000.pinctrl/pinmux-pins | head -30
# GPIO sysfs'den pin mux durumu
cat /sys/kernel/debug/gpio | grep -A 5 "gpiochip0"
07 Python bindings
python3-libgpiod, libgpiod'un Pythonic sarmalayıcısıdır. asyncio ile event-driven GPIO uygulamaları yazmayı kolaylaştırır.
Kurulum
# Debian/Ubuntu
sudo apt install python3-libgpiod
# veya pip (libgpiod C kütüphanesi kurulu olmalı)
pip3 install gpiod
# Sürüm kontrolü
python3 -c "import gpiod; print(gpiod.__version__)"
Temel kullanım — output ve input
import gpiod
import time
# Chip aç
chip = gpiod.Chip("/dev/gpiochip0")
# LED output (GPIO 18)
led_request = chip.request_lines(
config={
18: gpiod.LineSettings(
direction=gpiod.line.Direction.OUTPUT,
output_value=gpiod.line.Value.INACTIVE
)
},
consumer="python-led"
)
# Buton input (GPIO 17, pull-up)
btn_request = chip.request_lines(
config={
17: gpiod.LineSettings(
direction=gpiod.line.Direction.INPUT,
bias=gpiod.line.Bias.PULL_UP,
edge_detection=gpiod.line.Edge.BOTH,
debounce_period=datetime.timedelta(milliseconds=5)
)
},
consumer="python-button"
)
# LED yanıp söndür
for i in range(6):
led_request.set_value(18,
gpiod.line.Value.ACTIVE if i % 2 else gpiod.line.Value.INACTIVE)
time.sleep(0.5)
led_request.release()
btn_request.release()
chip.close()
asyncio ile event loop
import asyncio
import gpiod
import datetime
async def monitor_button(chip_path: str, offset: int):
chip = gpiod.Chip(chip_path)
request = chip.request_lines(
config={
offset: gpiod.LineSettings(
direction=gpiod.line.Direction.INPUT,
bias=gpiod.line.Bias.PULL_UP,
edge_detection=gpiod.line.Edge.BOTH,
debounce_period=datetime.timedelta(milliseconds=5)
)
},
consumer="asyncio-button"
)
fd = request.fd
loop = asyncio.get_event_loop()
print(f"GPIO {offset} izleniyor...")
try:
while True:
# asyncio event loop'una entegre et
future = loop.create_future()
loop.add_reader(fd, future.set_result, None)
await future
loop.remove_reader(fd)
# Event'leri oku
events = request.read_edge_events()
for ev in events:
edge = "RISING" if ev.event_type == \
gpiod.EdgeEvent.Type.RISING_EDGE else "FALLING"
ts_ns = ev.timestamp_ns
print(f"[{ts_ns} ns] GPIO {ev.line_offset}: {edge}")
finally:
request.release()
chip.close()
async def main():
await asyncio.gather(
monitor_button("/dev/gpiochip0", 17),
monitor_button("/dev/gpiochip0", 22)
)
asyncio.run(main())
08 Pratik: RPi4 button debounce + LED control daemon
Raspberry Pi 4 üzerinde libgpiod v2 ile buton debounce + LED kontrol yapan, systemd servis olarak çalışan tam bir daemon uygulaması.
Donanım bağlantıları
| Bileşen | RPi4 GPIO | Pin | Açıklama |
|---|---|---|---|
| Buton | GPIO 17 | Pin 11 | Pull-up, GND'ye bağlı — basınca LOW |
| LED (kırmızı) | GPIO 18 | Pin 12 | 330Ω dirençle 3.3V |
| LED (yeşil) | GPIO 27 | Pin 13 | 330Ω dirençle 3.3V |
| GND | GND | Pin 9 | Ortak toprak |
gpio-daemon.c — tam daemon kodu
/* gpio-daemon.c — buton + LED kontrol daemon */
#include <gpiod.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h>
#include <syslog.h>
#include <unistd.h>
#define CHIP_PATH "/dev/gpiochip0"
#define BTN_OFFSET 17
#define LED_R 18
#define LED_G 27
#define DEBOUNCE_US 10000 /* 10 ms debounce */
static volatile int running = 1;
static void sighandler(int sig) {
syslog(LOG_INFO, "gpio-daemon: signal %d, stopping\n", sig);
running = 0;
}
int main(void) {
openlog("gpio-daemon", LOG_PID | LOG_CONS, LOG_DAEMON);
syslog(LOG_INFO, "gpio-daemon başlatılıyor");
signal(SIGTERM, sighandler);
signal(SIGINT, sighandler);
struct gpiod_chip *chip = gpiod_chip_open(CHIP_PATH);
if (!chip) {
syslog(LOG_ERR, "Chip açılamadı: %s", CHIP_PATH);
return EXIT_FAILURE;
}
/* ── LED output request ── */
struct gpiod_line_settings *led_s = gpiod_line_settings_new();
gpiod_line_settings_set_direction(led_s,
GPIOD_LINE_DIRECTION_OUTPUT);
gpiod_line_settings_set_output_value(led_s,
GPIOD_LINE_VALUE_INACTIVE);
struct gpiod_line_config *led_cfg = gpiod_line_config_new();
unsigned int led_offsets[] = {LED_R, LED_G};
gpiod_line_config_add_line_settings(led_cfg, led_offsets, 2, led_s);
struct gpiod_request_config *rc = gpiod_request_config_new();
gpiod_request_config_set_consumer(rc, "gpio-daemon-led");
struct gpiod_line_request *led_req =
gpiod_chip_request_lines(chip, rc, led_cfg);
if (!led_req) {
syslog(LOG_ERR, "LED request başarısız");
return EXIT_FAILURE;
}
/* ── Buton input request ── */
struct gpiod_line_settings *btn_s = gpiod_line_settings_new();
gpiod_line_settings_set_direction(btn_s,
GPIOD_LINE_DIRECTION_INPUT);
gpiod_line_settings_set_bias(btn_s,
GPIOD_LINE_BIAS_PULL_UP);
gpiod_line_settings_set_edge_detection(btn_s,
GPIOD_LINE_EDGE_FALLING);
gpiod_line_settings_set_debounce_period_us(btn_s, DEBOUNCE_US);
struct gpiod_line_config *btn_cfg = gpiod_line_config_new();
unsigned int btn_offset = BTN_OFFSET;
gpiod_line_config_add_line_settings(btn_cfg, &btn_offset, 1, btn_s);
gpiod_request_config_set_consumer(rc, "gpio-daemon-btn");
struct gpiod_line_request *btn_req =
gpiod_chip_request_lines(chip, rc, btn_cfg);
if (!btn_req) {
syslog(LOG_ERR, "Buton request başarısız");
return EXIT_FAILURE;
}
int fd = gpiod_line_request_get_fd(btn_req);
struct gpiod_edge_event_buffer *evbuf =
gpiod_edge_event_buffer_new(8);
struct pollfd pfd = { .fd = fd, .events = POLLIN };
int led_state = 0; /* 0=kırmızı, 1=yeşil, 2=off */
/* Başlangıç: kırmızı LED */
gpiod_line_request_set_value(led_req, LED_R,
GPIOD_LINE_VALUE_ACTIVE);
syslog(LOG_INFO, "Hazır — buton bekleniyor");
while (running) {
int ret = poll(&pfd, 1, 2000);
if (ret < 0 && running) {
syslog(LOG_ERR, "poll hatası");
break;
}
if (ret == 0) continue; /* timeout, döngüye devam */
int n = gpiod_line_request_read_edge_events(
btn_req, evbuf, 8);
for (int i = 0; i < n; i++) {
led_state = (led_state + 1) % 3;
/* Tüm LED'leri kapat */
gpiod_line_request_set_value(led_req, LED_R,
GPIOD_LINE_VALUE_INACTIVE);
gpiod_line_request_set_value(led_req, LED_G,
GPIOD_LINE_VALUE_INACTIVE);
/* Yeni duruma göre aç */
if (led_state == 0) {
gpiod_line_request_set_value(led_req, LED_R,
GPIOD_LINE_VALUE_ACTIVE);
syslog(LOG_DEBUG, "LED: KIRMIZI");
} else if (led_state == 1) {
gpiod_line_request_set_value(led_req, LED_G,
GPIOD_LINE_VALUE_ACTIVE);
syslog(LOG_DEBUG, "LED: YEŞİL");
} else {
syslog(LOG_DEBUG, "LED: KAPALI");
}
}
}
/* Temizlik */
gpiod_line_request_set_value(led_req, LED_R,
GPIOD_LINE_VALUE_INACTIVE);
gpiod_line_request_set_value(led_req, LED_G,
GPIOD_LINE_VALUE_INACTIVE);
gpiod_edge_event_buffer_free(evbuf);
gpiod_line_request_release(btn_req);
gpiod_line_request_release(led_req);
gpiod_line_config_free(led_cfg);
gpiod_line_config_free(btn_cfg);
gpiod_line_settings_free(led_s);
gpiod_line_settings_free(btn_s);
gpiod_request_config_free(rc);
gpiod_chip_close(chip);
syslog(LOG_INFO, "gpio-daemon durduruldu");
closelog();
return EXIT_SUCCESS;
}
Derleme ve systemd servisi
# Derleme
gcc -o gpio-daemon gpio-daemon.c \
$(pkg-config --cflags --libs libgpiod) \
-Wall -Wextra -O2
# Test
./gpio-daemon
# systemd servis dosyası
cat > /etc/systemd/system/gpio-daemon.service <<'EOF'
[Unit]
Description=GPIO Button+LED Daemon
After=multi-user.target
[Service]
Type=simple
User=pi
Group=gpio
ExecStart=/usr/local/bin/gpio-daemon
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
# Servisi etkinleştir
sudo systemctl daemon-reload
sudo systemctl enable --now gpio-daemon
# Logları izle
journalctl -u gpio-daemon -f
libgpiod v2, sysfs GPIO'nun tüm eksikliklerini giderir: güvenli sahiplik, atomik bulk operasyon, kernel düzeyinde debounce, nanosaniye timestamp ve asyncio entegrasyonu. Daemon geliştirme için C API, hızlı prototipleme ve otomasyon için Python binding, shell scriptler için gpiotools CLI idealdir. Pinctrl DT binding ile multiplexing konfigürasyonu kernel boot zamanında otomatik uygulanır.