● 대부분 디바이스 드라이버는 두 가지 문맥으로 동작
● Top half
– 인터럽트 컨텍스트에서 동작
– 인터럽트 핸들러
● 제한된 환경
● 일부 커널 함수 호출 불가
– Sleep 함수(예: mutex) 호출 불가
● Bottom half
– 보통 스레드(커널 스레드) 컨텍스트에서 동작
● sleep 함수 또는 blocking lock(mutex와 같은)호출 가능
● 일반적으로는 ISR은 아래와 같은 절차로 진행
● Acknowledge to device
– 다음 인터럽트를 받을 수 있도록
● 전반부 처리
– 레지스터 read/write
● wake_up_interruptible(&queue);
– 대기 중인 커널 스레드 wake_up
● Softirq/Tasklet
– TIMER, NET, BLOCK HRTIMER, RCU등 커널의 중요한 드라이버에서 사용
– 일반적으로 threaded irq, workqueue, kthread 이용
● Threaded IRQ
– 인터럽트 핸들러가 커널 스레드로 동작함
– Block/sleep 가능(I2C/SPI)에 필요
– 동적으로 priority 설정 가능
● 이유는 threaded irq에서 사용하는 thread는 real-time 클래스로 동작하고 있음.
● 워크큐(Workqueues)
– 대기중인 스레드 필요 없음
– Worker thread 이용
– 사용하기 편함
– 다음 시간에 실습 예정
● 인터럽트 핸들러가 커널 스레드(Real-time)로 동작함
– Block/sleep 가능
– 동적으로 priority 설정 가능
– thread_fn은 real-time 클래스로 동작
●
int request_threaded_irq(struct device dev, unsigned int irq,
irq_handler_t handler, irq_handler_t thread_fn,
unsigned long flags, const char name,
void *dev);
– handler: 인터럽트 핸들러(보통 NULL)
– thread_fn: 스레드로 동작하는 인터럽트 핸들러
● 인터럽트 컨텍스트
– Bottom half이지만 sleep 불가능
● 동적으로 등록 못함
● TIMER_SOFTIRQ, NET_TX/RX_SOFTIRQ, BLOCK_SOFTIRQ
● 가장 빠르게 실행
– 일반 디바이스 드라이버에서는 사용하지 않음.
● 동적으로 생성 가능
● 인터럽트 컨텍스트
– Bottom half이지만 sleep 불가능
● 빠르게 실행
– sleep이 불가능
● 커널 스레드로 동작(워커 스레드)
● 사용하기 쉽다.
● GPIO input으로 설정하여 외부 인터럽트로 사용 가능
– 예) 버튼 입력, Door, Touch, Sensor interrupts
● Push 버튼 등 물리적인 문제
– 채터링 방지 처리 필요
– Debounce
● 인터럽트 기반으로 구현
– ISR에서 kthread wake-up
– ISR에서 user application에 signal 전송