임베디드 개발/리눅스 디바이스 드라이버16 LDD ] Device Tree (DT) 디바이스 트리 디바이스 트리(Device Tree, DT)란 하드웨어의 구조와 특성을 운영체제나 소프트웨어가 이해할 수 있도록 기술한 데이터 구조이다.이전에는 커널 소스에 하드웨어 정보를 하드코딩하는 방식이었다면 디바이스 트리 파일의 등장으로 인해 다양한 하드웨어를 단일 커널 이미지로 지원할 수 있게 되었다. 이로 인해 코드 중복이 줄어들고 유지보수성이 향상되는 이점이 있다. 디바이스 트리의 주요 목적은 다음과 같다.플랫폼 식별 : 커널이 실행 중인 플랫폼(보드)의 하드웨어 구조와 자원을 설명하여 플랫폼에 맞는 초기화 과정을 수행할 수 있도록 함디바이스 등록 : 디바이스 트리 데이터를 파싱하여 커널 내부 데이터 구조를 생성하고 디바이스 드라이버로 전달함 디바이스 트리의 계층적 작성 및 재사용.. 2025. 3. 27. LDD ] PCIe 디바이스 드라이버 작성하기 - (4) with sysfs 이번 글 역시 PCIe 디바이스를 다루는 것보다 디바이스 드라이버 작성 방식에 대해 초점을 맞추도록 한다. 디바이스 드라이버 with sysfs 직전 글에서 사용한 코드를 약간 수정하여 sysfs 인터페이스를 구현하는 디바이스 드라이버를 작성해보도록 하자. sysfs란?sysfs는 커널 객체(Kernel Object, kobject) 및 해당 객체의 속성 정보(attribute)를 사용자 공간에 노출하는 파일 시스템을 말하며, /sys 디렉토리에 마운트된다. sysfs에서 커널 객체(kobject)는 디렉토리를 나타내고, 속성(attribute)는 디렉토리 내의 파일로 표현되어 해당 객체의 상태 정보 또는 설정값을 제공한다. 그리고 리눅스 커널의 디바이스(struct device)와 드라이버(str.. 2025. 3. 18. LDD ] 커널 메모리 할당 함수 (kmalloc, kzalloc 등) kmalloc / kzallockmalloc과 kzalloc은 커널 공간에서 연속된 메모리를 동적으로 할당하는 함수로, 사용자 공간의 malloc, calloc과 유사하지만 커널 내부에서만 사용된다. 참고로 이 두 함수로 할당 가능한 최대 메모리 크기는 시스템의 page size에 의존하며, 일반적인 page size인 4KB보다 작은 크기의 객체를 할당할 때만 사용하는 것이 권장된다. 만약 4KB 이상의 메모리를 할당하려면 vmalloc 등 다른 메모리 할당 함수를 사용해야 한다. 한편 이 두 함수를 사용에 할당된 메모리는 사용이 끝나면 반드시 kfree를 통해 해제하여 메모리 누수를 방지해야 한다. kmalloc과 kzalloc의 차이는 다음과 같다.kmalloc : 할당된 메모리는 초기화되지 않는다.. 2025. 3. 12. LDD ] PCIe 디바이스 드라이버 작성하기 - (3) with Interrupt 이번 글에서는 PCIe 디바이스를 다루는 것보다 디바이스 드라이버 작성 방식에 대해 초점을 맞추도록 한다. 디바이스 드라이버 with 인터럽트 직전 글에서 사용한 코드를 약간 수정하여 디바이스 드라이버에서 인터럽트를 핸들링하는 방법을 알아보도록 하자.2024.11.29 - [임베디드 개발/리눅스 디바이스 드라이버] - LDD ] PCIe 디바이스 드라이버 작성하기 - (2) 하드웨어 장치는 특정 작업을 완료하거나 상태가 변경될 때 CPU에 인터럽트를 발생시켜 처리를 요청하는데 이를 IRQ(Interrupt Request)라고 한다. 그리고 디바이스 드라이버는 인터럽트가 발생했을 때 호출될 IRQ 핸들러를 등록하여 인터럽트를 처리할 수 있다. 이번 목표는 PSR 레지스터를 타이머를 사용해서 폴링으로 체.. 2025. 3. 3. LDD ] 커널 시간 관련 함수 사용법 1. HZ와 jiffies HZ초당 발생하는 타이머 인터럽트의 수를 나타내는 상수로, 플랫폼마다 다르지만 일반적으로 250으로 설정된다. jiffies커널에서 사용하는 시간 단위의 전역 변수로, 부팅 이후 매 타이머 인터럽트마다 1씩 증가하는 tick 카운터이다. 즉, jiffies는 초당 HZ의 수 만큼 증가하며, HZ가 250으로 설정된 경우 1 jiffy는 1 / HZ = 1 / 250 = 4ms이다. 현재 시스템의 HZ 값을 터미널에서 확인하는 법현재 실행 중인 커널의 컴파일 시 설정 정보는 /boot/config-$(uname -r) 이름으로 파일시스템에 노출되는데, 해당 파일에서 다음 명령을 통해 HZ 설정값을 확인할 수 있다. grep CONFIG_HZ /boot/config-$(unam.. 2025. 2. 27. Linux Kernel ] Container_of Container_ofContainer_of는 리눅스 커널에서 매우 유용하게 자주 쓰이는 매크로로 구조체 멤버의 포인터로부터 해당 멤버가 속한 구조체의 시작 주소를 얻는데 사용된다. Container_of 매크로의 정의는 다음과 같으며, 인자로 '구조체 멤버의 포인터', '전체 구조체의 타입', '구조체 멤버의 이름'을 받고 '전체 구조체의 시작 주소'를 반환한다. #define container_of(ptr, type, member) ({ \ void *__mptr = (void *)(ptr); \ static_assert(__same_type(*(ptr), ((type *)0)->member) || \ __same_type(*(ptr), void), \ "p.. 2025. 2. 6. Linux Kernel ] Error Handling 커널의 에러 코드 정의 리눅스 커널에서 사용되는 에러 코드들은 아래 파일들에 정의되어 있다.- include/uapi/asm-generic/errno-base.h- include/uapi/asm-generic/errno.h errno-base.h 파일은 기본 에러 코드들을 정의하며, error.h 파일은 errno-base.h 파일을 포함하며 추가적으로 아키텍처나 환경에 따라 확장된 에러 코드를 제공한다. errno-base.h/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */#ifndef _ASM_GENERIC_ERRNO_BASE_H#define _ASM_GENERIC_ERRNO_BASE_H#define EPERM 1 /* Operatio.. 2025. 2. 3. Device tree compiler 사용법 Device tree compiler는 Device tree 파일을 컴파일/디컴파일하기 위한 도구로 아키텍처에 종속되지 않는 독립적인 표준을 따른다. 설치 방법$ sudo apt update$ sudo apt install device-tree-compiler 기본 사용법 (dts ↔ dtb/dtbo) # dtc -I -O -o # dtb -> dts 디컴파일$ dtc -I dtb -O dts -o extracted.dts source.dtb# dts -> dtb 컴파일$ dtc -I dts -O dtb -o compiled.dtb source.dts 현재 시스템(proc/device-tree)의 장치 트리를 dts로 추출 dtc -I fs -O dts -o output.dts /pro.. 2025. 1. 27. LDD ] PCIe 디바이스 드라이버 작성하기 - (2) Parallel Port에 대해서먼저 맨땅에 데이터시트를 읽으려니 이해가 힘들어서 Parallel port 프로토콜에 대해 대충 알아봤다. Parallel port란 물리적인 포트를 의미하기도 하지만, 이를 통해 이루어지는 통신 방식도 포함한다. 먼저 Parallel port는 보통 DB-25 커넥터를 사용하며 아래 핀 배열을 기반으로 한다. 핀 번호신호 이름설명방향1Strobe데이터 전송 시작 신호출력2-9Data0-Data78비트 데이터 라인출력(기본)/입력10Ack데이터 수신 확인 신호입력11Busy장치 사용 중 신호입력12Paper-Out용지 부족 신호입력13Select장치 선택 신호입력14Auto Feed자동 줄 바꿈 제어출력15Error장치 오류 신호입력16Initialize장치 초기화 제어출.. 2025. 1. 15. VSCode에서 리눅스 커널 모듈 개발시 Intellisense Error 없애기 Workspace에서 .vscode/c_cpp_properties.json 추가 (Ctrl + Shift + P > Edit Configuration) 그리고 커널 모듈 코드 작성시 필요한 매크로와 헤더 경로를 추가해주면 된다. { "configurations": [ { "name": "Linux", "includePath": [ "${workspaceFolder}/**", "/usr/include", "/usr/local/include", "/usr/src/linux-headers-5.4.0-150-generic/include", .. 2024. 12. 29. LDD ] PCIe 디바이스 드라이버 작성하기 - (1) PCIe 카드 구입 이제부터 PCIe 리눅스 디바이스 드라이버를 공부해보려고 PCIe 카드 하나를 구입했다. 학습용으로 사용할거기 때문에 네이버에서 낮은 가격순으로 정렬해서 가장 저렴한걸 구입해봤다. COMS 사의 SW562 제품으로 CH382L 칩셋을 탑재한 x1 슬롯 타입 PCIe 페러럴 포트 카드이며 윈도우 디바이스 드라이버CD와 함께 제공된다. 📝 페러럴 포트란? Parallel Port는 예전에는 프린터, 스캐너, 산업용 장비 등 다양한 외부 장치를 연결하는 데 사용되었지만, 최근에는 USB나 네트워크 연결 방식으로 대체되어 PC에서 기본적으로 제공되지 않는 경우가 많다. 때문에 레거시 장비와 호환을 위해서 PCIe 슬롯에 꼽으면 PC에 Parallel Port를 추가해주는 이런 확장 카.. 2024. 12. 25. LDD ] printk를 활용한 디버깅 1. printk커널 공간에서는 C 표준 라이브러리를 사용할 수 없으므로 printf와 유사한 printk를 사용한다. 2. printk 사용법사용법은 printf와 거의 동일하며 단순히 printf를 printk로 대체하면 된다.단, %f, %e 등 부동소수점 형식의 포맷지정자는 지원하지 않으며, linux/Documentation/printk-formats.txt에서 사용 가능한 포맷지정자를 확인할 수 있다. ex.printk("num: %d, hex: %x\n", num, hex_num); Typeprintk format specifierint%d / %xunsigned int%u / %xlong%ld / %lxunsigned long%lu / %lxlong long%lld / %llxunsig.. 2024. 10. 6. LDD ] 리눅스 커널 모듈 In-tree building In-tree 빌드란? In-tree 빌드는 커널 모듈을 리눅스 커널 소스 트리 안에 추가하여 커널 빌드 시스템이 커널과 함께 해당 모듈을 빌드하도록 하는 방법이다. 이 방법을 사용하면 사용자는 menuconfig 명령어를 통해 메뉴 형태로 구성된 커널 설정 화면에서 모듈을 선택하거나 선택해제할 수 있다. In-tree building 과정 요약리눅스 커널 소스 트리 내에 모듈 추가로컬 Kconfig 파일 작성로컬 Makefile 작성상위 레벨 Kconfig 파일에 로컬 Koconfig 파일 추가상위 레벨 Makefile에 로컬 Makefile 추가커널 소스 루트 디렉토리로 이동해서 make menuconfig를 이용해 설정 (Optional)커널 소스 루트 디렉토리로 이동해서 모듈 빌드 1. 리눅.. 2024. 10. 4. LDD ] Hello World 커널 모듈 + Makefile 작성법 가장 단순한 예시인 Hello World 모듈로 커널 모듈을 빌드하고 실행해보면서 커널 모듈 작성법을 익혀보자. hello.c /* HEADER SECTION BEGIN */#include/* HEADER SECTION END *//* CODE SECTION BEGIN */static int __init hello_init(void){ pr_info("Hello world\n"); return 0;}static void __exit hello_exit(void){ pr_info("Goodbye world\n");}/* CODE SECTION END *//* REGISTRATION SECTION BEGIN */module_init(hello_init);module_exit(hello_e.. 2024. 10. 2. modprobe와 insmod의 차이 1. modprobe커널 모듈을 로드하는데 사용하는 명령어로 모듈의 이름만 지정하면 /lib/modules/$(uname -r) 경로에서 해당 모듈과 모듈의 의존성을 자동으로 처리해 로드한다.(ex. modprobe e1000e) 2. insmod커널 모듈 파일을 직접 로드하는 명령어로 모듈 파일(.ko)의 경로를 지정하여 로드해야 하며 모듈의 의존성을 자동으로 처리하지 않는다.(ex. insmod /lib/modules/$(uname -r)/kernel/drivers/net/ethernet/intel/e1000e.ko) 2024. 9. 30. 리눅스 커널 모듈 (Linux Kernel Module) 1. Linux Kernel Module리눅스 커널 모듈은 리눅스 커널에 동적으로 로드하거나 언로드할 수 있는 코드 조각으로 커널의 기능을 확장하거나 특정 기능을 추가할 때 사용된다. 커널 모듈은 실행 중인 커널에 동적으로 추가될 수 있어 커널을 재부팅하지 않고도 기능을 추가하거나 제거할 수 있는 장점이 있다. 2. Linux Device Driver디바이스 드라이버는 특정 하드웨어 장치를 제어하기 위해 커널에서 실행되는 소프트웨어이다. 하드웨어 장치와 커널 간의 인터페이스를 제공하여 응용 프로그램이 하드웨어를 제어할 수 있게 하는 용도로 사용되며, 대부분의 디바이스 드라이버는 커널 모듈로 구현된다. 이를 통해 사용자가 원하는 하드웨어를 커널에 동적으로 추가하거나 제거할 수 있다. 즉, 커널 모듈은 .. 2024. 9. 28. 이전 1 다음