Embedded System/Bootloader & System Startup

U-Boot 드라이버 모델(DM) 이해하기: I2C 제어부터 디바이스 트리 설정까지

임베디드 친구 2026. 5. 10. 15:09
728x90
반응형

서론: 왜 이제는 DM(Driver Model)인가?

과거의 임베디드 드라이버는 하드웨어 레지스터에 직접 접근하거나 전역 함수를 호출하는 방식이 많았습니다. 하지만 시스템이 복잡해지면서 유지보수와 확장성을 위해 DM(Driver Model) 도입이 필수적이 되었습니다.

이번 포스트에서는 U-Boot 및 최신 임베디드 시스템에서 표준으로 자리 잡은 DM 기반 I2C 드라이버의 구조와 실제 코드 작성법을 살펴보겠습니다.

Generated by Gemini AI.


1. DM I2C 드라이버의 핵심 구조

DM(Driver Model) 체계에서 I2C 드라이버는 크게 두 가지 핵심 구조체를 구현해야 합니다.

  • struct dm_i2c_ops: 실제 하드웨어 제어 함수(xfer, probe, set_speed 등)를 정의하는 인터페이스입니다.
  • U_BOOT_DRIVER: 드라이버의 이름, ID, 그리고 위에서 정의한 ops를 시스템에 등록하는 매크로입니다.

2. 핵심 코드 구현: dm_i2c_ops 정의

가장 먼저 하드웨어가 실제로 어떻게 데이터를 주고받을지 정의해야 합니다.

C
 
#include <common.h>
#include <dm.h>
#include <i2c.h>

/* 1. I2C 통신을 위한 실제 동작 정의 */
static int my_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
{
    /* 
     * 하드웨어 레지스터 제어 로직 
     * bus: I2C 컨트롤러 장치
     * msg: 전송할 데이터 메시지 (Read/Write 구분)
     */
    // TODO: Implement Hardware Specific Transfer
    return 0;
}

static int my_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
{
    // TODO: Implement Speed Control (100kHz, 400kHz 등)
    return 0;
}

/* 2. Operations 구조체 연결 */
static const struct dm_i2c_ops my_i2c_ops = {
    .xfer           = my_i2c_xfer,
    .set_bus_speed  = my_i2c_set_bus_speed,
};

3. 드라이버 등록 및 매칭 (Device Tree)

작성한 드라이버가 어떤 하드웨어와 매칭될지 Device Tree의 compatible 문자열을 통해 지정합니다.

C
 
/* 3. Device Tree 매칭 정보 */
static const struct udevice_id my_i2c_ids[] = {
    { .compatible = "myvendor,my-i2c-controller" },
    { }
};

/* 4. 드라이버 메타데이터 등록 */
U_BOOT_DRIVER(my_i2c_drv) = {
    .name   = "my_i2c_drv",
    .id     = UCLASS_I2C,        /* I2C 클래스로 등록 */
    .of_match = my_i2c_ids,
    .ops    = &my_i2c_ops,       /* 위에서 만든 ops 연결 */
    .priv_auto_alloc_size = sizeof(struct my_i2c_priv),
};

4. Device Tree (dts) 설정 예시

보드 설정 파일(.dts)에서 컨트롤러를 활성화하는 것도 잊지 마세요.

코드 스니펫
 
&i2c0 {
    compatible = "myvendor,my-i2c-controller";
    reg = <0x12340000 0x1000>;
    status = "okay";
    clock-frequency = <400000>;

    eeprom@50 {
        compatible = "atmel,24c02";
        reg = <0x50>;
    };
};

5. 개발 시 주의사항 (Troubleshooting)

  1. Probe 시점: probe 함수 내에서 클럭(Clock)과 핀매핑(Pinmux)이 선행되어야 합니다.
  2. UCLASS 확인: dm tree 명령어를 통해 I2C 컨트롤러가 정상적으로 UCLASS_I2C 아래에 바인딩 되었는지 확인하십시오.
  3. 오류 반환: I2C 통신 실패 시 -ETIMEDOUT 또는 -EIO 등 적절한 에러 코드를 반환해야 상위 레이어에서 예외 처리가 가능합니다.

마치며

DM 기반 드라이버는 처음에는 구조가 복잡해 보일 수 있지만, 한 번 구현해 두면 Device Tree 수정만으로 다양한 하드웨어 변경에 유연하게 대응할 수 있습니다.

반응형