지노랩 /JinoLab

FreeRTOS 인터럽트 우선순위 설정 제대로 이해하기 본문

임베디드 시스템/RTOS

FreeRTOS 인터럽트 우선순위 설정 제대로 이해하기

지노랩/JinoLab 2025. 6. 27. 09:08

**configMAX_SYSCALL_INTERRUPT_PRIORITY(또는 configMAX_API_CALL_INTERRUPT_PRIORITY)**가 도대체 무슨 의미인지 헷갈리셨다면, 이 글로 한 방에 정리해 보세요!


1. 왜 또 다른 우선순위 매크로가 있을까?

FreeRTOS 커널은 SysTick / PendSV / SVC 같은 ‘커널 전용 인터럽트’를 가장 낮은 우선순위(예: 0xF0)로 고정해 둡니다.
그러나 사용자 인터럽트(UART, ADC, TIM 등)는 상황에 따라 RTOS API를 호출해야 할 때가 있고, 또 어떤 ISR은 완전 실시간(순수 Bare-metal) 로 동작해야 하기도 합니다.

그래서 “API를 부를 수 있는 ISR”와 “절대 부르면 안 되는 ISR” 간 경계값이 필요합니다.
이 값이 바로 configMAX_SYSCALL_INTERRUPT_PRIORITY 입니다.


2. 매크로가 가리키는 ‘경계선’

구분 우선순위 값(숫자) 의미

0x00 ~ configMAX_SYSCALL_INTERRUPT_PRIORITY-1 가장 높은 우선RTOS 임계구역보다 우선 실행 → RTOS API 호출 금지  
configMAX_SYSCALL_INTERRUPT_PRIORITY ~ 0xF0 커널보다만 높으면 OK → …FromISR() 계열 API 호출 가능  
0xF0 (커널) SysTick, PendSV, SVC  

즉, 이 숫자보다 “같거나 큰 값(=우선도가 낮은 인터럽트)” 에서만 xQueueSendFromISR(), xTaskNotifyFromISR() 같은 API를 안전하게 부를 수 있습니다.


3. STM32F4 예시로 계산해 보기

  1. CMSIS 확인
  2. #define __NVIC_PRIO_BITS 4 // 4비트 우선순위 → 16단계(0~15)
  3. 커널 우선순위
  4. #define configKERNEL_INTERRUPT_PRIORITY (15 << (8-4)) // 0xF0
  5. SYSCALL 한계값 설정 (보통 5~10 정도 채택)
  6. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 10 #define configMAX_SYSCALL_INTERRUPT_PRIORITY (10 << (8-4)) // 0xA0
  7. 결과
    • API 사용 ISR : 우선순위 10(0xA0) ~ 15(0xF0)
    • 초고속 ISR : 우선순위 0 ~ 9 (RTOS 호출 금지)

4. 실수 방지 체크리스트 ✅

  1. ISR 안에서 xXXXFromISR() 호출 시 NVIC_SetPriority() 값이 0xA0 이상인지 확인.
  2. PendSV / SysTick 우선순위는 절대 바꾸지 않는다.
  3. 라이브러리 기본값(=0) 그대로 두고 API를 부르면 HardFault 날 확률 100%!

5. 한 줄 요약

“RTOS API를 쓰는 인터럽트는 configMAX_SYSCALL_INTERRUPT_PRIORITY(예: 0xA0)보다 숫자가 크거나 같은 우선순위로 설정하라.”

이 원칙만 기억하면 우선순위 충돌로 인한 데드락·HardFault 걱정 끝!
안전하고 깔끔한 FreeRTOS 프로젝트에 꼭 적용해 보세요. 🚀