STM32 상전원 후 부트로더 동작 과정: 하드웨어 초기화에서 애플리케이션 실행까지

임베디드 시스템 개발을 시작하는 순간, STM32 마이크로컨트롤러의 LED가 처음 깜빡일 때 우리는 성취감을 느낀다. 하지만 전원이 인가되고 첫 번째 명령어가 실행되기까지 칩 내부에서 어떤 일이 벌어질까? 이 글에서는 STM32가 전원을 받은 후 부트로더를 통해 어떻게 소프트웨어를 안정적으로 구동하는지 단계별로 살펴본다.

1. 전원 인가와 초기 하드웨어 준비

마이크로컨트롤러는 단순한 프로세서가 아니라 통합된 시스템이다. 전원이 공급되면 다음 순서로 하드웨어 상태를 정립한다:

  1. 전압 안정화: LDO 및 전력 관리 회로가 3.3V 출력을 생성하고, 모든 전원 도메인이 안정될 때까지 대기한다.
  2. 내장 클럭 활성화: 외부 크리스털 없이도 작동 가능한 HSI(High Speed Internal) 발진기가 최초 클럭 소스로 선택된다 (보통 8MHz).
  3. 리셋 해제: NRST 핀의 저전압 상태가 해제되면, 칩은 리셋 해제 지연(RESET RELEASE DELAY)을 거쳐 초기 실행 흐름으로 진입한다.

이 시점에서 CPU는 아직 메모리에 저장된 사용자 코드를 실행하지 않는다. 대신, 현재 선택된 부팅 모드에 따라 시작 주소를 결정한다. 이 설정은 BOOT0과 BOOT1 핀의 조합으로 제어된다.

부팅 소스 BOOT1 BOOT0 시작 주소 용도
주 플래시 메모리 X 0 0x08000000 일반 애플리케이션 실행
시스템 메모리 X 1 0x1FFF0000 UART를 통한 펌웨어 다운로드 (ISP)
SRAM 1 1 0x20000000 디버깅 또는 동적 로딩

2. 부트로더의 역할과 초기화 절차

가장 일반적인 경우인 주 플래시 메모리에서 부팅하는 시나리오를 기준으로 설명한다.

2.1 초기 스택 및 예외 벡터 설정

CPU는 첫 번째 4바이트를 초기 스택 포인터(SP)로, 두 번째 4바이트를 리셋 핸들러 주소로 읽어들인다. 이 정보는 벡터 테이블에 정의되어 있으며, 링커 스크립트를 통해 .isr_vector 섹션에 배치된다.

__attribute__((section(".isr_vector")))
void (* const vector_table[])(void) = {
    (void*)(&__main_stack_end),   // 초기 스택 최상위 주소
    reset_handler_entry,          // 리셋 발생 시 점프할 함수
    nmi_interrupt,                // NMI 처리기
    hard_fault_handler,           // 하드폴트 예외 처리
    mem_manage_handler,
    bus_fault_handler,
    usage_fault_handler,
    // ... 기타 예외 벡터
};

2.2 시스템 클럭 구성

HSI 클럭은 불안정할 수 있으므로, 대부분의 애플리케이션은 PLL을 사용해 더 높고 정확한 시스템 클럭을 생성한다. 예를 들어:

  • HSI → PLL 입력
  • PLL ×6 → 48MHz 시스템 클럭
  • 클럭 분배: AHB, APB1, APB2 버스에 적절히 분배

2.3 애플리케이션 무결성 검사 (옵션)

보안 부트 또는 신뢰성 요구사항이 높은 시스템에서는 다음 검사를 수행할 수 있다:

  • Firmware CRC 또는 SHA-256 해시 검증
  • 디지털 서명 확인 (RSA/ECDSA 기반)
  • 플래시 메모리의 보호 비트 상태 확인

3. 사용자 애플리케이션으로 제어 이양

모든 준비가 완료되면, 부트로더는 최종적으로 사용자 코드로 점프한다. 이 과정은 어셈블리 레벨에서 다음과 같이 구현된다:

; 사용자 애플리케이션 시작 주소 정의
.equ APP_START_ADDR, 0x08000000

; 스택 포인터 및 프로그램 카운터 설정
ldr r0, =APP_START_ADDR
ldr sp, [r0]          ; 첫 번째 워드: 스택 포인터 값
ldr pc, [r0, #4]      ; 두 번째 워드: 리셋 핸들러 주소

이 순간 PC(Program Counter)는 0x08000000 위치 이후의 reset_handler_entry로 이동하며, C 런타임 환경 초기화(__libc_init_array) 및 main() 함수 호출이 시작된다.

결국 LED가 깜빡이는 것은 단순한 출력이 아니라, 수십 개의 하드웨어 블록과 소프트웨어 단계가 정밀하게 협업한 결과물이다. 이러한 이해는 디버깅이나 부트로더 커스터마이징 시 큰 도움이 된다.

태그: STM32 Bootloader embedded systems ARM Cortex-M Firmware Initialization

6월 10일 17:46에 게시됨