[Embedded] 임베디드 시스템의 이해 ②

예빈·2025년 11월 26일

Embedded/Linux

목록 보기
3/21


0️⃣ 들어가며

임베디드 시스템의 이해 2번째 편이다.
순서 상으로는 ARM프로세서 이전이라고 보면 된다.
기초 임베디드 시스템 관련 포스팅은 다음 글이 마지막일 것 같다.
이번 글에서는 컴파일, 링크, 실행 과정에 관한 내용이 대부분이다.


1️⃣ 학습 내용

임베디드 소프트웨어의 컴파일, 링크, 실행 과정 이해

빌드 및 메모리 섹션의 흐름

  • 컴파일-링크-실행 과정 개요

    소스 코드가 실행파일로 만들어지고, 메모리(RAM/ROM)에 올려 실행되기까지의 과정

    각 과정에서 데이터와 코드가 .text, .data, .bss, .const 등 다양한 메모리 구역(섹션)으로 분리되어 관리됨

  • 소스 코드 → 오브젝트 파일(.o) 변환

    소스(.c) 파일을 컴파일하면, 해당 소스의 코드(.text), 상수(.const), 초기화 데이터(.data), 초기화되지 않은 데이터(.bss) 등이 분리되어 오브젝트 파일에 저장

    .text : 실행 코드 영역

    .const : 상수 데이터

    .data : 초기값이 있는 전역변수

    .bss : 초기값이 없는 전역/정적 변수

  • 여러 오브젝트 파일 → 실행 파일(ELF, BIN 등) 생성

    각각의 오브젝트 파일(A.o, B.o 등)을 링커가 하나로 합쳐 실행 파일(a.out 등)을 만듦

    이 과정에서 각 섹션들도 합쳐지고, 실제 메모리상 배치 정보가 결정됨

메모리 주소, 적재(로딩) 시점의 이해

  • Load View (LMA, Load Memory Address)

    링커 단계에서 결정되는, 코드와 데이터가 플래시/ROM에 저장될 실제 주소

    (예: a.out(passive), Load View(LMA))

  • Virtual View (VMA, Virtual Memory Address)

    프로그램이 실행될 때, RAM 등에서 각 섹션(.text, .data, .bss 등)이 실제로 매핑되는 실행 시점의 주소

    ROM 등 외부 저장소에서 RAM으로 섹션이 복사되어 실행

임베디드 메모리 영역의 이해

메모리 섹션의 구분

  • 섹션별 데이터 구분

    ROM: 변경 불가능한 코드/상수

    RAM: 변경 가능한 데이터/초기화 데이터

    섹션별 데이터 구분으로 메모리 사용을 최적화하고 신뢰성을 확보

주요 메모리 영역과 섹션

  • Code (.text)

    함수, 실행 명령어 등 프로그램의 동작 코드가 포함된 영역

    ROM(Flash)에 저장되어 직접 실행하는 경우가 많고, 일반적으로 변경되지 않음

  • Read-only Data (RO, .rodata, .const)

    수정될 수 없는 데이터, (예: const 변수, 상수 테이블)

    코드와 마찬가지로 ROM 또는 Flash에 저장

  • Read-write Data (RW, .data)

    초기화 값이 있지만 실행 중 변경 가능한 데이터 영역

    초기값은 ROM/Flash에서 저장되지만, 실행 시 RAM에 복사되어 사용

    예: 초기값이 있는 전역변수, static 변수 등

  • Zero-initialized Data (ZI, .bss)

    초기값이 '0'인 글로벌/static 변수 영역

    ROM에는 저장되지 않고, 프로그램 시작 시 RAM(또는 SDRAM)에서 0으로 초기화되어 사용

메모리 맵핑 과정 정리

  • 빌드 과정

    소스 코드(.c, .h) → 컴파일 → 오브젝트 파일(.o) 생성

    각 오브젝트 파일 내부에 .text, .rodata, .data, .bss 등이 각각 할당

  • 링크 과정

    여러 오브젝트(.o) → 실행파일(ELF, BIN 등) 병합

    링커 스크립트에 따라 각 섹션별 ROM/Flash, RAM 맵핑 결정

  • 실행 과정

    ROM에는 code, ro-data, rw-data(초기값), 루트로더 등 필수 데이터 저장

    RAM에는 code(필요시), ro-data(필요시), rw-data(변수), zi-data(0으로 초기화) 등이 적재

    스타트업 코드(Startup Code)가 RAM으로 데이터 복사 및 초기화 실행

  • 로케이터

    로케이터(링커와 함께)는 여러 오브젝트 파일의 섹션을 합치고, 실제 실행 타겟의 메모리 주소에 각 섹션을 배치

    최종 프로그램의 코드, 데이터, 스택 등이 RAM, ROM, Flash 등 실제 위치에 올라갈 자리를 결정

  • 로케이터의 섹션별 데이터 배치 원리

    • 초기화된 전역 변수

      코드 내에서 값이 지정된 전역변수(예: int a = 10;)

      컴파일 시 ROM(Flash)에 저장, 프로그램 시작 시 RAM으로 복사됨(.data 영역)

    • 초기화되지 않은 전역 변수

      값이 없는 전역/정적 변수(예: int b;)

      실행 시작 시 RAM(.bss 영역)에 공간을 할당, 값은 0으로 자동 초기화

    • 문자열 리터럴/포인터

      상수 문자열은 ROM에 위치, char* 포인터 변수는 RAM에서 해당 위치를 가리킴

      (예: 전역 char = "문자열")

    • 지역 변수

      함수 내 선언된 변수, 실행 시간에 스택(RAM)에 할당/소멸 (.stack 영역)

  • 타겟 모델 구성하기

    타겟 MCU나 SoC별로 RAM, NAND Flash/NOR Flash/ROM 등 구성이 다름

    • 예: 라즈베리파이의 구성

      MCU(메인 프로세서)

      RAM(실행 중 데이터 저장)

      NAND Flash(대용량 저장 매체, OS/파일시스템 등)

ROM Writer와 주요 레지스터

  • ROM Writer

    BIN/HEX 등 실행 가능한 이미지 파일을 Flash나 ROM에 직접 기록하는 장치/툴

    부트/실행을 위해 MCU가 해당 ROM/Flash에서 코드를 읽어옴

  • 프로그램 카운터, 스택 포인터, 링크 레지스터

    • PC(Program Counter) 

      다음에 실행할 명령어의 주소를 가리키는 레지스터

    • SP(Stack Pointer) 

      스택 영역의 최상단(최근)에 있는 데이터 주소

    • LR(Link Register) 

      함수 호출 시 복귀 주소 저장, ARM 아키텍처 등에서 사용


0개의 댓글