CMSIS-Core 6.0.0 · Cortex-M 시작 코드

Cortex-M: 리셋 벡터에서 main까지

벡터, 시작 코드, 링크 배치와 C 런타임의 역할을 구분해 main 이전의 실패를 찾습니다.

첫 두 항목은 스택 값과 시작 주소입니다

Cortex-M 시작을 볼 때는 유효한 벡터 테이블의 기준 주소부터 확인합니다. CMSIS 시작 코드 예시의 첫 항목은 초기 MSP 값, 두 번째 항목은 Reset_Handler입니다. 각 항목이 32비트인 이 테이블에서 오프셋은 각각 0과 4바이트입니다. 두 번째 항목이 main을 직접 가리킨다는 뜻은 아닙니다.

주소 0으로 보이는 부트 메모리와 실제 Flash 주소가 같은 개념인 것은 아닙니다. 칩의 부트 설정·주소 별칭·사용 가능한 VTOR·보안 상태를 먼저 확인합니다. 이미 실행 중인 부트로더가 응용으로 분기하는 과정은 하드웨어 리셋과 다릅니다. 인터럽트·클록·스택 등 인계 상태를 별도로 맞춰야 하므로 여기의 흐름만으로 점프 코드를 만들지 않습니다.

CMSIS 예시에 따른 개념 흐름
  1. 유효 벡터: 초기 MSP·Reset_Handler

  2. 시스템 초기화: SystemInit

  3. C 런타임 진입: __PROGRAM_START

  4. 초기화가 끝난 뒤 main

링커는 배치하고 런타임은 초기화합니다

CMSIS 예시의 Reset_Handler는 SystemInit을 호출한 뒤 __PROGRAM_START로 제어를 넘깁니다. 실제 프로젝트의 함수 이름과 초기화 순서는 툴체인·SDK에 따라 달라집니다. .data 복사, .bss 초기화, 필요한 언어 런타임 준비가 어느 코드에 있는지 현재 startup 파일과 런타임 구현에서 추적합니다.

GNU ld의 LMA 설명에서 LMA는 섹션을 적재할 위치이고 VMA는 실행 중 사용하는 주소입니다. Flash에 초기값을 두고 RAM에서 사용하는 .data라면 두 주소가 달라질 수 있습니다. 링크 스크립트가 두 주소를 정했다고 해서 리셋 뒤의 복사가 저절로 수행되지는 않습니다. 복사 루프나 런타임이 그 배치를 이용해야 합니다.

예시 항목의미
.data의 LMA 0x08004000초기값이 저장된 가상 예시 위치
.data의 VMA 0x20000000실행 중 접근할 가상 예시 위치
복사 크기와 경계 심볼해당 빌드의 링크 결과에서 확인

위 주소는 교육용 가정이며 특정 보드의 메모리 맵이나 실제 측정값이 아닙니다. .bss를 포함한 모든 RAM을 무조건 같은 방식으로 초기화한다고 일반화하지 않습니다.

main에 도달하지 못하면 앞 단계를 좁힙니다

부트 모드와 실제 적재 파일을 맞춘 뒤 벡터 값, 초기 스택이 속한 유효 RAM, Reset_Handler의 실행 주소를 확인합니다. 다음으로 링크 map의 섹션 범위와 초기화 루프의 경계를 대조합니다. 그 뒤 SystemInit과 런타임 진입 전후에 중단점을 두어 처음 달라지는 위치를 찾습니다. 이 순서는 조사 방법이며 보드에서 수행한 시험 결과가 아닙니다.

이른 시점의 출력은 클록·핀·드라이버가 아직 준비되지 않아 실패할 수 있습니다. 로그가 없다고 해서 main 이전의 어느 지점에서 실패했는지 확정할 수는 없습니다. 디버거가 연결되면서 리셋·부트 상태를 바꾸는지도 함께 기록합니다.

대상과 자료

이 글은 LinkedIn 원고 451·582·597의 시작 경로를 공식 예시와 대조한 설명입니다. Cortex-M의 흐름을 ARM64 Linux 부팅과 섞지 않습니다. 호출 이후의 복귀는 LR·SP와 Step Out에서 이어집니다. 원게시물의 전체 미디어를 재검증하거나 보드에서 실행한 기록은 아닙니다.

English summary. Separate the vector, system initialization, runtime and main. Linker placement does not execute data initialization. A bootloader handover is not a hardware reset; verify the actual device and startup implementation.