RaspberryPi/DeviceDriver

Raspberry Pi – Linux Device Driver 만들어 보기-1 (module 형태 만들기)

변화의 물결 2022. 6. 12. 16:23

 

안녕하세요.

 

  라즈베리 파이를 사용하면서 여러 장치들 제어하기 위해서 메인 소스상에서 추가해서 사용했는데, 그것이 아니라 필요에 따라서 등록하고 해제해서 사용할 수 있도록 디바이스 드라이버 모듈로 만들어 보면 좋겠다 생각하였습니다. 그리고 외국분이 작업한 내용이 있어서 참조하면서, 확인해보도록 하겠습니다.

 

  샘플 예제는 Raspberry Pi 3이지만 현재 작업하는 환경은 Raspberry Pi 4 bullseye 32bit에서 테스트 진행하였습니다. 참고로, 라즈베리 파이 전용 디바이스 드라이버라고 하기는 그렇고, 하드웨어 핀과 같은 특정 부분을 제외하면 리눅스 디바이스 드라이버라고 생각해도 될 것 같습니다.


 1. 개발에 필요한 프로그램 설치

 - 디바이스 드라이버 개발에 필요한 커널 헤더와 드라이버 소스를 컴파일을 위한 패키지 프로그램들을 설치해보겠습니다.      

pi@raspberrypi:~ $ sudo apt update
pi@raspberrypi:~ $ sudo apt install raspberrypi-kernel-headers
pi@raspberrypi:~ $ sudo apt upgrade
pi@raspberrypi:~ $ sudo apt-get install -y build-essential cmake vim -y

 

  - 디바이스 드라이버 개발 연습할 디렉터리를 만들고 여기서 작업을 진행합니다. 

pi@raspberrypi:~ $ mkdir ~/DriverStudy/day1 -p
pi@raspberrypi:~ $ cd DriverStudy/day1/
pi@raspberrypi:~/DriverStudy/day1 $ vim day1_module.c​

 

2. 소스 작성

 - 드라이버에 개발에 있어 소스의 기본 형태를 갖추는 작업을 먼저 합니다.

 

1) 헤더 파일

 - 디바이스 모듈을 개발에 필요한 헤더 파일을 추가합니다.    

#include <linux/module.h>
#include <linux/init.h> //module_init, exit를 위해 필요

  

2) 저작권, 개발자 정보 등 모듈 정보 나타내는 매크로에 값을 입력합니다. 

/* Meta Information */
MODULE_LICENSE(“GPL”);
// MODULE_AUTHOR(“Johannes 4 GNU/Linux”); refer source site
MODULE_AUTHOR(“Student 4 GNU/Linux”);
MODULE_DESCRIPTION(“Hello World Day1”);

  

3) 모튤 초기화 함수 구현

  - 모듈을 로드할 때 초기화하는 함수이며, 커널에서는 command line이 없기 때문에 커널 디버깅을 위한 별도의 printk() 함수로 메시지를 출력합니다.

/*
 @ brief This function is called, when the module is loaded into the kernel
 */
static int __init driver_init(void) {
           printk("Hello, Driver Day1!\n");
           return 0;
}

 

  - 모듈을 언로드 할 때 해제하는 함수   

/**
 * @brief This function is called, when the module is removed from the kernel
 */
static void __exit driver_exit(void) {
           printk("Bye Driver Day1\n");
}

 

  - module_init은 커널 내장 모듈로 매크로 함수이며 함수 이름을 넣어줍니다. 그러면 insmod시에 module_init()에 등록한 초기화 함수가 자동으로 호출되도록 등록시켜줍니다. 반대는 “rmmod” shell command에 의해 이루어집니다.   

module_init(driver_init); 
module_exit(driver_exit);

 

3. Makefile 생성

  - 파일을 빌드를 자동화하기 위해서 Makefile를 생성합니다.   

pi@raspberrypi:~/DriverStudy/day1 $ vim Makefile

 

 - 여기서 커널 경로 지정하는 부분을 조심하면 문제없이 컴파일될 것입니다. 그리고 Makefile에서 간격 띄울 때는 탭(Tab)으로 구분해주어야 합니다.      

obj-m += day1_module.o
all:
           make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
           make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

4. 실행 결과 확인

  - 컴파일이 진행된 후 여러 파일이 생성되고 그중에 .ko 파일이 생성된 것을 확인할 수 있습니다.

  

pi@raspberrypi:~/DriverStudy/day1 $ make

 

 

  - insmod, rmmod, lsmod 명령어로 등록과 해제가 잘 되었는지 확인합니다.

pi@raspberrypi:~/DriverStudy/day1 $ sudo insmod day1_module.ko
pi@raspberrypi:~/DriverStudy/day1 $ lsmod | grep day1_module
pi@raspberrypi:~/DriverStudy/day1 $ rmmod day1_module
pi@raspberrypi:~/DriverStudy/day1 $ dmesg | tail

 - 디바이스 드라이버를 등록하고 해제하는 것을 확인할 수 있고 lsmod로 커널에 등록된 module의 정보를 확인할 수 있습니다. (모듈 이름, 상주 모듈에 의해서 사용되는 메모리 양(byte), 사용되고 있는 인스턴스 수를 lsmod 실행하면 나타납니다.)

 

 

감사합니다.

 

 

<참고 사이트>

1. Let's code a Linux Driver - 1: Hello World Linux Kernel Module

https://youtu.be/4tgluSJDA_E?list=PLCGpd0Do5-I3b5TtyqeF1UdyD4C-S-dMa

2. Init call mechanism. 디바이스 드라이버 초기화 호출 체계

https://dreamlog.tistory.com/336

3. 리눅스 커널 모듈이란

https://hyeyoo.com/83

4. 리눅스 lsmod 명령어 정리

https://blankspace-dev.tistory.com/293

day1.zip
0.00MB