시험을 위해 정리하는 글이므로 가독성 없고 부연설명 없음 주의
SW 프로그래밍을 다뤄본 사람이라면 예외처리에 대해 배워본 경험이 있을 것이다. C++에서의 try, throw, catch와 같이 말이다.
C++에서 예외를 throw하게 되면, 그 순간 코드의 흐름이 멈추며 스택이 풀리고 catch 블록을 실행하게 된다.
interrupt는 이것의 HW 버전이라고 생각하면 될 것 같다.
HW적으로 어떠한 이벤트가 발생하면 CPU는 main code의 실행을 멈추고 이에 대한 대응을 하게 된다. 이 대응을 interrupt service routine(ISR) 혹은 interrupt handler라고 한다. ISR의 실행이 끝나면 다시 원래의 흐름으로 복귀한다.
CPU에서 이러한 HW적 이벤트를 감지할 수 있는 이유는 hardwired Control Unit을 사용하기 때문이다. 간단히 말하면 하드웨어적으로 control signal을 생성한다고 할 수 있다. 즉, CPU가 직접 peripheral의 memory mapped된 register의 값을 확인하지 않아도 peripheral 쪽에서 CPU쪽으로 신호를 보낸다고 할 수 있을 것이다.
이러한 interrupt 방식은 SW적으로 이벤트를 감지하는 방식인 polling과 비교되는데, polling은 CPU쪽에서 직접 루프를 돌며 register의 값을 확인하는 방식이다. 즉 둘의 방향성이 반대라고 할 수 있다.
이러한 interrupt들은 우리가 priority를 지정할 수 있으며(reset, NMI, hard fault와 같이 priority가 고정되어 있는 exception도 있다) masking할 것인지(ISR을 수행할 것인지)의 여부를 지정할 수도 있다. (NMI, non-maskable interrupt는 masking할 수 없다.)
앞에서 exception이라는 단어를 사용하였는데, 주로 exception이라고 하면 SW적으로 발생하는 synchronous한 exception을 말하며, interrupt는 외부로부터 들어오는, 즉 HW적으로 발생하는 asynchronous한 exception을 의미한다.
또한 이러한 interrupt는 곧바로 CPU로 가는 것이 아니라 NVIC(Nested Vectored Interrupt Controller)를 통해 CPU로 전달된다. CPU는 한 번에 한 개의 interrupt만 처리할 수 있기 때문에 Interrupt Controller에서 Interrupt들의 priority를 고려하여 CPU로 전달해 줄 필요가 있는 것이다.
Nested는 무엇을 의미하냐고 하면, CPU가 어떠한 handler를 수행하던 도중, 더 priority가 높은 IRQ(Interrupt request)가 들어오게 되면 아직 다른 handler를 수행중이었어도 priority가 더 높은 interrupt의 handler를 call한다는 것이다. 물론 handler의 수행이 끝나면 원래 수행중이었던 위치로 다시 복귀한다. SW적으로 비유하면, function을 수행 중에 다른 function이 call된 상황이라고 볼 수 있겠다.
Vectored는 Vector table을 사용하기 때문에 붙은 것이다. Vector table은 interrupt handler의 시작위치를 가리키는 포인터의 table이라고 보면 될 것 같다.
한마디로, Reset vector가 0x00000004에 위치해 있다면, 이 메모리 주소에는 reset에 대한 hanler의 주소가 저장되어 있다고 할 수 있다.(다른 말로 하자면, 0x00000004는 reset handler를 가리키는 포인터의 위치이다.)
참고로 ARM Cortex-M의 경우 메모리 주소 0x00000004부터 vector table이 있고, 0번지는 Main Stack Pointer(MSP)의 initial value가 존재한다. 따라서 reset을 할 시에 이 값을 fetch해와 stack을 초기화한다.
reset시 수행되는 루틴은 다음과 같다. 먼저 MSP의 값을 fetch해와 SP를 저장하는 R13 register에 저장한다. (SP 초기화)
그리고 reset vector를 PC에 fetch해서 reset handler로 branch한다.(boot code, startup code를 실행한 뒤 main code를 실행하게 된다.)
'EE > 임베디드 시스템' 카테고리의 다른 글
[임베디드] GPIO OTYPER, Push-Pull, Open Drain (0) | 2023.04.06 |
---|---|
[임베디드] EXTI, External Interrupts (0) | 2023.04.06 |
[임베디드] SysTick, System timer (0) | 2023.04.06 |