![라즈베리파이 5 GPIO LED 제어를 위한 리눅스 디바이스 드라이버 만들어보기](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7bzQk%2FbtsLRlweDik%2FuV6xeJUMqUpTQRqLKPT0K0%2Fimg.jpg)
클로드를 사용하여 라즈베리파이 5에서 LED 켜고 끄는 디바이스 드라이버 만드는 방법을 조사후 진행해봤습니다.
2025. 1. 16 최초작성
원래는 다음처럼 연결해야 하지만, 편의상 저항은 빼고 연결했습니다.
GPIO 18 (PIN 12) → 220Ω 저항 → LED 긴 다리 → LED 짧은 다리 → GND
이미지 출처 - https://www.reddit.com/r/raspberry_pi/comments/18y24yr/powering_raspberry_pi_5_with_gpio/
필요한 패키지를 설치합니다.
$ sudo apt update
$ sudo apt install raspberrypi-kernel-headers build-essential
코드를 저장할 디렉토리를 만들고 그 안에 소스 코드를 저장합니다.
pi@raspberrypi:~ $ mkdir led_driver
pi@raspberrypi:~ $ cd led_driver/
pi@raspberrypi:~/led_driver $ nano led_driver.c
다음 코드를 led_driver.c에 붙여넣고 Ctrl + O눌러 저장하고 Ctrl + X를 눌러 nano에서 빠져나옵니다.
GPIO 18번 핀을 사용하도록 코드가 작성되어 있습니다. 주의할점은 GPIO 18번에 대해 내부 핀 번호 589를 사용해야 합니다.
참고 https://blaxsior-repository.tistory.com/294
다음 명령으로 내부 핀번호 확인이 가능합니다.
$ cat /sys/kernel/debug/gpio
#include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/gpio.h> #include <linux/kobject.h> #include <linux/sysfs.h> #define LED_GPIO 589 static struct kobject *led_kobj; static int led_value = 0; // sysfs에서 LED 상태 읽기 static ssize_t led_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "%d\n", led_value); } // sysfs를 통해 LED 제어 static ssize_t led_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { int ret; long temp; ret = kstrtol(buf, 10, &temp); if (ret) { printk(KERN_ERR "LED Driver: Invalid input value\n"); return ret; } if (temp != 0 && temp != 1) { printk(KERN_ERR "LED Driver: Value must be 0 or 1\n"); return -EINVAL; } led_value = temp; gpio_set_value(LED_GPIO, led_value); printk(KERN_INFO "LED Driver: LED set to %d\n", led_value); return count; } static struct kobj_attribute led_attr = __ATTR(value, 0660, led_show, led_store); static int __init led_init(void) { int ret; printk(KERN_INFO "LED Driver: 초기화 시작\n"); // GPIO 요청 ret = gpio_request(LED_GPIO, "LED"); if (ret) { printk(KERN_ERR "LED Driver: GPIO request failed\n"); return ret; } // GPIO 출력으로 설정 ret = gpio_direction_output(LED_GPIO, 0); if (ret) { printk(KERN_ERR "LED Driver: Failed to set GPIO direction\n"); gpio_free(LED_GPIO); return ret; } // sysfs 엔트리 생성 led_kobj = kobject_create_and_add("led_driver", kernel_kobj); if (!led_kobj) { printk(KERN_ERR "LED Driver: Failed to create sysfs entry\n"); gpio_free(LED_GPIO); return -ENOMEM; } // sysfs 파일 생성 ret = sysfs_create_file(led_kobj, &led_attr.attr); if (ret) { printk(KERN_ERR "LED Driver: Failed to create sysfs file\n"); kobject_put(led_kobj); gpio_free(LED_GPIO); return ret; } printk(KERN_INFO "LED Driver: 초기화 완료\n"); return 0; } static void __exit led_exit(void) { printk(KERN_INFO "LED Driver: 제거 시작\n"); if (led_kobj) { sysfs_remove_file(led_kobj, &led_attr.attr); kobject_put(led_kobj); } gpio_set_value(LED_GPIO, 0); // LED 끄기 gpio_free(LED_GPIO); printk(KERN_INFO "LED Driver: 제거 완료\n"); } module_init(led_init); module_exit(led_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple LED driver for Raspberry Pi 5"); |
Makefile을 생성하여 다음 코드를 붙여넣고 Ctrl + O눌러 저장하고 Ctrl + X를 눌러 nano에서 빠져나옵니다.
pi@raspberrypi:~/led_driver $ nano Makefile
obj-m := led_driver.o KERNELDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean: $(MAKE) -C $(KERNELDIR) M=$(PWD) clean |
이제 모듈을 빌드합니다. 코드 수정해도 절대 make clean을 하지 마세요. 커널 헤더를 지워버려서 문제가 생깁니다.
pi@raspberrypi:~/led_driver $ make
make -C /lib/modules/6.6.62+rpt-rpi-2712/build M=/home/pi/led_driver modules
make[1]: Entering directory '/usr/src/linux-headers-6.6.62+rpt-rpi-2712'
CC [M] /home/pi/led_driver/led_driver.o
MODPOST /home/pi/led_driver/Module.symvers
CC [M] /home/pi/led_driver/led_driver.mod.o
LD [M] /home/pi/led_driver/led_driver.ko
make[1]: Leaving directory '/usr/src/linux-headers-6.6.62+rpt-rpi-2712'
모듈을 로드합니다.
pi@raspberrypi:~/led_driver $ sudo insmod led_driver.ko
커널 로그를 확인할 수 있습니다.
pi@raspberrypi:~/led_driver $ dmesg | tail
[ 4.208238] macb 1f00100000.ethernet: gem-ptp-timer ptp clock registered.
[ 4.216415] brcmfmac: brcmf_cfg80211_set_power_mgmt: power save enabled
[ 8.217902] Bluetooth: RFCOMM TTY layer initialized
[ 8.217912] Bluetooth: RFCOMM socket layer initialized
[ 8.217922] Bluetooth: RFCOMM ver 1.11
[ 332.746253] led_driver: loading out-of-tree module taints kernel.
[ 391.111387] LED Driver: 초기화 시작
[ 391.111416] LED Driver: 초기화 완료
권한을 설정합니다.
pi@raspberrypi:~/led_driver $ sudo chmod 666 /sys/kernel/led_driver/value
LED가 켜집니다. 상태확인도 가능합니다.
pi@raspberrypi:~/led_driver $ echo 1 > /sys/kernel/led_driver/value
pi@raspberrypi:~/led_driver $ cat /sys/kernel/led_driver/value
1
LED가 꺼집니다. 상태확인도 가능합니다.
pi@raspberrypi:~/led_driver $ echo 0 > /sys/kernel/led_driver/value
pi@raspberrypi:~/led_driver $ cat /sys/kernel/led_driver/value
0
pi@raspberrypi:~/led_driver $
커널 로그를 확인합니다.
pi@raspberrypi:~/led_driver $ dmesg | tail
[ 391.111387] LED Driver: 초기화 시작
[ 391.111416] LED Driver: 초기화 완료
[ 553.606858] LED Driver: LED set to 1
[ 606.958806] LED Driver: LED set to 0
드라이버를 제거합니다.
pi@raspberrypi:~/led_driver $ sudo rmmod led_driver.ko
커널 로그를 확인합니다.
pi@raspberrypi:~/led_driver $ dmesg | tail
[ 391.111387] LED Driver: 초기화 시작
[ 391.111416] LED Driver: 초기화 완료
[ 553.606858] LED Driver: LED set to 1
[ 606.958806] LED Driver: LED set to 0
[ 635.966072] LED Driver: 제거 시작
[ 635.966092] LED Driver: 제거 완료
'Raspberry Pi > Raspberry Pi 활용' 카테고리의 다른 글
Raspberry Pi 5 BCM2712 Datasheet 찾아본 결과 (0) | 2024.07.13 |
---|---|
Raspberry Pi 400에 RetroPie 설치하기 (0) | 2024.04.19 |
Raspberry Pi 4 에서 무선랜(WiFi) 설정하는 방법 (0) | 2023.10.21 |
C언어로 Raspberry Pi 3의 GPIO 레지스터 접근하여 버튼값 읽어오기 (0) | 2023.10.09 |
C언어로 Raspberry Pi 3의 GPIO 레지스터 접근하여 LED켜보기 (0) | 2023.10.09 |