본문 바로가기
경제

임베디드기사 실기 20부작 2편 Startup Code와 부팅의 시작

by 프레스러쉬 2026. 9. 14.

임베디드기사 실기 20부작 2편
Startup Code와 부팅의 시작

임베디드 시스템에 전원을 넣으면 우리가 작성한 main() 함수가 곧바로 실행될 것 같지만 실제로는 그렇지 않습니다. CPU는 먼저 정해진 리셋 위치에서 시작하고, 어셈블리 기반의 초기화 코드를 거쳐 스택과 메모리, 클럭, C 런타임 환경을 준비한 뒤에야 main()이나 다음 단계의 Bootloader로 넘어갑니다.

이번 편의 핵심 질문
전원이 들어온 직후 CPU는 어디서 시작하는가?
왜 startup.s 같은 어셈블리 코드가 필요한가?
.data와 .bss는 왜 초기화해야 하는가?
Startup Code와 Bootloader는 어떻게 다른가?

1. 전원 인가 직후 가장 먼저 실행되는 것은 무엇일까?

시스템에 전원이 인가되거나 Reset이 발생하면 CPU의 Program Counter는 아키텍처가 정한 Reset Vector를 가리키게 됩니다. 이때 실행되는 최초의 초기화 코드를 일반적으로 Startup Code 또는 Reset Handler라고 부릅니다.

이 단계에서는 아직 C언어 프로그램이 정상적으로 동작할 수 있는 조건이 만들어지지 않았습니다. Stack Pointer가 준비되지 않았을 수 있고, 외부 DRAM도 초기화되지 않았으며, 전역변수의 초기값도 RAM에 배치되지 않았습니다. 따라서 최초의 코드는 보통 어셈블리어로 작성됩니다.

부팅의 큰 흐름

Reset

Reset Vector

startup.s / Reset Handler

CPU 상태·Stack 초기화

Clock / PLL / Memory Controller 초기화

.data 복사 / .bss 0 초기화

main() 또는 Bootloader

2. Reset Vector는 왜 필요한가?

Reset Vector는 CPU가 Reset 직후 어디에서 첫 명령을 읽을지를 결정하는 시작점입니다. 아키텍처마다 구체적인 주소와 형식은 다르지만 개념은 같습니다. CPU가 아무 코드도 모르는 상태에서 출발할 수 있도록 최초의 진입점을 하드웨어적으로 정해두는 것입니다.

ARM 계열에서는 Vector Table의 초기 항목에 Stack Pointer 초기값과 Reset Handler 주소가 배치되는 형태가 널리 사용됩니다. 시험에서는 정확한 주소 암기보다 Reset → Vector 참조 → Reset Handler 실행이라는 순서를 이해하는 것이 중요합니다.

3. 왜 처음부터 C언어로 시작하지 않을까?

C 함수가 실행되려면 Stack이 있어야 하고, 함수 호출 규약이 동작해야 하며, 전역·정적 변수의 메모리 배치도 정상적으로 끝나 있어야 합니다. 하지만 Reset 직후에는 이런 환경이 아직 만들어지지 않았습니다.

그래서 Startup Code는 먼저 CPU 모드와 상태 레지스터를 설정하고, 필요하면 인터럽트를 잠시 비활성화하고, Stack Pointer를 초기화합니다. 이후 Clock과 외부 Memory Controller 등을 설정해 C언어가 사용할 수 있는 실행 환경을 만듭니다.

시험 암기 포인트
Startup Code의 대표 역할을 물으면 다음 키워드를 떠올리면 됩니다.
Reset Vector / Stack Pointer / Clock / SDRAM / .data / .bss / main()

4. Clock과 Memory Controller 초기화

MCU나 SoC는 Reset 직후 저속의 기본 Clock으로 시작하는 경우가 많습니다. 실제 시스템 동작을 위해 Oscillator와 PLL을 설정해 목표 주파수로 올립니다. 외부 DDR/SDRAM을 사용하는 시스템이라면 Memory Controller의 Timing과 초기화 Sequence도 필요합니다.

외부 RAM이 정상 동작하지 않으면 Kernel Image를 복사하거나 대용량 Stack/Heap을 사용할 수 없습니다. 그래서 메모리 초기화는 Bootloader와 Startup Code를 이해할 때 매우 중요한 연결고리입니다.

5. .data와 .bss는 왜 따로 처리할까?

.data에는 초기값이 있는 전역변수와 정적변수가 들어갑니다. 예를 들어 int count = 10;과 같은 값입니다. 초기값은 비휘발성 메모리인 Flash에 저장되어 있다가 실행 시 RAM의 .data 영역으로 복사됩니다.

.bss에는 초기값이 없는 전역·정적 변수가 들어갑니다. 예를 들어 int error_count;와 같은 변수입니다. C언어 규칙상 이런 변수는 0으로 시작해야 하므로 Startup Code가 해당 RAM 영역을 0으로 Clear합니다.

.data와 .bss 한눈에 보기

.data : 초기값 있음 → Flash의 초기값을 RAM으로 복사
.bss : 초기값 없음 → RAM 영역을 0으로 초기화

6. Startup Code와 Linker Script의 관계

Startup Code가 아무리 정확해도 코드와 데이터가 실제 메모리의 올바른 위치에 배치되지 않으면 시스템은 부팅되지 않습니다. 이때 중요한 것이 Linker Script(.ld)입니다.

Linker Script는 Flash와 RAM의 주소 범위, Vector Table과 .text, .data, .bss 등의 배치 위치를 결정합니다. 즉 Startup Code가 '어떻게 초기화할지'를 담당한다면 Linker Script는 '어디에 배치할지'를 정의한다고 볼 수 있습니다.

7. Startup Code와 Bootloader의 차이

두 용어는 부팅 초기에 함께 등장해 자주 헷갈립니다. Startup Code는 C 실행 환경을 만드는 최소 초기화 코드에 가깝고, Bootloader는 보다 큰 범위에서 저장장치·네트워크·DRAM을 준비하고 Kernel Image와 DTB를 읽어 RAM에 적재한 뒤 운영체제에 제어권을 넘기는 부팅 프로그램입니다.

비교

Startup Code
Reset 직후 실행환경 준비
Stack·Clock·Memory·C Runtime 초기화
.data 복사, .bss Clear
main() 또는 다음 단계로 Jump

Bootloader
DRAM·Storage·Network 초기화
Kernel Image/DTB Load
Boot Arguments 설정
Kernel Entry Point로 Jump

8. 실기시험에서는 어떻게 물어볼까?

실기에서는 단순히 'Startup Code란 무엇인가?'뿐 아니라 수행 순서나 .data/.bss 초기화, Bootloader와의 차이로 변형될 수 있습니다.

예상문제 1
Startup Code가 main() 실행 전에 수행하는 작업을 4가지 쓰시오.

모범답안 예
Reset Vector를 통해 초기 진입점을 설정하고 Stack Pointer와 CPU 상태를 초기화한다. Clock과 Memory Controller 등 저수준 하드웨어를 초기화한다. Flash의 .data 초기값을 RAM으로 복사하고 .bss 영역을 0으로 초기화한 뒤 main() 또는 Bootloader로 제어권을 넘긴다.

예상문제 2
.data와 .bss의 차이를 설명하시오.

예상문제 3
Startup Code와 Bootloader의 차이를 설명하시오.

시험장에서 쓰기 좋은 3문장 답안

Startup Code는 전원 인가 또는 Reset 직후 실행되어 시스템의 최소 실행 환경을 준비하는 초기화 코드이다. Stack Pointer, Clock, Memory Controller 등을 설정하고 .data를 RAM으로 복사하며 .bss를 0으로 초기화한다. 초기화가 완료되면 main() 함수 또는 다음 단계의 Bootloader로 제어권을 넘긴다.

9. 실무에서 왜 중요한가?

Startup Code를 이해하면 'main()에 한 줄도 도달하지 않는 고장'을 분석할 수 있습니다. Clock 설정 오류, SDRAM Timing 문제, Vector Table 위치 오류, Stack 주소 오류, .data 복사 범위 오류 등은 모두 애플리케이션 코드가 시작되기 전 단계에서 시스템을 멈출 수 있습니다.

따라서 임베디드 개발에서 부팅 문제를 분석할 때는 Application부터 보는 것이 아니라 Reset → Vector → Startup → Memory → Bootloader → Kernel/Application의 순서로 좁혀가는 습관이 중요합니다.

10. 오늘의 초압축 암기

Reset → Reset Vector → Startup Code → Stack/Clock/Memory 초기화 → .data 복사 → .bss 0 → main()/Bootloader

Startup Code = 실행환경 준비
Bootloader = OS/Kernel을 찾아 적재하고 실행

11. 다음 편 예고

다음 3편에서는 Bootloader와 Linux 부팅 과정을 다룹니다. U-Boot가 DRAM을 준비하고 Kernel Image와 Device Tree를 RAM에 올린 뒤 Kernel로 제어권을 넘기는 과정을 하나의 흐름으로 연결해 보겠습니다.


태그
#임베디드기사 #임베디드기사실기 #임베디드실기 #StartupCode #ResetHandler #ResetVector #Bootloader #ARM #CortexM #임베디드펌웨어 #링커스크립트 #LinkerScript #부팅시퀀스 #펌웨어개발 #기사실기 #임베디드시스템 #Uboot #EmbeddedLinux #자격증공부 #기술블로그