그라운드 임베디드 EN 유튜브 구독

노트 / MCU 펌웨어

부트로더: 펌웨어가 스스로 업데이트하는 구조

Flash를 부트로더와 앱으로 나누고, 새 펌웨어를 받아 검증한 뒤 앱으로 점프합니다. 점프 순서와 실패 대비.

GROUND EMBEDDED · 정리 노트펌웨어 12부트로더 1uint32_t sp = *(uint32_t *)APP_ADDR, pc… 2__disable_irq(); 3// 사용한 주변장치와 SysTick 끄기, 펜딩 인터럽트 지우기 4SCB->VTOR = APP_ADDR;

메모리 분할 예

영역 주소 크기
부트로더 0x0800_0000 16KB
앱 0x0800_4000 나머지
(선택) 새 앱 임시 영역 뒤쪽 앱과 같은 크기

부트로더 흐름

리셋부트로더업데이트 요청?있으면 새 이미지 수신CRC·서명 검증앱으로 점프
리셋 뒤 부트로더가 하는 일. 검증에 실패하면 앱으로 넘어가지 않습니다.
  1. 리셋 → 부트로더 실행
  2. 업데이트 요청(버튼, 플래그, 통신 명령)이 있으면 UART/CAN/USB로 새 이미지 수신
  3. 앱 영역을 지우고 쓰기, CRC나 서명 검증
  4. 앱이 유효하면 앱으로 점프

앱으로 점프하는 순서

uint32_t sp = *(uint32_t *)APP_ADDR, pc = *(uint32_t *)(APP_ADDR + 4);
__disable_irq();
// 사용한 주변장치와 SysTick 끄기, 펜딩 인터럽트 지우기
SCB->VTOR = APP_ADDR;
__set_MSP(sp);
((void (*)(void))pc)();

앱은 링커 스크립트의 FLASH 시작 주소를 0x0800_4000으로 바꿔 빌드합니다.

실패 대비

  • 쓰는 도중 전원이 꺼져도 부트로더는 남아 있어야 합니다. 부트로더 영역은 쓰기 보호합니다.
  • 앱 끝에 "유효" 표시를 마지막에 쓰고, 표시가 없으면 부트로더에 머뭅니다.
  • 이미지 두 개를 번갈아 쓰는 A/B 방식이면 새 앱이 부팅에 실패할 때 이전 앱으로 되돌릴 수 있습니다.

STM32에는 ROM에 내장된 시스템 부트로더(BOOT0 핀)도 있어서 공장 초기 굽기에 씁니다.

그림으로 보기: Flash를 나눠 쓰기

0x0800_0000부트로더16 KB, 바꾸지 않음0x0800_4000응용 프로그램업데이트 대상끝부분설정 저장버전, CRC, 플래그
Flash 맨 앞에는 부트로더가, 그 뒤에 응용 프로그램이 놓입니다. 리셋되면 항상 부트로더부터 실행됩니다.

부트로더는 작고 단순해야 합니다. 부트로더 자체에 버그가 있으면 고칠 방법이 없기 때문입니다.

부트로더가 하는 판단

  1. 업데이트 요청이 있는가? (버튼, 플래그, 통신으로 들어온 명령)
  2. 응용 프로그램이 온전한가? (CRC 검사)
  3. 온전하면 응용으로 점프, 아니면 업데이트 대기
int main(void) {
    if (!update_requested() && app_crc_ok()) jump_to_app();
    run_update_protocol();          // 여기서 새 펌웨어를 받는다
}

응용으로 점프하기

응용 프로그램의 벡터 테이블 첫 두 칸에는 초기 스택 포인터와 리셋 핸들러 주소가 들어 있습니다.

#define APP_BASE 0x08004000u

void jump_to_app(void) {
    uint32_t sp    = *(uint32_t *)(APP_BASE + 0);
    uint32_t reset = *(uint32_t *)(APP_BASE + 4);

    __disable_irq();
    /* 부트로더가 켠 주변장치와 인터럽트를 모두 끄고, 대기 중인 요청을 지운다 */
    SCB->VTOR = APP_BASE;           // 벡터 테이블을 응용 것으로
    __set_MSP(sp);
    ((void (*)(void))reset)();
}

응용 프로그램 쪽에서는 링커 스크립트의 Flash 시작 주소를 0x08004000으로 옮겨야 합니다. 이를 빠뜨리면 응용이 부트로더 자리에 맞춰 빌드되어 점프 직후 죽습니다.

무료 전자책이 주제를 한 권으로 이어 읽기 (PDF 3권)→

Flash에 쓰는 규칙

  • 지워야 쓸 수 있다: Flash는 1을 0으로만 바꿀 수 있습니다. 다시 1로 만들려면 페이지나 섹터 단위로 지워야 합니다.
  • 지우는 단위가 크다: 수 KB 단위입니다. 한 바이트만 고칠 수 없습니다.
  • 횟수 제한: 보통 1만~10만 번입니다. 자주 바뀌는 값을 같은 자리에 계속 쓰면 닳습니다.
  • 쓰는 동안 조심: 쓰기 중 전원이 끊기면 그 페이지는 반쯤 쓰인 상태가 됩니다.

전원이 끊겨도 벽돌이 되지 않게

방법 원리 대가
CRC 확인 후 점프 응용이 깨졌으면 부트로더에 머묾 가장 기본, 반드시 넣기
유효 플래그를 마지막에 기록 전체를 쓰고 검증한 뒤에만 "완료" 표시 플래그 저장 공간
슬롯 두 개 (A/B) 새 버전을 빈 슬롯에 쓰고 전환 Flash가 두 배 필요
시험 부팅 후 확정 새 버전이 정상 동작을 알려야 확정, 아니면 되돌림 구현 복잡

적어도 앞의 두 가지는 넣습니다. 업데이트 도중 전원이 꺼져도 부트로더가 살아 있으면 다시 시도할 수 있습니다.

업데이트 프로토콜에 들어갈 것

  • 전체 크기와 버전을 먼저 보낸다.
  • 일정 크기 블록마다 번호와 CRC를 붙이고, 받는 쪽이 응답한다.
  • 응답이 없으면 같은 블록을 다시 보낸다.
  • 마지막에 전체 CRC로 한 번 더 확인한다.

현업에서 자주 터지는 문제

  • 점프 후 인터럽트가 이상함: 부트로더가 켠 타이머나 UART 인터럽트를 끄지 않고 넘어갔습니다.
  • 워치독: 부트로더에서 워치독을 켰다면 응용에서도 계속 먹이를 줘야 합니다. 한 번 켜면 끌 수 없는 워치독이 많습니다.
  • 다른 제품의 펌웨어를 받아들임: 헤더에 제품 식별자를 넣어 확인합니다.
  • 보안: 서명 검증이 없으면 누구든 임의의 펌웨어를 넣을 수 있습니다. 제품에는 서명 확인과 읽기 보호를 검토합니다.
영상으로 이어 보기회로와 하드웨어 시리즈 8편전자제품 속 회로 소자는 어떻게 동작할까? · 저항 · 커패시터 · 인덕터 완벽 정리PROJECT COURSE레지스터 설정을 실제 보드에서 해 보고 싶다면밸런싱 로봇 하나를 요구사항, 회로와 PCB, 펌웨어, 앱까지 실무 순서대로 만드는 강의입니다. 10파트 165강.강의 살펴보기 →FREE PDF무료 전자책 3권 받기이 주제를 한 권으로 이어서 읽고 싶다면. BLDC 모터 제어, 직렬통신, 센서를 책 분량으로 묶었습니다. 이메일만 남기면 바로 받습니다.무료로 받기 →