본문 바로가기

CS/[Embedded]Embedded System Software

[Embedded]Install / Free an Interrupt Handler

Interrupt Handler는 HW를 관리하는 device driver가 담당한다. 각 장치 별로 driver가 존재하며, interrupt를 사용하는 장치라면 driver에서 interrupt handler를 등록하게 된다.

 

driver는 <linux/interrupt.h> 파일에 정의된 request_irq() 함수를 이용해 interrupt를 활성화 시키고, interrupt handler를 등록한다.

 

linux에서의 interrupt handling 과정은 위 그림과 같다.

1. device driver에서 request_irq 함수를 이용하여 interrupt handler를 kernel에 등록 시킨다.

->insmod 시 등록됨

2. HW에서 IRQ interrupt가 발생하면 해당 번호에 맞는 IRQ interrupt handler를 call 한다.

3.  rsmod 시 free_irq 함수를 통해 커널에서 interrupt handler를 제거한다.

 

Install Free an interrupt handler

request_irq 함수를 이용하여 interrupt handler를 install 한다.

넘겨주는 parameter은 아래와 같다.

첫 번째 인자를 통해 할당할 interrupt를 지정한다.

시스템 타이머나 키보드 같은 기본 장치의 경우는 보통 이 값이 고정되어 있다. 이외의 장치들은 동적으로 정해지게 된다.

 

두 번째 인자는 interrupt를 처리할 실제 interrupt handler를 가리키는 함수 포인터를 넘겨준다.

OS는 interrupt를 받고 처리할 때마다 해당 함수를 실행한다.

 

세 번째 인자는 0 또는 <linux/interrupt.h>에 정의된 flag를 조합한 비트 마스크 값을 사용한다.

IRQF_DISABLED  플래그가 설정되면 커널은 interrupt handler를 실행하는 동안 모든 인터럽트를 비활성화 시킨다. 

IRQF_SHARED 플래그가 설정되면 여러 interrupt handler 가 같은 interrupt를 공유할 수 있게 된다. interrupt를 공유하는 모든 핸들러가 이 플래그를 사용해야 한다. flag를 사용하지 않는다면 interrupt 당 하나의 handler 만 존재할 수 있다.

 

네 번째 인자는 device name 이다. 사용자와 통신할 때 해당 이름을 사용하게 된다.

 

다섯 번째 인자는 interrupt를 공유할 때 사용한다. 공유 interrupt가 아니라면 해당 값을 NULL 값으로 지정한다. 공유 interrupt 라면 고유한 값을 지정해 주어야 한다.

해당 값은 핸들러를 호출할 때에도 지정해 줌으로서 공유 interrupt의 어떤 handler를 활용하는지 알려주어야 한다.

보통 해당 값은 driver의 장치 구조체 포인터를 넘겨주는 방식을 일반적으로 많이 사용한다.

 

이렇게 등록에 성공하게 되면 request_irq 함수는 0을 반환한다.

 

추가적으로 request_irq 함수는 휴면 상태를 허용하기 때문에 interrupt context에 있을 때나 코드 실행이 중단돼서는 안되는 상황에서는 호출할 수 없다.

 

해제는 free_irq함수를 이용하여 해제한다.

만약 해제할 interrupt가 공유 interrupt가 아니라면, 해당 함수는 handler를 제거하고 interrupt line 도 비활성화 시킨다.

공유 interrupt라면 dev 인자로 지정한 handler를 제거하고 handler가 모두 제거된 상태라면 interrupt line 도 비활성화 시킨다.

 

free_irq 함수는 process context에서 호출해 주어야 한다.

 

 

Shared Interrupt

interrupt line은 한정적이기 때문에 shared interrupt가 필요할 경우가 있다.

install, free는 위에 설명한 바와 같이 비공유 handler와 같은 방식으로 request_irq, free_irq 함수를 이용하며, 인자 값을 이용하여 shared interrupt를 등록한다.

shared interrupt handler의 경우는 interrupt를 공유하기 때문에 interrupt line의 모든 handler를 round-robin 으로 차례대로 호출하면서 탐색하고 해당하는 handler를 찾게 된다.

 

따라서, 알맞는 handler를 찾기 위해서 shared interrupt handler에는 모두 해당 interrupt를 발생시킨 것인지 판별할 수 있는 부분이 있어야 한다.

 

차례대로 Handler를 호출하며 handler에서 빠르게 check 하고 해당하지 않으면 바로 종료할 수 있도록 한다.