Interrupt vs Polling

moonsyu·2026년 9월 1일

stm32

목록 보기
5/9
post-thumbnail

1. 인터럽트의 개념

  • CPU가 현재 실행 중인 코드를 잠시 멈추고, 긴급하게 처리해야 하는 이벤트의 전용 함수로 이동하는 메커니즘

이 전용 함수를 ISR(Interrupt Service Routine) 또는 Interrupt Handler라고 한다.

Interrupt 처리 순서

  1. GPIO, 타이머, UART와 같은 주변장치에서 이벤트 발생
  2. 주변장치가 인터럽트 요청 발생
  3. CPU는 현재 실행 위치와 일부 상태 저장
  4. 인터럽트 벡터 테이블을 통해 해당 ISR로 이동
  5. ISR이 필요한 최소 작업 수행
  6. 저장한 상태 복원 후 중단했던 코드부터 이어서 실행

즉, 인터럽트는 프로그램의 실행 흐름과 독립된 시점에 발생하기 때문에 비동기 이벤트라고 한다.


2. 인터럽트의 특징

빠른 이벤트 대응

  • CPU가 주변장치를 계속 확인하지 않아도 이벤트가 발생하는 즉시 처리가 가능
  • 실제 응답 시간은 MCU의 현재 상태, 인터럽트 우선순위, 비활성화 구간 등에 따라 달라짐

CPU 사용 효율 향상

  • 이벤트가 없을 때 CPU는 다른 작업을 수행하거나 저전력 모드에 들어갈 수 있음
  • 드물게 발생하는 이벤트를 처리할수록 효과가 큼

우선순위 설정

  • 대부분의 MCU는 인터럽트 우선순위 지원
  • STM32의 NVIC(Nested Vectored Interrupt Controller)는 더 높은 우선순위의 인터럽트가 낮은 우선순위의 ISR을 선점하도록 설정 가능

동시성 문제

  • ISR과 메인 코드가 같은 변수를 사용할 경우 실행 순서 주의 필요
  • 컴파일러 최적화로 값이 누락되지 않도록 여러 바이트 데이터나 복합 연산에는 임계 구역 또는 원자적 접근이 필요하다.

ISR은 짧아야 한다

  • 플래그 설정이나 데이터 복사만 하고, 실제 처리는 메인 루프나 RTOS 태스크에 넘긴다.

    긴 연산, HAL_Delay(), 블로킹 통신, 과도한 로그 출력 등을 수행하면 다른 인터럽트와 메인 작업이 지연되기 때문


3. 임베디드 시스템에서의 인터럽트

임베디드 시스템에서는 외부 신호와 내부 주변장치 이벤트를 처리하기 위해 인터럽트를 폭넓게 사용한다.

대표적인 예시는 다음과 같다.

인터럽트 소스활용 예시
GPIO/EXTI버튼 입력, 센서의 데이터 준비 신호
Timer주기 작업, 시간 측정, PWM 주기 완료
UART/SPI/I2C데이터 수신·송신 완료
ADC/DMA변환 완료, 버퍼 절반 또는 전체 전송 완료
RTC알람 또는 주기적 깨우기
SysTick시스템 시간 기준 또는 RTOS 스케줄링

설계 시 고려사항

  • 배터리 기반 장치: CPU가 저전력 모드에서 대기하고 인터럽트가 발생할 때만 깨어나도록 설계하면 전력 효율을 높일 수 있다.
  • 모터 제어 시스템: 실시간 응답이 중요하므로 인터럽트 지연 시간과 최악 실행 시간(WCET)을 예측하고 관리해야 한다.

4. 일반적인 인터럽트와 임베디드 인터럽트의 차이

기본 원리는 같다. 이벤트가 발생하면 현재 흐름을 중단하고 지정된 처리 루틴을 실행한다.

차이는 주로 환경에 있다.

구분범용 컴퓨터임베디드 시스템
관리 주체운영체제와 드라이버가 주로 관리펌웨어가 직접 설정하는 경우가 많음
주요 목적장치, 시스템 호출, 스케줄링 처리핀, 타이머, 통신 등 하드웨어 이벤트 처리
제약 조건비교적 풍부한 자원제한된 메모리, 전력, 처리 성능
중요 지표처리량과 시스템 안정성응답 시간, 결정성, 전력 효율
설정 방식OS API와 드라이버 중심레지스터, NVIC, CubeMX/HAL 중심

따라서 “임베디드 전용의 완전히 다른 인터럽트”가 존재하는 것은 아니다. 같은 개념을 더 하드웨어 중심적이고 시간 제약이 큰 환경에서 사용하는 것이다.


5. 임베디드 시스템에서의 인터럽트 사용법

아래는 STM32CubeMX와 HAL을 사용해 PA0에 연결된 버튼의 Falling Edge(클릭)를 감지하는 예시다. 버튼은 PA0와 GND 사이에 연결하고 내부 Pull-up을 사용하는 상황을 가정한다. 실제 핀과 인터럽트 이름은 MCU 및 보드에 맞게 변경해야 한다.

5.1 하드웨어 구성

  • 버튼 한쪽: PA0
  • 버튼 다른 쪽: GND
  • PA0 내부 Pull-up 활성화
  • 버튼을 누르면 입력이 HIGH에서 LOW로 변하므로 Falling Edge(클릭) 감지

스위치에는 바운스가 발생할 수 있으므로 실제 제품에서는 RC 필터, 슈미트 트리거 또는 소프트웨어 디바운싱을 고려해야 한다.

5.2 STM32CubeMX 설정

  1. Pinout & Configuration에서 PA0를 GPIO_EXTI0로 설정
  2. GPIO mode를 External Interrupt Mode with Falling edge trigger detection으로 선택
  3. Pull-up/Pull-down을 Pull-up으로 설정
  4. NVIC Settings에서 EXTI line0 interrupt를 활성화
  5. 필요한 경우 Preemption Priority와 Sub Priority를 지정
  6. 코드를 생성한 뒤 인터럽트 핸들러와 HAL 콜백 구현

5.3 STM32 HAL 예제 코드

void EXTI0_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}

애플리케이션에서는 HAL 콜백에서 플래그만 설정하고, 실제 작업은 메인 루프에서 처리한다.

#include <stdbool.h>

volatile bool button_event = false;

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == GPIO_PIN_0)
    {
        button_event = true;
    }
}

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();

    while (1)
    {
        if (button_event)
        {
            button_event = false;

            // 시간이 오래 걸릴 수 있는 실제 작업은 여기에서 수행
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);  // NUCLEO-F446RE LD2
        }

        // 다른 작업 수행 또는 저전력 모드 진입
    }
}

5.4 구현 시 주의사항

  • ISR 안에서 HAL_Delay()나 긴 반복문을 사용하지 않는다.
  • 공유 데이터의 원자성과 경쟁 조건을 확인한다.
  • 인터럽트 플래그를 올바르게 해제한다.
  • 우선순위를 무조건 높게 설정하지 않는다.
  • 버튼 바운스와 노이즈를 고려한다.
  • 빠른 이벤트가 반복된다면 단순 bool 플래그 대신 카운터나 링 버퍼를 사용한다.
  • ISR 실행 시간과 인터럽트 발생 주기가 겹치지 않는지 측정한다.

6. Polling의 개념

  • CPU가 주변장치나 입력 핀의 상태를 반복해서 읽어 이벤트 발생 여부를 확인하는 방식
  • 실시간으로 입력을 놓치면 안될 때 사용
// 버튼 상태 Polling 예시
while (1)
{
    if (HAL_GPIO_ReadPin(BUTTON_GPIO_Port, BUTTON_Pin) == GPIO_PIN_RESET)
    {
        HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);

        // 간단한 디바운싱 예시
        HAL_Delay(20);
    }
}

7. Polling의 특징

구현과 디버깅의 단순함

  • 코드가 순차적으로 실행되므로 흐름을 이해하기 쉽다.
  • 작은 프로그램이나 초기 동작 검증에 유리하다.

검사 주기에 따라 응답 시간이 결정됨

  • 10ms마다 상태를 확인한다면 이벤트 응답은 최악의 경우 약 10ms 이상 늦어질 수 있다.
  • 다른 블로킹 작업이 있으면 지연은 더 커진다.

CPU 시간을 지속적으로 사용함

  • 이벤트가 없어도 지속적으로 CPU 사용
  • 검사 사이에 대기 시간을 두면 부하는 줄지만 응답성이 낮아짐

짧은 이벤트를 놓칠 수 있음

  • 입력 펄스가 Polling 주기보다 짧으면 감지하지 못할 수 있다.
  • 짧은 이벤트의 경우 인터럽트, 입력 캡처 또는 하드웨어 래치를 사용하는 편이 안전하다.

실행 흐름을 예측하기 쉬움

  • 공유 데이터와 경쟁 조건이 단순해진다.
    - 인터럽트에 의한 비동기 실행이 적기 때문
  • 매우 짧고 고정된 주기의 메인 루프에서는 Polling이 오히려 충분히 결정적인 선택일 수 있다.

8. 인터럽트와 Polling의 차이점

비교 항목InterruptPolling
이벤트 감지하드웨어가 CPU에 알림CPU가 상태를 반복 확인
응답 속도일반적으로 빠름검사 주기에 좌우됨
CPU 효율이벤트가 없을 때 효율적지속 검사 시 비효율적
구현 난이도우선순위와 동시성 고려 필요비교적 단순함
이벤트 누락적절히 설정하면 짧은 이벤트 감지 가능검사 주기보다 짧으면 누락 가능
전력 소비저전력 모드와 결합하기 좋음Busy Polling은 전력 소비가 큼
디버깅실행 순서가 비동기적이라 복잡할 수 있음순차적이어서 비교적 쉬움
적합한 상황비동기·긴급·저빈도 이벤트단순 상태 확인, 매우 짧은 고정 주기 루프

※ 참고 사항

  • 인터럽트가 항상 더 좋은 것은 아니다.
  • 이벤트가 매우 자주 발생하면 ISR 진입과 복귀 비용이 오히려 커질 수 있다.
  • 반대로 버튼 입력처럼 드물고 비동기적인 이벤트나 짧은 펄스는 인터럽트가 적합하다.
  • 실제 시스템에서는 두 방식을 함께 사용하는 경우가 많다.
  • 인터럽트로 이벤트를 빠르게 감지해 플래그나 버퍼에 기록하고, 메인 루프나 태스크가 Polling 방식으로 그 플래그를 확인해 무거운 작업을 처리하는 구조다.

0개의 댓글