인터럽트란 사전전 의미 그대로 방해하는 행위를 말한다.
즉, MCU가 일을 계속 하고 있는 도중 어떤 이벤트가 발생해서 MCU에게 잠시 실행을 중지하고 이것부터 우선적으로 처리하도록 하는 방식이 인터럽트이다.
이 인터럽트에는 ARM에서 정해놓은 중요 인터럽트 이외에도 사용자가 직접 정의해서 사용할 수 있는 인터럽트도 있다.
Hello World나 Entry Point등의 이전 장들에서도 언급을 했었는데 이번장에서 자세히 알아보도록 하자.
이전 장들 특히 Entry Point에서 언급한 Interrupt Vector Table등의 내용들과 병행해서 보는게 이해가 빠를 수 있다.
|
1. MCU의 Interrupt 처리
인터럽트는
- 외부장치에서의 인터럽트 요청
- 내부 S/W오류에 의한 인터럽트
- MCU자체의 이상동작에 의한 인터럽트
등의 사유로 발생되며 이때의 요청을 IRQ(Interrupt Request)라 한다.
인터럽트 요청이 들어오면 즉 IRQ가 발생하면 인터럽트 컨트롤러라고 하는 장치가 MCU에게 통지한다. ARM Cortex-M4의 경우 이 컨트롤러를 NVIC(Nested Vectored Interrupt Controller)라고 하는 컨트롤러가 담당하고 있다.
일단 인터럽트 컨트롤러에 의해 인터럽트가 MCU에 통지되면 MCU는 현재 작업중인 명령까지만 완료하고 인터럽트를 수행하게 된다.
이때 MCU는 요청된 IRQ 번호에 따라 메모리의 인터럽트 벡터 테이블에서 해당 IRQ번호에 해당하는 주소값을 읽는다.
이 주소값은 해당 인터럽트에 대한 처리를 담당하는 ISR(Interrupt Service Routine)의 주소값이며 이 주소값에 있는 내용을 실행하게 된다.
이런 인터럽트 처리방식은 약간의 차이가 있을 수 있지만 우리가 사용하는 PC도 마찬가지이다. 다음은 윈도우의 랜카드에 대한 장치관리자 상세 화면인데 랜카드도 CPU입장에서 Peripheral이며 이 장치에 대한 고유 IRQ번호를 가지고 있는게 보인다. 랜카드는 이 IRQ번호를 통해 CPU에 인터럽트 요청을 수행한다.
2. ARM Cortex-M4의 인터럽트 방식
ARM Cortex-M4에는 NVIC(Nested Vectored Interrupt Controller)라는 인터럽트 컨트롤러를 내장하고 있다.
NVIC는 우리말로 하면 중첩 벡터 인터럽트 컨트롤러인데 쉽게 설명하면 어떤 인터럽트가 발생해서 해당 ISR을 실행하고 있는 도중 그 인터럽트 보다 우선순위가 높은 인터럽트가 발생할 경우 해당 ISR의 실행을 잠시 중단하고 우선순위 높은 인터럽트를 먼저 처리하고 원래 인터럽트의 나머지를 처리하는 방식이다.
일부 다른 MCU의 경우 인터럽트 하나가 실행중일 때 다른 인터럽트가 발생하는 경우, 이를 처리하지 못하는 경우가 발생하는데 NVIC는 이런 상황에서도 인터럽트 요청을 놓치지 않는다.
위의 그림을 보면 먼저 main()실행중에 첫번째 인터럽트가 발생하면 해당 인터럽트의 ISR1이 실행된다. ISR1이 실행중인 도중 다시 첫번째 인터럽트보다 우선순위가 높은 인터럽트 요청이 발생했을 때 ISR1실행을 잠시 중단하고 ISR2를 먼저 처리한 뒤 나머지 ISR1을 처리한다. (이때 ISR1에서 ISR2로 Context Switching이 발생할 때 ISR1의 현재상태는 Stack에 Push되고 ISR2가 완료되는 시점에서 Pop된다.)
그리고 ISR1 처리가 완료되면 다시 원래 main()으로 돌아온다.
NVIC의 특징을 보면
- 최대 91개 마스크 가능한 인터럽트 채널(FPU가 있는 Cortex-M4의 16개 인터럽트 라인 제외)
- 16개의 프로그램 가능 우선 순위 레벨(4비트 인터럽트 우선순위 사용)
- 낮은 대기 시간 예외 및 인터럽트 핸들링
- 전원 관리 제어
- 시스템 제어 레지스터 구현
등의 특징을 가지고 있는데 하나씩 살펴보자.
마스크 가능한 인터럽트 (Maskable Interrupt)
먼저 마스크 가능한 인터럽트라는건 해당 IRQ번호에 대해 S/W적으로 인터럽트가 발생하게도 발생하지 않게도 할 수 있는 인터럽트를 말한다.
STM32F4xx의 91개 인터럽트는 레퍼런스 매뉴얼 378p부터 나와 있다.
앞부분 회색으로 칠해진 부분은 NMI(Non-maskable interrupt)이므로 사용자가 임의로 마스크 처리를 할 수 없는 내부 인터럽트이다. NMI는 인터럽트 처리를 무시할 수 없는 중요한 인터럽트로 다른 인터럽트보다 우선순위가 높다. 그외 외부에서 들어오는 인터럽트 신호는 EXTI Controller라는 외부 인터럽트 처리 컨트롤러에 의해 제어되고 NVIC쪽으로 처리를 넘긴다.
외부 인터럽트 처리는 다음 그림과 같이 진행된다.
여기서 EXTI Controller는 다시 그림과 같이 구성된다.
위 그림과 같이 STM32F4xx의 EXTI Controller는 각각 23개씩의 인터럽트 라인으로 구분된다. 그래서 EXTI는 0~22까지의 번호를 가지는데 GPIO핀과의 관계를 보면 다음과 같이 설명이 되어 있다.
그림을 보면 0번 핀(PA0, PB0, PC0...)은 EXTI0, 1번 핀(PA1, PB1, PC1...)은 EXTI1로 묶여있는걸 볼 수 있다.
즉 핀번호가 동일하다면 같은 EXTI번호를 사용한다는 말이다.
그리고 그림에 나오지는 않지만 EXTI5~EXTI9까지는 EXTI9_5에, EXTI10~EXTI15까지는 EXTI15_10에 하나로 묶여 있다.
이 EXTI번호가 NVIC쪽으로 전달되고 NVIC는 중첩 벡터 방식에 의해 IRC를 실행하게 된다.
인터럽트의 우선순위 설정
각 EXTI는 CubeMX의 NVIC설정에서 우선순위를 지정할 수 있다. 여기에 설정된 값의 숫자가 낮을 수록 우선순위가 높아진다.
위의 두 그림과 같이 GPIO에서 PC13, PE3, PF7을 인터럽트 입력으로 설정하고 NVIC설정을 보면 PC13은 EXTI line[15:10], PE3은 EXTI line3, PF7은 EXTI line[9:5]로 선언된 걸 볼 수 있다. (위에 설명한 바와 같이 EXTI5~9는 EXTI9_5로 묶이고 EXTI10~15는 EXTI15_10 하나로 묶이기 때문에 PE3을 제외하고는 묶인 EXTI를 사용하고 있다.)
그리고 NVIC에서 오른쪽을 보면 Preemption Priority가 있는데 이 부분이 우선순위를 지정하는 칸이다.
그 옆에 Sub Priority도 있는데 이 우선순위는 동일한 Preemption Priority를 가지는 각각의 인터럽트가 동시에 발생한 경우 어느 인터럽트를 우선할 것이냐를 결정하는 우선순위이다.
이 우선순위는 NVIC화면의 상단에 있는 Priority Group의 선택에 따라 Preemption/Sub Priority에 각각 몇bit를 할당할지가 결정되고 선택된 Group은 SCB_AIRCR 레지스터의 [10:8] 비트에 설정된다.
예를들어 위의 콤보박스에서 "3 bits for pre-emption priority 1 bits for subprioriy"를 선택했다면 Preemption Priority는 0~7의 우선순위, Sub Priority는 0~1의 우선순위를 선택할 수 있다.
Low Latency 인터럽트 처리
통상 인터럽트가 발생하고 ISR을 실행하기까지는 수십 사이클이 소요된다.
이를 인터럽트 지연시간이라고 하는데 ARM Cortex-M4의 NVIC는 12사이클의 Latency를 가진다. 이는 다른 MCU보다 2배정도 빠른 시간이라고 한다.
전원관리 제어
다른 장에서 보겠지만 ARM Cortex-M4는 전력소모를 줄이기 위해 저전력 모드로 들어갈 수 있다. 여기에는 Sleep Mode, Stop Mode, Standby Mode가 있는데 저전력 모드에 들어간 후 특정 인터럽트나 이벤트로 깨어날 수 있다.
시스템 제어 레지스터
모든 인터럽트의 설정 및 제어는 다른 Peripheral과 마찬가지로 레지스터로 제어가 가능하다.
다음 시간에 CubeMX가 만든 소스를 통해 레지스터에 대해 살펴볼 것이다.
3. Event
EXTI는 외부 Interrupt뿐 아니라 Event도 처리한다. EXTI는 실제 External interrupt/event controller의 약자다.
위의 그림중 [EXTI Controller Block Diagram] 이미지에서 하단부분이 Event에 관련된 다이어그램인데 인터럽트의 경우 Pending request register를 통해 NVIC쪽으로 신호가 들어간 뒤 NVIC에서 우선순위를 따져 해당 ISR을 실행하지만 Event의 경우 왼쪽 하단과 같이 별도 처리 없이 Pulse generator에 의해 하나의 펄스만 발생시킨다.
이 펄스는 아래 그림과 같이 저전력 모드에서 깨어나는 신호로, 또는 EVG(Event Generator)에 의해 발생한 펄스가 Process Core로 전달 된다.
Event 설정은 해당 핀을 먼저 GPIO_EXTIxx 로 설정한 뒤 GPIO화면에서 아래와 같이 GPIO mode를 변경해 설정할 수 있다.
Event로 설정할 경우 이 핀은 더이상 인터럽트로 동작하지 않으므로 NVIC화면에는 해당 인터럽트가 표시되지 않는다.
'임베디드 > STM32' 카테고리의 다른 글
14. [STM32] Interrupt 구현하기 (0) | 2024.10.10 |
---|---|
13. [STM32] Interrupt-Register (0) | 2024.09.26 |
11. [STM32] SWV/ITM 을 사용한 디버깅 (0) | 2024.09.23 |
10. [STM32] GPIO예제(feat. Open Drain) (0) | 2024.09.23 |
9. [STM32] Bit-banding (0) | 2024.09.10 |