728x90
반응형
서론: 왜 이제는 DM(Driver Model)인가?
과거의 임베디드 드라이버는 하드웨어 레지스터에 직접 접근하거나 전역 함수를 호출하는 방식이 많았습니다. 하지만 시스템이 복잡해지면서 유지보수와 확장성을 위해 DM(Driver Model) 도입이 필수적이 되었습니다.
이번 포스트에서는 U-Boot 및 최신 임베디드 시스템에서 표준으로 자리 잡은 DM 기반 I2C 드라이버의 구조와 실제 코드 작성법을 살펴보겠습니다.

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)
- Probe 시점: probe 함수 내에서 클럭(Clock)과 핀매핑(Pinmux)이 선행되어야 합니다.
- UCLASS 확인: dm tree 명령어를 통해 I2C 컨트롤러가 정상적으로 UCLASS_I2C 아래에 바인딩 되었는지 확인하십시오.
- 오류 반환: I2C 통신 실패 시 -ETIMEDOUT 또는 -EIO 등 적절한 에러 코드를 반환해야 상위 레이어에서 예외 처리가 가능합니다.
마치며
DM 기반 드라이버는 처음에는 구조가 복잡해 보일 수 있지만, 한 번 구현해 두면 Device Tree 수정만으로 다양한 하드웨어 변경에 유연하게 대응할 수 있습니다.
반응형
'Embedded System > Bootloader & System Startup' 카테고리의 다른 글
| U-Boot 네트워크 설정 및 OTA 업데이트 구현 가이드 (TFTP, NFS, 보안부팅) (0) | 2025.12.11 |
|---|---|
| U-Boot 디버깅 가이드: UART 로그부터 부트 로고 커스터마이징까지 (0) | 2025.12.10 |
| U-Boot 커널 및 RootFS 로딩 완벽 가이드 (0) | 2025.12.09 |
| 임베디드 리눅스 U-Boot 환경 변수 설정 및 활용 가이드 (0) | 2025.12.08 |
| U-Boot 사용자 정의 명령 추가 가이드: U_BOOT_CMD 완벽 분석 (0) | 2025.12.07 |