커널 포팅 (4. 드라이버 포팅 / 4.2 기존 드라이버 포팅)

2025. 3. 6. 19:43프로그래밍/시스템

4.2 기존 드라이버 포팅

기존 보드에서 사용되는 디바이스 드라이버를 확인하고, 이를 새로운 환경에 맞게 포팅하는 과정을 다룹니다.
리눅스에서는 lsmod, modinfo 등을 사용하여 현재 로드된 드라이버를 확인할 수 있으며, 필요한 드라이버를 분석, 수정, 빌드하여 새로운 환경에서 적용할 수 있습니다.


🔹 기존 보드에서 사용되는 드라이버 확인 (lsmod, modinfo)

1️⃣ 현재 로드된 커널 모듈 확인 (lsmod)

lsmod

출력 예시:

Module                  Size  Used by
bcm2835_rng            16384  0
i2c_bcm2835            16384  0
bcm2835_codec          36864  0
bcm2835_v4l2           45056  0
  • Module: 드라이버(커널 모듈) 이름
  • Size: 모듈 크기
  • Used by: 이 모듈을 사용 중인 다른 모듈 또는 프로세스

2️⃣ 특정 드라이버의 상세 정보 확인 (modinfo)

modinfo bcm2835_rng

출력 예시:

filename:       /lib/modules/5.10.17-v7l+/kernel/drivers/char/hw_random/bcm2835-rng.ko
description:    "BCM2835 Random Number Generator driver"
license:        GPL
author:         "Broadcom"
alias:          platform:bcm2835-rng
depends:
vermagic:       5.10.17-v7l+ SMP mod_unload modversions ARMv7
  • filename: 해당 드라이버의 실제 파일 경로
  • description: 드라이버 설명
  • license: 라이선스 정보
  • depends: 필요한 다른 모듈

3️⃣ 특정 드라이버가 어떤 디바이스와 연결되어 있는지 확인

ls /sys/class/net/        # 네트워크 장치 목록 확인
ls /sys/class/gpio/       # GPIO 장치 확인
ls /sys/class/i2c-adapter # I2C 장치 확인

이 정보를 바탕으로 새로운 보드에서도 동일한 기능을 지원할 수 있도록 드라이버를 수정해야 합니다.


🔹 필요한 드라이버 코드 분석 및 수정

드라이버 포팅 과정에서 기존 커널의 드라이버 소스를 분석하고, 새로운 하드웨어 환경에 맞게 수정해야 합니다.

1️⃣ 기존 드라이버 소스 위치 확인 리눅스 커널의 드라이버 소스는 drivers/ 디렉토리에 저장됩니다.

cd linux/drivers/
ls

주요 디렉토리:

  • drivers/char/ → 문자 장치 드라이버 (예: bcm2835_rng)
  • drivers/block/ → 블록 장치 드라이버 (예: mmc, sd)
  • drivers/net/ → 네트워크 드라이버 (예: bcmgenet)
  • drivers/gpio/ → GPIO 드라이버
  • drivers/i2c/ → I2C 드라이버

2️⃣ 드라이버 코드 분석 (drivers/char/bcm2835_rng.c 예시)

static int bcm2835_rng_probe(struct platform_device *pdev)
{
    struct bcm2835_rng_priv *priv;
    struct device *dev = &pdev->dev;

    priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    if (!priv)
        return -ENOMEM;

    priv->base = devm_platform_ioremap_resource(pdev, 0);
    if (IS_ERR(priv->base))
        return PTR_ERR(priv->base);

    return 0;
}
  • probe() → 드라이버가 특정 하드웨어와 연결될 때 실행
  • devm_kzalloc() → 커널 공간에 메모리 할당
  • devm_platform_ioremap_resource() → 디바이스의 I/O 리소스를 매핑

3️⃣ 새로운 SoC에 맞게 드라이버 수정 만약 메모리 매핑 주소가 변경된 경우, 기존 드라이버에서 ioremap()을 호출하는 부분을 수정해야 합니다.

기존 코드:

priv->base = ioremap(0x3f100000, 0x1000);

새로운 SoC에서 사용하는 메모리 주소로 변경:

priv->base = ioremap(0x20000000, 0x1000);

4️⃣ 새로운 하드웨어의 디바이스 트리(DTS) 수정 드라이버가 새로운 SoC에서 동작하려면 디바이스 트리에 해당 장치가 정의되어 있어야 합니다.

기존 bcm2835_rng 드라이버가 지원하는 DTS 항목:

bcm2835_rng: rng@3f104000 {
    compatible = "brcm,bcm2835-rng";
    reg = <0x3f104000 0x1000>;
};

새로운 SoC에 맞게 수정:

my_rng: rng@20040000 {
    compatible = "mycompany,my_rng";
    reg = <0x20040000 0x1000>;
};

이제 드라이버가 새로운 SoC의 하드웨어와 연결될 수 있습니다.


🔹 드라이버 빌드 후 테스트 (insmod, rmmod)

1️⃣ 드라이버 빌드 수정한 드라이버를 빌드하려면 Makefile에 해당 드라이버를 추가하고 커널을 빌드해야 합니다.

예제 Makefile (drivers/char/Makefile 수정)

obj-$(CONFIG_BCM2835_RNG) += bcm2835_rng.o

빌드 명령어:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- modules -j$(nproc)

2️⃣ 빌드된 커널 모듈 확인

find . -name "bcm2835_rng.ko"

3️⃣ 드라이버 로드 (insmod)

sudo insmod bcm2835_rng.ko
  • insmod → 커널 모듈을 로드
  • /dev/ 디렉토리에 해당 장치 파일이 생성되는지 확인

4️⃣ 드라이버 언로드 (rmmod)

sudo rmmod bcm2835_rng
  • rmmod → 커널 모듈을 제거

5️⃣ 모듈 로그 확인 (dmesg)

dmesg | tail -20

출력 예시:

[ 123.456789] bcm2835_rng: Registered new RNG driver

6️⃣ 자동 로딩 설정 (modprobe) 부팅 시 자동으로 드라이버를 로드하려면 modules.conf에 추가:

echo "bcm2835_rng" | sudo tee -a /etc/modules

✅ 정리

  1. 기존 보드에서 사용되는 드라이버 확인
    • lsmod → 현재 로드된 드라이버 확인
    • modinfo → 특정 드라이버 정보 확인
    • /sys/class/ → 디바이스와 연결된 드라이버 확인
  2. 드라이버 코드 분석 및 수정
    • drivers/ 디렉토리에서 기존 소스 분석 (probe(), ioremap() 등)
    • 새로운 SoC의 메모리 주소 및 레지스터 값 수정
    • 디바이스 트리(DTS)를 업데이트하여 새로운 보드에서 장치 인식 가능하게 설정
  3. 드라이버 빌드 및 테스트
    • make modules → 드라이버 빌드
    • insmod, rmmod → 드라이버 로드 및 언로드
    • dmesg → 로그 확인
    • modprobe 설정을 통해 부팅 시 자동 로딩 가능