부트로더에서 앱으로 점프했다.

근데 인터럽트 터지면 HardFault.


문제

STM32는 기본적으로 0x08000000의 Vector Table을 참조한다.

인터럽트 발생
    ↓
0x08000000 + offset 주소 읽음
    ↓
부트로더의 핸들러로 점프  ← 문제!

앱 실행 중인데 부트로더 핸들러가 호출됨.


해결: VTOR

Vector Table Offset Register.

Cortex-M3/M4에서 지원. (M0는 없음)

SCB->VTOR = APP_ADDR;  // 앱의 Vector Table 주소로 변경

이제 인터럽트 발생하면:

인터럽트 발생
    ↓
0x08042800 + offset 주소 읽음  ← VTOR 값 사용
    ↓
앱의 핸들러로 점프  ← 정상!

VTOR 위치

// core_cm3.h 또는 core_cm4.h
#define SCB_VTOR  (*((volatile uint32_t *)0xE000ED08))

또는 CMSIS 헤더 사용:

#include "stm32f1xx.h"
SCB->VTOR = APP_ADDR;

VTOR 정렬 조건

VTOR 값은 정렬되어야 함.

Cortex-M3/M4: 128바이트 또는 벡터 수에 따라
              최소 0x80 (128) 배수

0x08042800은 0x80의 배수라 OK.


부트로더에서 설정

앱으로 점프하기 직전에:

void jump_to_app(void) {
    uint32_t app_sp = *(volatile uint32_t *)APP_ADDR;
    uint32_t app_reset = *(volatile uint32_t *)(APP_ADDR + 4);
    
    // VTOR 재배치
    SCB->VTOR = APP_ADDR;
    
    // MSP 설정
    __set_MSP(app_sp);
    
    // 앱으로 점프
    void (*reset_handler)(void) = (void (*)(void))app_reset;
    reset_handler();
}

앱에서도 설정?

앱 쪽 system_stm32f1xx.c에서:

#define VECT_TAB_OFFSET  0x00042800U  // 앱 오프셋

이러면 앱이 SystemInit()에서 VTOR 설정함.

근데 부트로더에서 이미 했으니까 중복. 둘 중 하나만 해도 됨.

개인적으론 부트로더에서 하는 게 깔끔함.


Cortex-M0는?

VTOR 없음. Vector Table 재배치 불가.

대신 RAM에 Vector Table 복사하고 리맵핑하는 방법 있음. 복잡함.

F103은 Cortex-M3라 VTOR 사용 가능.


다음 글에서 앱으로 점프하기.

#7 - 앱으로 점프하기