본문 바로가기

MCU

Vector table

STM32 제품군별 벡터 테이블 차이

벡터 테이블은 인터럽트와 예외 핸들러의 주소를 저장하는 메모리 구조로, ARM Cortex-M 코어의 NVIC(Nested Vectored Interrupt Controller)에 의해 사용됩니다. STM32 제품군별 차이는 코어 아키텍처와 메모리 구성에 따라 발생합니다.

 

VTOR(Vector Table Offset Register) 지원 여부

  • STM32F0 (Cortex-M0):
    • 특징: Cortex-M0 코어는 VTOR 레지스터를 지원하지 않음. 벡터 테이블은 기본적으로 플래시 메모리(0x00000000)에 고정되거나, RAM으로 복사하여 사용해야 함
    • 제약: 동적 재배치가 불가능하며, 링커 스크립트와 메모리 매핑으로 관리
  • STM32F1, F4, H7 (Cortex-M3, M4, M7):
    • 특징: VTOR 레지스터를 지원하여 벡터 테이블을 플래시, RAM, 또는 기타 메모리 영역으로 재배치 가능
    • 장점: 부트로더와 사용자 애플리케이션 간 전환 시 유연한 설정 가능

벡터 테이블 크기 및 인터럽트 수

  • STM32F0:
    • Cortex-M0는 기능이 줄어들며 벡터 테이블 엔트리 수도 감소
    • 최대 32개의 인터럽트를 지원하며, 벡터 테이블은 초기 스택 포인터(MSP)와 최대 32개의 IRQ 핸들러로 구성
    • 벡터 테이블 크기: 약 136바이트 (4바이트 * (1 + 32 + 예외))
  • STM32G0 / C0 (Cortex‑M0+ 계열)
    • Cortex-M3 기반, 최대 60개의 인터럽트를 지원
  • STM32F1:
    • Cortex-M3 기반으로 기본 16 exception + 최대 60~80 IRQ 엔트리를 지원
  • STM32F4:
    • Cortex-M4 기반, 최대 82개의 인터럽트를 지원
  • STM32H7:
    • Cortex-M7 기반, 최대 150개의 인터럽트를 지원하며, 더 복잡한 인터럽트 우선순위 관리 가능

메모리 정렬 요구사항

  • Cortex-M0 (STM32F0):
    • 벡터 테이블은 4바이트(32비트) 정렬이 필수. 정렬되지 않은 주소 접근은 HardFault 발생
    • 플래시 메모리(0x00000000) 또는 RAM의 정렬된 주소에 배치
  • Cortex-M3/M4/M7 (STM32F1, F4, H7):
    • VTOR은 7비트 정렬(128바이트)을 요구하며, 상위 비트는 무시됨
    • 정렬되지 않은 접근은 일부 허용되지만, 성능을 위해 정렬 권장

부트로더와 벡터 테이블 재배치

  • STM32F0:
    • VTOR 미지원으로, 부트로더에서 사용자 코드로 전환 시 RAM에 벡터 테이블을 복사하거나 플래시 메모리 매핑 사용
  • STM32F1, F4, H7:
    • VTOR을 통해 부트로더와 사용자 애플리케이션의 벡터 테이블을 동적으로 변경 가능
    • 예: 플래시 메모리의 사용자 코드 시작 주소(예: 0x08010000)로 VTOR 설정

차이의 이유

  • 코어 아키텍처:
    • Cortex-M0/M0+는 저비용, 저전력 설계를 목표로 VTOR과 같은 고급 기능을 생략
    • Cortex-M3/M4/M7은 고성능 응용을 위해 더 많은 인터럽트와 유연한 메모리 관리를 지원
  • STM32 설계 목표:
    • STM32F0는 소형, 저전력 응용(예: 센서, 간단한 제어)에 최적화되어 간소화된 인터럽트 구조를 가짐
    • STM32F4/H7은 고성능 응용(예: GUI, 모터 제어, 네트워킹)에 적합하며, 더 많은 인터럽트와 복잡한 NVIC 설정 지원
  • 메모리 제약:
    • STM32F0는 플래시(8~256KB)와 RAM(4~32KB)이 제한적이므로, 벡터 테이블 재배치가 제한됨
    • STM32F4/H7은 큰 플래시(최대 2MB)와 RAM(최대 1MB)을 제공하여 유연한 설정 가능

 

 

/******************************************************************************
*
* The minimal vector table for a Cortex M3. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
* 
*******************************************************************************/
   .section  .isr_vector,"a",%progbits
  .type  g_pfnVectors, %object
   
   
g_pfnVectors:
  .word  _estack
  .word  Reset_Handler

  .word  NMI_Handler
  .word  HardFault_Handler
  .word  MemManage_Handler
  .word  BusFault_Handler
  .word  UsageFault_Handler
  .word  0
  .word  0
  .word  0
  .word  0
  .word  SVC_Handler
  .word  DebugMon_Handler
  .word  0
  .word  PendSV_Handler
  .word  SysTick_Handler
  
  /* External Interrupts */
  .word     WWDG_IRQHandler                   /* Window WatchDog              */                                        
  .word     PVD_IRQHandler                    /* PVD through EXTI Line detection */                        
  .word     TAMP_STAMP_IRQHandler             /* Tamper and TimeStamps through the EXTI line */            
  .word     RTC_WKUP_IRQHandler               /* RTC Wakeup through the EXTI line */                      
  .word     FLASH_IRQHandler                  /* FLASH                        */                                          
  .word     RCC_IRQHandler                    /* RCC                          */                                            
  .word     EXTI0_IRQHandler                  /* EXTI Line0                   */                        
  .word     EXTI1_IRQHandler                  /* EXTI Line1                   */                          
  .word     EXTI2_IRQHandler                  /* EXTI Line2                   */                          
  .word     EXTI3_IRQHandler                  /* EXTI Line3                   */                          
  .word     EXTI4_IRQHandler                  /* EXTI Line4                   */                          
  .word     DMA1_Stream0_IRQHandler           /* DMA1 Stream 0                */                  
  .word     DMA1_Stream1_IRQHandler           /* DMA1 Stream 1                */                   
  .word     DMA1_Stream2_IRQHandler           /* DMA1 Stream 2                */                   
  .word     DMA1_Stream3_IRQHandler           /* DMA1 Stream 3                */                   
  .word     DMA1_Stream4_IRQHandler           /* DMA1 Stream 4                */                   
  .word     DMA1_Stream5_IRQHandler           /* DMA1 Stream 5                */                   
  .word     DMA1_Stream6_IRQHandler           /* DMA1 Stream 6                */                   
  .word     ADC_IRQHandler                    /* ADC1, ADC2 and ADC3s         */                   
  .word     CAN1_TX_IRQHandler                /* CAN1 TX                      */                         
  .word     CAN1_RX0_IRQHandler               /* CAN1 RX0                     */                          
  .word     CAN1_RX1_IRQHandler               /* CAN1 RX1                     */                          
  .word     CAN1_SCE_IRQHandler               /* CAN1 SCE                     */                          
  .word     EXTI9_5_IRQHandler                /* External Line[9:5]s          */                          
  .word     TIM1_BRK_TIM9_IRQHandler          /* TIM1 Break and TIM9          */         
  .word     TIM1_UP_TIM10_IRQHandler          /* TIM1 Update and TIM10        */         
  .word     TIM1_TRG_COM_TIM11_IRQHandler     /* TIM1 Trigger and Commutation and TIM11 */
  .word     TIM1_CC_IRQHandler                /* TIM1 Capture Compare         */                          
  .word     TIM2_IRQHandler                   /* TIM2                         */                   
  .word     TIM3_IRQHandler                   /* TIM3                         */                   
  .word     TIM4_IRQHandler                   /* TIM4                         */                   
  .word     I2C1_EV_IRQHandler                /* I2C1 Event                   */                          
  .word     I2C1_ER_IRQHandler                /* I2C1 Error                   */                          
  .word     I2C2_EV_IRQHandler                /* I2C2 Event                   */                          
  .word     I2C2_ER_IRQHandler                /* I2C2 Error                   */                            
  .word     SPI1_IRQHandler                   /* SPI1                         */                   
  .word     SPI2_IRQHandler                   /* SPI2                         */                   
  .word     USART1_IRQHandler                 /* USART1                       */                   
  .word     USART2_IRQHandler                 /* USART2                       */                   
  .word     USART3_IRQHandler                 /* USART3                       */                   
  .word     EXTI15_10_IRQHandler              /* External Line[15:10]s        */                          
  .word     RTC_Alarm_IRQHandler              /* RTC Alarm (A and B) through EXTI Line */                 
  .word     OTG_FS_WKUP_IRQHandler            /* USB OTG FS Wakeup through EXTI line */                       
  .word     TIM8_BRK_TIM12_IRQHandler         /* TIM8 Break and TIM12         */         
  .word     TIM8_UP_TIM13_IRQHandler          /* TIM8 Update and TIM13        */         
  .word     TIM8_TRG_COM_TIM14_IRQHandler     /* TIM8 Trigger and Commutation and TIM14 */
  .word     TIM8_CC_IRQHandler                /* TIM8 Capture Compare         */                          
  .word     DMA1_Stream7_IRQHandler           /* DMA1 Stream7                 */                          
  .word     FMC_IRQHandler                    /* FMC                          */                   
  .word     SDIO_IRQHandler                   /* SDIO                         */                   
  .word     TIM5_IRQHandler                   /* TIM5                         */                   
  .word     SPI3_IRQHandler                   /* SPI3                         */                   
  .word     UART4_IRQHandler                  /* UART4                        */                   
  .word     UART5_IRQHandler                  /* UART5                        */                   
  .word     TIM6_DAC_IRQHandler               /* TIM6 and DAC1&2 underrun errors */                   
  .word     TIM7_IRQHandler                   /* TIM7                         */
  .word     DMA2_Stream0_IRQHandler           /* DMA2 Stream 0                */                   
  .word     DMA2_Stream1_IRQHandler           /* DMA2 Stream 1                */                   
  .word     DMA2_Stream2_IRQHandler           /* DMA2 Stream 2                */                   
  .word     DMA2_Stream3_IRQHandler           /* DMA2 Stream 3                */                   
  .word     DMA2_Stream4_IRQHandler           /* DMA2 Stream 4                */                   
  .word     0                                 /* Reserved                     */                   
  .word     0                                 /* Reserved                     */                     
  .word     CAN2_TX_IRQHandler                /* CAN2 TX                      */                          
  .word     CAN2_RX0_IRQHandler               /* CAN2 RX0                     */                          
  .word     CAN2_RX1_IRQHandler               /* CAN2 RX1                     */                          
  .word     CAN2_SCE_IRQHandler               /* CAN2 SCE                     */                          
  .word     OTG_FS_IRQHandler                 /* USB OTG FS                   */                   
  .word     DMA2_Stream5_IRQHandler           /* DMA2 Stream 5                */                   
  .word     DMA2_Stream6_IRQHandler           /* DMA2 Stream 6                */                   
  .word     DMA2_Stream7_IRQHandler           /* DMA2 Stream 7                */                   
  .word     USART6_IRQHandler                 /* USART6                       */                    
  .word     I2C3_EV_IRQHandler                /* I2C3 event                   */                          
  .word     I2C3_ER_IRQHandler                /* I2C3 error                   */                          
  .word     OTG_HS_EP1_OUT_IRQHandler         /* USB OTG HS End Point 1 Out   */                   
  .word     OTG_HS_EP1_IN_IRQHandler          /* USB OTG HS End Point 1 In    */                   
  .word     OTG_HS_WKUP_IRQHandler            /* USB OTG HS Wakeup through EXTI */                         
  .word     OTG_HS_IRQHandler                 /* USB OTG HS                   */                   
  .word     DCMI_IRQHandler                   /* DCMI                         */                   
  .word     0                                 /* Reserved                     */                   
  .word     0                                 /* Reserved                     */
  .word     FPU_IRQHandler                    /* FPU                          */
  .word     0                                 /* Reserved                     */
  .word     0                                 /* Reserved                     */
  .word     SPI4_IRQHandler                   /* SPI4                         */
  .word     0                                 /* Reserved                     */
  .word     0                                 /* Reserved                     */
  .word     SAI1_IRQHandler                   /* SAI1                         */
  .word     0                                 /* Reserved                     */
  .word     0                                 /* Reserved                     */
  .word     0                                 /* Reserved                     */
  .word     SAI2_IRQHandler                   /* SAI2                         */
  .word     QUADSPI_IRQHandler                /* QuadSPI                      */
  .word     CEC_IRQHandler                    /* CEC                          */
  .word     SPDIF_RX_IRQHandler               /* SPDIF RX                     */
  .word     FMPI2C1_EV_IRQHandler          /* FMPI2C 1 Event               */
  .word     FMPI2C1_ER_IRQHandler          /* FMPI2C 1 Error               */
  

  .size  g_pfnVectors, .-g_pfnVectors

 

우선순위 설정

// 우선순위 설정 예시
HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);      // 최고 우선순위 (응급 버튼)
HAL_NVIC_SetPriority(TIM2_IRQn, 1, 0);       // 중간 우선순위 (타이머)
HAL_NVIC_SetPriority(USART2_IRQn, 2, 0);     // 낮은 우선순위 (통신)

 

 

Handler and Callback

핸들러 함수 (Interrupt Service Routine, ISR)

인터럽트 발생 시 CPU가 즉시 진입하는 함수로, 벡터 테이블에 등록되어 있으며 NVIC에 의해 직접 호출

 

  • 하드웨어 인터럽트와 직접 연결됨
  • 함수 이름은 고정 (XX_IRQHandler)
  • 매우 빠르게 응답해야 하며, 가볍고 빠르게 실행되어야 함

 

void EXTI0_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);  // HAL 라이브러리의 공통 핸들러 호출
}

 

콜백 함수 (Callback Function)

핸들러 내부에서 라이브러리(HAL 등)에 의해 호출되는 사용자 정의 함수로, 실제 동작(비즈니스 로직)은 여기서 처리

 

  • 사용자가 정의함 (예: 버튼을 눌렀을 때의 동작)
  • HAL 내부에서 ISR 처리 후 자동으로 호출됨
  • HAL이 제공하는 확장 가능한 후처리 구조
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == GPIO_PIN_0)
    {
        // 버튼 눌림 처리: LED 토글, 변수 변경 등
    }
}

 

 

처리 흐름

1. 인터럽트 발생
2. NVIC가 EXTI0_IRQHandler() 실행
3. HAL_GPIO_EXTI_IRQHandler() 호출 → 인터럽트 플래그 클리어
4. HAL 내부에서 HAL_GPIO_EXTI_Callback() 호출
5. 사용자 정의 동작 실행

 

 

예제

STM32F0: RAM 기반 벡터 테이블 (VTOR 미지원)

STM32F0는 VTOR이 없으므로, 벡터 테이블을 RAM으로 복사하여 사용.

#include "stm32f0xx.h"

#define VECTOR_TABLE_SIZE 48
uint32_t vectorTable_RAM[VECTOR_TABLE_SIZE] __attribute__((section(".RAMVectorTable")));

void RelocateVectorTable(void) {
    for (uint32_t i = 0; i < VECTOR_TABLE_SIZE; i++) {
        vectorTable_RAM[i] = *(__IO uint32_t*)(0x00000000 + (i * 4));
    }
    
    __disable_irq();
    __enable_irq();
}

int main(void) {
    HAL_Init();
    RelocateVectorTable();
    SystemInit();
    while (1) {
    }
}

- 벡터 테이블은 플래시(0x00000000)에서 RAM으로 복사됨
- 링커 스크립트에서 .RAMVectorTable 섹션을 RAM 영역에 정의해야 함
- NVIC는 RAM 주소를 직접 참조하도록 설정되며, VTOR이 없으므로 하드웨어 매핑에 의존

STM32F4: VTOR을 사용한 벡터 테이블 재배치

STM32F4는 VTOR을 지원하므로, 플래시 메모리 내 다른 주소로 벡터 테이블을 재배치 가능

#include "stm32f4xx.h"

#define NEW_VECTOR_TABLE_ADDRESS 0x08004000

void RelocateVectorTable(void) {
    __disable_irq();
    SCB->VTOR = NEW_VECTOR_TABLE_ADDRESS;
    __enable_irq();
}

int main(void) {
    HAL_Init();
    SystemInit();
    RelocateVectorTable();
    while (1) {
    }
}

 

- SCB->VTOR에 새 벡터 테이블 주소를 설정
- 링커 스크립트에서 벡터 테이블을 NEW_VECTOR_TABLE_ADDRESS에 배치해야 함
- 부트로더와 사용자 애플리케이션 간 전환 시 유용

 

// CMSIS/레지스터 직접 설정
extern uint32_t __vector_table[];  // 벡터 테이블 배열

void VectorTable_Relocate(void) {
    SCB->VTOR = (uint32_t)__vector_table;
}

// HAL 기반 설정
// main.c 또는 system_*.c 파일에
#define VECT_TAB_OFFSET  0x2000  // 원하는 플래시 오프셋

void SystemInit(void) {
    SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;
}

 

STM32F4: 부트로더에서 사용자 코드로 점프

부트로더에서 사용자 코드로 전환 시 VTOR을 재설정하는 예제

#include "stm32f4xx.h"

#define USER_CODE_ADDRESS 0x08010000

void JumpToUserCode(void) {
    __disable_irq();
    SCB->VTOR = USER_CODE_ADDRESS;
    uint32_t stack_pointer = *(__IO uint32_t*)USER_CODE_ADDRESS;
    uint32_t reset_handler = *(__IO uint32_t*)(USER_CODE_ADDRESS + 4);
    __set_MSP(stack_pointer);
    void (*user_reset_handler)(void) = (void (*)(void))reset_handler;
    user_reset_handler();
}

int main(void) {
    HAL_Init();
    JumpToUserCode();
    while (1) {
    }
}

 

VTOR을 사용자 코드 주소로 설정하여 인터럽트 벡터를 재배치
- 스택 포인터(MSP)와 리셋 핸들러를 읽어 사용자 코드로 점프

'MCU' 카테고리의 다른 글

ESP32-BLE-Raspberry pi  (0) 2025.06.09
STM32-CAN-Raspberry Pi  (0) 2025.04.07
DHT22 온습도 센서  (0) 2025.03.23
OLED display 128x32  (0) 2025.02.28
STM32 clock  (0) 2025.01.23