Raspi3 OS 만들기위해 Interrupt코드를 구현하면서 헷갈리는 부분이 있다. 먼저 이해한 내용을 정리하면

 

1. ARM Interrupt

기본적으로 라즈베리파이역시 Broadcom ARM기반 chipset으로 ARM Interrupt IRQ, FIQ 모드를 따라 구현되어있다.

인터럽트 모드는 크게 2가지 IRQ, FIQ 되고 FIQ 경우 n번의 거침없이 바로 연결되는 인터럽트로 빠른 우선순위 높은 인터럽트 처리를위해 사용되는 모드이다.

 

우선은 Interrupt개발을 위해 FIQ 재껴두고 IRQ 대해서 고민해보자

인터럽트를 실행하기 위해서는 기본적으로 User, Kernel 모드 다양한 모드에서 동작중인 OS 인터럽트신호를 감지하게 되고 이를 Trigger 하여 IRQ 모드로 진입하게 된다.

그리고 위와같은 이루어진 ARM 6가지 모드는 공유하는 레지스터도있지만 각자 다른 레지스터를 사용한다.

가장 먼저 IRQ 모드 진입전에 IRQ모드로 진입할 있도록 상태레지스터에 I 의미하는 bit set해준다. 이는 IRQ 모드를 지원한다는 의미이기 때문에 init과정에서 set이필요하다.

 

이후 인터럽트 신호를 받게되면 PC 레지스터에 0x18(IRQ 모드) 진입하기위한 준비를 한다.

그리고 IRQ모드로 진입하게 되는데 위에서언급한 내용과같이 이전 모드와 IRQ모드에서 공유해서사용하는 레지스터의 경우 정보가 날아가지않게 백업이 필요하다.

0x18 주소로 무조건 오는것을 이용하여 해당 주소에서 레지스터 백업 과정과 인터럽트 핸들러 function 으로 jump해주는 코드를 작성한다.

 

인터럽트 핸들러에서는 IRQ번호에맞게 해당 핸들러 function으로 점프해주면된다.

그럼 정상적으로 handler함수가 실행되고 다시 돌아와서 레지스터 백업된 내용을 돌려받고 원래 모드로 돌아가게 된다.

 

2. Linux Interrupt

ARM 기본적인 인터럽트 동작에 대한 내용을 이해하고나면 Linux Kernel Interrupt 구현부분을 주목해볼 있다.

Linux kernel 보면 IRQ 값들은 이미 모두 정의가 되어있다. (Linux Kernel broadcom2835(raspi) 코드를 보면 9번은 USB이고 이런식으로 정의가 되어있음)

그리고 request_irq 통해서 핸들러를 해당 임의의 IRQ 사용자 임의로 연결할 있고 이렇게 연결된 IRQ 인터럽트가 실행되면 사용자가 연결한 function 핸들러함수로 실행된다.

 

만약 안드로이드 등의 OS 마찬가지로 Linux 기반의 OS 만든다면 Linux Kernel Interrupt구문을 참조할 있다.

이렇게 되면 내가 임의의 GPIO 값에 인터럽트 핸들러를 작성한다고 gpio_request 통해서 임의의 GPIO IRQ번호를 획득하고 이렇게 얻은 값을 바탕으로 request_irq 진행하여 핸들러를 등록할 있다.

이렇게 되면 Linux Kernel에서 기본적으로 등록된 IRQ 대해서만 인터럽트를 실행할 있을 것이다.

(우선 이게 맞는지 모르겠음..)

 

3. 직접 만든다면?

만약 내가 Linux Kernel 이용하지않고 직적 핸들러나 IRQ 등록한다면 어떻게 될까?

handler 등록하는 방법은 arm특징을이용하여 0x18(IRQ모드 시작지점) 내가 원하는 logic 추가하여 임의의 핸들러가 동작하게끔 구현할 있다.

하지만 여기서 내가 궁금한 부분은 IRQ 등록부분이다.

 

IRQ 모드로 진입한다는 것은 이미 IRQ번호대로 인터럽트가 정의되어있다는 것이다. 예를들어 GPIO n번핀으로 HIGH신호가 오면 IRQ 2번이다 이런식으로 모두 정의가 되어있는것이고 이후 pulse변화를 감지해서

IRQ 모드로 진입하고 인터러븥 핸들러를 실행하기 떄문이다.

 

결과적으로 내가 직접만든다면 어떻게 IRQ 정의를 진행할 있는지 의문이다. 이를 위해서는 내가 어떤 PIN에서 어떤 Pulse(High, Low, Rising, Falling) 따라 IRQ n번이 동작한다고 정의를 해야하는데 이부분을 어떻게 구현해야하는지 모르겠다.

기본적으로 BCM2835 datasheet 보면 default 정의된 ARM peripheral interrupt 존재하긴하지만 대부분의 interrupt IRQ 번호 GPU IRQ 경우 정의가 되어있지 않은것으로 보여진다. 그럼 어떻게 정의해야하는것일까?..

(이 부분을 계속해서 고민하고 검색하고 있지만 아직 답을 찾지는 못하고 있다..)

+ Recent posts