Linux/Kernel Driver

Embedded Linux Kernel: Platform Driver 작성하기

임베디드 친구 2025. 3. 19. 09:00
728x90
반응형

Embedded Linux Kernel: Platform Driver 작성하기

임베디드 시스템에서 Linux Kernel을 활용하려면 특정 하드웨어와 연동하기 위한 드라이버 작성이 필수적입니다. 이번 포스팅에서는 Platform Driver 작성, Platform Device와 Driver의 이해, 그리고 Device Tree와 Platform Driver 연동 방법을 Rockchip RK3399 시스템을 예제로 설명하겠습니다.

Platform Driver란?

Platform Driver는 일반적으로 SoC(System on Chip) 기반 시스템에서 특정 하드웨어를 제어하기 위한 커널 드라이버입니다. Platform Driver는 Platform Device와 매칭되어 동작하며, 이 매칭은 Device Tree를 통해 이루어집니다.

Platform Device와 Driver의 이해

Platform Device란?

Platform Device는 SoC에 내장된 하드웨어 장치를 표현하는 커널 객체입니다. 하드웨어의 속성, 메모리 맵, 인터럽트 정보 등을 포함합니다. 일반적으로 Device Tree에 정의된 내용을 기반으로 커널 부팅 시 생성됩니다.
Platform Driver는 특정 Platform Device를 제어하는 코드를 포함합니다. Driver는 Device Tree 또는 다른 방법으로 등록된 Platform Device와 매칭됩니다. 매칭이 성공하면 Driver의 probe 함수가 호출되어 하드웨어 초기화를 수행합니다.

Platform Device와 Driver의 관계

Platform Device와 Driver는 이름과 ID를 통해 매칭됩니다. 이를 통해 커널은 적절한 Driver를 Platform Device와 연결하여 작동시킵니다.

예제: Rockchip RK3399 기반 Platform Driver 작성

1. Device Tree에 Platform Device 추가하기

RK3399 시스템의 Device Tree에 간단한 LED 장치를 추가해보겠습니다. LED는 GPIO 핀을 사용해 제어합니다.

/ {
    leds {
        compatible = "gpio-leds";

        led1 {
            label = "status_led";
            gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>;
        };
    };
};
  • compatible: 이 Device가 사용할 Driver를 지정합니다.
  • gpios: 제어할 GPIO 핀을 지정합니다.

2. Platform Driver 코드 작성하기

아래는 해당 LED를 제어하는 Platform Driver의 예제 코드입니다.

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/of_gpio.h>

struct led_dev {
    struct gpio_desc *gpio;
};

static int led_probe(struct platform_device *pdev) {
    struct led_dev *led;
    int ret;

    /* 메모리 할당 */
    led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
    if (!led)
        return -ENOMEM;

    /* GPIO 핀 가져오기 */
    led->gpio = devm_gpiod_get(&pdev->dev, "status", GPIOD_OUT_HIGH);
    if (IS_ERR(led->gpio)) {
        dev_err(&pdev->dev, "Failed to get GPIO\n");
        return PTR_ERR(led->gpio);
    }

    platform_set_drvdata(pdev, led);
    dev_info(&pdev->dev, "LED driver probed\n");

    return 0;
}

static int led_remove(struct platform_device *pdev) {
    dev_info(&pdev->dev, "LED driver removed\n");
    return 0;
}

static const struct of_device_id led_of_match[] = {
    { .compatible = "gpio-leds" },
    {},
};
MODULE_DEVICE_TABLE(of, led_of_match);

static struct platform_driver led_driver = {
    .probe = led_probe,
    .remove = led_remove,
    .driver = {
        .name = "led_driver",
        .of_match_table = led_of_match,
    },
};

module_platform_driver(led_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Platform LED Driver");

코드 설명

  1. of_device_id: Device Tree의 compatible 항목과 매칭하기 위한 구조체입니다.
  2. led_probe: Device가 매칭되었을 때 호출됩니다. 이 함수에서 GPIO 핀을 초기화합니다.
  3. led_remove: Driver가 제거될 때 호출됩니다.
  4. module_platform_driver: Driver를 커널에 등록합니다.

3. 커널 빌드 및 로드

  1. 위 코드를 drivers/leds/ 디렉토리에 저장하고, Makefile에 추가합니다.
obj-m += led_driver.o
  1. 커널을 빌드하고 모듈을 로드합니다.
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- modules
insmod led_driver.ko
  1. dmesg로 로그를 확인합니다.
dmesg | grep "LED driver"

4. 작동 확인

GPIO 핀의 상태를 제어하여 LED가 정상적으로 켜지고 꺼지는지 확인합니다.

Device Tree와 Platform Driver 연동

Platform Driver는 Device Tree의 정보를 기반으로 하드웨어를 제어합니다. compatible 속성을 사용해 Driver와 Device를 매칭합니다. 이를 통해 Driver는 하드웨어 초기화, 인터럽트 처리, 데이터 전송 등을 수행할 수 있습니다.

마무리

이번 포스팅에서는 Platform Driver 작성, Device Tree와의 연동 과정을 Rockchip RK3399를 기준으로 설명했습니다. 임베디드 시스템에서 Platform Driver는 하드웨어와 소프트웨어를 연결하는 핵심 요소입니다. 이를 기반으로 다양한 드라이버를 작성해보세요!

728x90
반응형