3.1 데이터시트와 레지스터
향후 추가
3.2 디바이스 드라이버 표준 API
1. 디바이스 드라이버 작성 절차
1) 디바이스 드라이버 이름, 주번호 결정
2) 코어 함수 구현
3) 커널 연계 래퍼 작성 : 코어 함수를 커널에 등록하기 위해 리눅스 디바이스 드라이버가 참조하는 파일 오퍼레이션 구조체 (fops)에 대한 인터페이스 함수 구현
ㄴ open(), release(), read(), write(), ioctl() 인터페이스 함수 구현
ㄴ file_operations 구조체에 인터페이스 함수 등록
4) 커널에 등록 : 커널 내부 함수(register_XXXdev) 이용하여 개발한 디바이스 드라이버를 Insmod 명령을 이용하여 커널에 등록
5) 장치 파일 생성 : mknod 명령을 이용하여 디바이스 파일을 생성

2. 디바이스 드라이버 예제
#include <kernel.h>
#include <module.h>
#include <device.h>
#define DEVICE_NAME "MyTestDrv"
int result;
static const struct file_operations fops =
{
.owner = THIS_MODULE,
.open = myDrv_open,
.release = myDrv_release
};
int myDrv_open(struct inode *inode_p, struct file *fp){
}
int myDrv_release(struct inode *inode_p, struct file *fp){
}
static int myDrv_init(void)
{
result = register_chrdev(0, DEVICE_NAME, &fops);
printk("device number %d is registered", result);
return 0;
}
static void myDrv_exit(void)
{
unregister_chrdev(result, DEVICE_NAME);
printk("device number %d is unregistered", result);
}
module_init(myDrv_init);
module_exit(myDrv_exit);
3.3 디바이스 드라이버 저수준 OS API 활용하기
1. 디바이스 드라이버 데이터 전송 과정
1) 데이터 전송 과정에 필요한 별도 API
① get_user(void* x, constant void *addr)
- 사용자 공간 영역에서 커널 공간 영역으로 데이터 복사
② put_user(void* x, constant void *addr)
- 커널 공간 영역에서 사용자 공간 영역으로 데이터 복사
③ copy_to_user(void* to, void* from, unsigned long size)
- 커널 공간 영역에서 사용자 공간 영역으로 데이터 복사
④ copy_from_user(void* to, void* from, unsigned long size)
- 사용자 공간 영역에서 커널 공간 영역으로 데이터 복사
3.4 디바이스 드라이버 초기화 및 접근
1. 디바이스 드라이버 등록 / 해제
1) 모듈 초기화
- register_XXXdev() 함수 사용
ㄴ 실행 결과 성공 시 Major Number 반환
2) 모듈 커널 해제
- unregister_XXXdev() 함수 사용
3.5 Make 파일의 이해
1. Make 파일
1) make
- Unix/Linux 계열에서 빌드 자동화 지원하는 명령어
- Makefile이라는 명칭의 파일을 참조하여 빌드를 진행
2) Makefile
① Makefile 기본 규칙
<Target>: <Dependencies>
<Recipe>
- Target : 빌드 대상 이름. 최종적으로 생성하는 파일명
- Dependencies : 빌드 대상이 의존하는 대상. 여기에 명시된 라벨 명령들이 이미 완료된 상태여야 Target이 실행됨
- Recipe : 빌드 대상 생성하는 명령. 반드시 Tab 문자로 된 Indent 필요
② Makefile 옵션
- -D : #define과 같이 선언 정의
- -D__KERNEL__ : 커널의 변수와 함수를 사용한다는 정의
- -DMODULE : 모듈 형태로 로드 되어 사용한다는 정의
- -W : warning 출력
- -Wall : 모든 warning 출력
- -I : include
3.6 인터럽트 처리 절차
1. 인터럽트
1) 인터럽트 등록
① 인터럽트 등록은 request_irq 함수를 이용한다
int request_irq(unsigned int irq, irqreturn_t (*handler) (int, void *, struct pt_regs *), unsigned long flags, const char* dev_name, void* dev_id)
- unsigned int irq : 요청 인터럽트 번호
- *handler : 인터럽트를 처리할 함수 포인터
- unsigned long flags : 인터럽트 관리 옵션 비트 마스크
ㄴ IRQ_DISABLED : 인터럽트 발생 비활성화
ㄴ IRQF_SHARED : 인터럽트 공유
ㄴ IRQF_SAMPLE_RANDOM : 난수를 발생
- dev_name, dev_id : 인터럽트 소유자 정보 문자열, 포인터
2) 인터럽트 해제
void free_irq(unsigned int irq, void* dev_id)
- unsigned int irq : 요청 인터럽트 번호
- void *dev_id : request_irq에서 사용한 dev_id 값
3) 인터럽트 활성화 / 비활성화
① 모든 인터럽트
- 비활성화
ㄴ void local_irq_save(unsigned long flags)
ㄴ void local_irq_disable(void)
- 활성화
ㄴ void local_irq_restore(unsigned long flags)
ㄴ void local_irq_enable(void)
② 특정 인터럽트
- void disable_irq(int irq)
- void enable_irq(int irq)
2. 커널 타이머
1) 커널 타이머
- 사용자가 정의한 함수가 특정 시간에 실행되도록 하는 역할을 함
2) 커널 타이머 함수
- init_timer : 커널 타이머 구조체 초기화
- add_timer : 커널 타이머 수행될 함수 등록
- del_timer : 커널 타이머 목록에서 등록된 것 제거
# References
- https://wogh8732.tistory.com/304
'임베디드 기사 > 실기 - 임베디드 펌웨어' 카테고리의 다른 글
| 임베디드 펌웨어 실기 용어 정리 (0) | 2023.10.07 |
|---|---|
| 2. 임베디드 이해 및 포팅하기 (0) | 2023.09.24 |
| 1. 펌웨어 설계, 구현 및 테스팅 하기 (0) | 2023.09.16 |