디바이스 드라이버
우선 결론부터 시작하자
디바이스는 하드웨어를 말한다.
드라이버는 하드웨어를 다루는 소프트웨어를 말한다.
예를 들어보자.
UART 칩이 16개 달려있다고 했을 때 이를 제어하는 드라이버는 하나이다.
하지만 UART 칩이 16개 이니 디바이스는 16개 이다.
이제 리눅스 커널로 확장해 보자
arm 코아의 커널을 다루게 되면 항상 수정하거나 참고하는 파일이 있다.
EM-S5PV210 기준으로
arch/arm/mach-s5pv210/mach-ezs5pv210.c 파일이다.
이곳에서 보면 struct platform_device 구조체를 흔히 볼수 있다.
이 구조체의 몇몇 멤버를 보자
- name 문자열 이름
- id 정수형 아이디
- resource 리소스 구조체 포인터 (리소스 구조체는 하드웨의 주소나 인터럽트 정보가 나열된다.)
- num_resources 리소스 구조체 개수
다신한번 이 구조체의 이름이 struct platform_device 이다. 즉 디바이스인 것이다.
이 구조체는 아래의 함수를 통해 등록된다.
- platform_add_devices() 여러개의 디바이스들을 한번에 등록
- platform_device_register() 하나의 디바이스를 등록
이제 커널의 driver 디렉토리의 무수한 소스파일들을 보자
모두다 struct platform_driver 구조체를 품고 있다.
이제 struct platform_driver 구조체의 주요한 멤버를 보자
- probe 초기 실행함수
- remove 드라이버 제거시 실행되는 함수
- driver = { .name 드라이버 이름
이 구조체는 platform_driver_register() 함수를 통해 등록된다.
이제 흐름을 따라가 보자
커널 시작시 디바이스들이 등록된다. 리소스가 등록되는 것이다. UART칩이 16개 있다면 디바이스가 16 등록된다.
잠시후에 커널 드라이버가 등록된다. 이때 드라이버의 이름과 동일한 디바이스의 이름이 발견되면 probe() 함수가 호출된다.
동일한 이름의 디바이스가 16개 있다면 이 probe() 함수가 16번 호출된다.
참고해야 할것은 struct platform_device 구조체의 id 이다.
디바이스가 하나만 있다면 이값은 -1 로 설정한다. 하지만 2개 이상일 경우 id 는 0 부터 시작해서 각 디바이스마다 고유한 값을 넣는다.,
대게 1씩 순서대로 값을 넣는다.
struct platform_device 의 멤버 name 과 struct platform_driver 의 멤버 driver.name 은 동일한 값을 갖는다.
디바이스가 하나일 경우 디바이스의 이름과 드라이버의 이름은 같다.
하지만 디바이스가 여러개 일 경우 드라이버 이름은 보이는 대로의 이름이지만
디바이스의 경우 uart.0 uart.1 이렇게 숫자를 달고 나온다. id 로 확장된 것이다.
아래의 매크로를 이용하여 디바이스 이름을 얻는다.
- dev_name(&platform_device->dev)
이제 디바이스 드라이버가 한결 쉬워질 것이다. ^^