728x90
반응형
Memory Structure
- Memory Regions
- RAM(Random Access Memory):
- 주 메모리 또는 작업 메모리로 사용된다.
- 데이터에 대한 빠른 읽기와 쓰기를 지원한다.
- 전원이 꺼지면 저장된 데이터가 사라지는 휘발성 메모리이다.
- ROM(Read-Only Memory):
- 데이터를 읽을 수만 있고, 일반적으로 쓰기는 불가능하다.
- 시스템의 기본 입력/출력 시스템(BIOS) 또는 펌웨어가 저장되어 있다.
- 전원이 꺼져도 데이터가 유지되는 비휘발성 메모리이다.
- FLASH:
- CPU와 주 메모리 사이의 속도 차이를 줄이기 위해 사용된다.
- 가장 자주 사용되거나 최근에 사용된 데이터를 빠르게 접근하기 위한 작은 용량의 빠른 메모리이다.
- RAM(Random Access Memory):
Linker Script
링커 스크립트(Linker Script)는 링커가 오브젝트 파일들을 어떻게 결합하여 실행 가능한 파일 또는 라이브러리를 생성할지 지시하는 스크립트 파일이다. 이 스크립트는 링커의 작업을 제어하고, 프로그램이 메모리에 어떻게 로드되고 실행될지를 정의한다. 링커 스크립트의 주요 기능은 다음과 같다.
- 메모리 레이아웃 지정:
링커 스크립트는 메모리 내에서 프로그램의 각 섹션(text, data, bss)이 어디에 배치될지 지정한다.
이를 통해 특정 메모리 주소에 데이터와 코드를 배치할 수 있다. - 심볼 할당:
특정 심볼(변수나 함수 이름)에 메모리 주소를 할당하거나, 심볼에 특정 값을 지정할 수 있다. - 섹션의 병합 및 순서 정의:
오브젝트 파일의 여러 섹션들을 어떻게 결합할지, 그리고 그 순서를 어떻게 정할지를 지정한다.
이는 실행 파일의 최적화와 메모리 사용 효율성을 높이는 데 중요하다. - 엔트리 포인트 지정:
프로그램이 시작되는 지점, 즉 entry point를 지정한다.
일반적으로 'main'함수가 이 역할을 한다.
링커 스크립트는 특히 임베디드 시스템, 운영 체제의 커널, 또는 메모리 구성이 복잡하거나 특별한 제약이 있는
시스템 소프트웨어에서 중요한 역할을 한다. 이러한 환경에서는 메모리 공간이 제한적이거나 특정 기능이 특정 메모리
주소에 위치해야 할 필요가 있기 때문에, 링커 스크립트를 통해 정밀한 메모리 관리와 제어가 가능해진다.
- _estack (Stack의 시작 주소)
- 위치: RAM의 가장 마지막 주소
- 설명:
스택은 메모리의 가장 높은 주소에서 시작하여 낮은 주소로 커진다.
예를 들어, "_estack = ORIGIN(RAM) * LENGTH(RAM)"과 같이 스택의 시작 주소를 정의하여
RAM의 가장 높은 주소에서 시작한다.
일반적으로 임베디드 시스템이나 시스템 레벨 프로그래밍에서 사용되는 시작 주소를 나타내는 심볼(Symbol)이다.
- 스택의 시작 주소 지정:
'e_stack'은 Stack memory의 최상단 주소를 나타낸다.
이 주소는 RAM의 끝 부분에 위치하며, 스택이 이 주소에서부터 아래로(낮은 메모리 주소 방향으로) 확장 된다. - 스택 초기화:
임베디드 시스템이 시작될 때, 'e_stack' 주소는 스택 포인터 초기값으로 설정된다.
이를 통해 프로그램이 로컬(지역) 변수, 함수 호출 정보 등을 저장할 스택 메모리를 사용할 수 있게 된다. - 높은 주소 지정:
일반적으로 스택은 메모리의 높은 주소 영역에서 시작한다.
이는 스택이 아래로 확장되도록 하고, 힙(동적 메모리)와의 충돌을 방지하기 위함이다. - 스택 오버플로우 방지:
스택 메모리가 한정된 크기를 가지고 있기 때문에 '_estack'을 통해 스택의 시작 지점을 명확히 정의하는 것은 Stack Overflow를 방지하는 데 중요하다. 이는 프로그램의 안정성을 보장하는데 필수적인 부분이다. - 링커 스크립트에서의 역할:
'e_stack'은 링커 스크립트에서 정의되어, 스택의 크기와 위치를 제어한다. 이를 통해 개발자는 메모리 구조에 맞게 스택을 최적화할 수 있다.
- 스택의 시작 주소 지정:
- '_estack'은 특히 메모리 관리가 중요한 임베디드 시스템이나 시스템 레벨의 소프트웨어 개발에서 중요한 역할을 한다. 스택 메모리의 효율적인 사용과 관리는 프로그램의 안정성과 성능에 직접적인 영향을 미친다.
- .isr_vector (Interrupt Service Routines Vector)
- 위치: ROM(FLASH)의 시작 주소
- 설명:
이 섹션은 ROM의 시작 주소에 위치한다.
프로그램 또는 임베디드 시스템의 메모리에서 인터럽트 서비스 루틴(ISR)의 주소를 나타내는
벡터 테이블을 저장하는 부분이다.
- 인터럽트 벡터 테이블:
.isr_vector 섹션은 인터럽트 벡터 테이블을 포함한다.
이 테이블은 시스템이 특정 interrupt를 받았을 때 실행해야할 함수(Interrupt Service Routine)의 주소 목록을 담고 있다. - 시스템 초기화 및 인터럽트 처리:
프로그램이나 시스템이 시작될 때, .isr_vector 세그먼트는 CPU가 인터럽트에 대응하는 방법을 알 수 있도록
초기화한다. 예를 들어, 하드웨어 인터럽트, 예외 처리, 시스템 호출 등이 발생했을 때 해당 인터럽트의 종류에 따라 적절한 ISR을 호출한다. - 메모리 상의 위치:
.isr_vector 세그먼트는 보통 ROM(FLASH)의 시작 부분에 위치한다.
이는 시스템이 부팅될 때 바로 접근 가능하도록 하기 위함이다. - 고정된 주소 할당:
Interrupt vector table은 일반적으로 고정된 주소에 할당된다.
이는 시스템이 정확한 위치에서 인터럽트 처리 루틴의 주소를 찾을 수 있도록 하기 위함이다. - 임베디드 시스템에서의 중요성:
특히 임베디드 시스템에서 .isr_vector 세그먼트는 매우 중요하다.
임베디드 시스템은 다양한 external event에 빠르고 정확하게 반응해야 하며, 이를 위해서는 효율적인 인터럽트 처리가 필수적이다.
- 인터럽트 벡터 테이블:
- .isr_vector 세그먼트의 이러한 특징들은 시스템의 안정성과 반응성을 보장하는 데 중요한 역할을 한다.
인터럽트가 발생했을 때 시스템이 신속하고 정확하게 대응할 수 있도록 하는 것이 핵심이다.
- .text(실행 코드)
- 위치: ROM(FLASH)
- 설명:
프로그램의 실행 코드를 포함한다.
이는 메모리의 낮은 주소에 위치한다.
.text 세그먼트는 프로그램의 메모리에서 실제 실행 코드를 포함하는 부분이다.
이 세그먼트는 프로그램의 기계어 코드, 즉 컴파일된 소스 코드의 명령어들이 저장되는 곳이다.
- 실행 코드 저장:
.text 세그먼트는 프로그램이 실행 될 때 CPU에 의해 직접 실행되는 기계어 코드를 담고 있다.
이는 함수, 루프, 조건문 등 프로그램의 로직을 구현한 코드이다. - 읽기 전용(Read-Only):
대부분의 시스템에서 .text 세그먼트는 읽기 전용으로 설정된다.
이는 프로그램 실행 중에 코드가 변경되는 것을 방지하여 안정성과 보안을 향상시킨다. - 메모리 공간 효율성:
.text 세그먼트는 메모리 공간을 효율적으로 사용한다.
같은 코드가 여러 번 사용되더라도 한 번만 메모리에 로드되어 실행된다. - 실행 파일의 핵심 부분:
.text 세그먼트는 실행 파일의 핵심적인 부분을 구성한다.
프로그램이 실행 될 때, 이 섹션의 내용은 메모리에 로드되어 CPU에서 직접 실행된다. - 메모리 상의 위치:
.text 섹션은 보통 메모리의 낮은 주소 영역에 위치한다.
이는 프로그램의 실행 코드가 메모리에서 쉽게 접근 가능하도록 하기 위함이다.
- 실행 코드 저장:
- .data(Initialized data)
- 위치: RAM
- 설명:
초기화된 전역변수와 정적변수를 포함한다.
이 데이터는 프로그램 시작시 ROM에서 RAM으로 복사된다.
프로그램의 메모리에서 초기화된 데이터
즉, 프로그램 시작 시점에 이미 특정 값으로 설정된 전역 변수와 정적 변수를 저장하는 부분이다.- 초기화된 데이터 저장:
.data 세그먼트는 프로그램의 소스코드에서 초기값이 명시적으로 주어진 전역 변수와 정적 변수를 포함한다.
예를 들어 C언어에서 'int a = 10;' 와 같이 선언된 전역 변수는 .data 세그먼트에 저장된다. - 실행파일의 일부분:
초기화된 데이터는 프로그램의 실행 파일에 저장된다.(정적)
이는 프로그램이 실행될 때 이 데이터가 메모리로 로드되어야 함을 의미한다. - 메모리 할당:
프로그램 실행 시, .data 세그먼트의 데이터는 메모리에 할당되고, 실행 파일에 저장된 초기값으로 초기화된다. 이 과정은 프로그램 시작 전에 수행된다. - 비휘발성:
.data 세그먼트는 프로그램 실행 중 지속적으로 유지되며, 프로그램이 종료될 때까지 메모리에 남아 있다. - 메모리 사용 효율:
.data 세그먼트는 필요한 만큼의 메모리만을 사용하며,
각 변수에 할당된 초기값에 따라 메모리 공간이 결정된다.
- 초기화된 데이터 저장:
- .bss(Block Started by Symbol: Uninitialized data)
- 위치: RAM
- 설명:
초기화되지 않은 전역 변수와 정적변수를 포함한다.
일반적으로는 0으로 초기화된다.
.bss 세그먼트의 변수들은 프로그램이 실행 될 때 0 또는 NULL 값으로 자동 초기화된다.
이 세그먼트의 목적은 메모리 공간을 절약하기 위함이다.
따라서 초기화되지 않은 변수들은 실제로 디스크 상에 저장할 필요가 없기 때문에,
.bss 세그먼트는 프로그램의 실행 파일 크기를 줄이는 데 기여한다.
- 초기화되지 않은 데이터 저장:
.bss 세그먼트는 프로그램 소스 코드에서 명시적인 초기값이 주어지지 않은 전역 및 정적 변수를 포함한다.
예를 들어, C 언어에서 'int a;'와 같이 선언된 전역 변수는 .bss 세그먼트에 저장된다. - 기본값으로의 초기화:
프로그램 실행 시, .bss 세그먼트의 변수들은 기본적으로 0 또는 NULL 값으로 초기화된다.
이는 메모리를 할당 받은 직후에 자동으로 수행된다. - 메모리 효율성:
.bss 세그먼트는 프로그램의 실행 파일 크기를 줄이는 데 기여한다.
초기화되지 않은 변수들은 실제 디스크 상의 실행 파일에 저장되지 않고, 실행 시 메모리에만 할당되기 때문이다. - 동적 메모리 할당:
프로그램 실행 중에 메모리 크기가 결정 되므로, .bss 세그먼트는 동적 메모리 관리에 있어 중요한 역할을 한다. - 실행 파일과의 관계:
실행 파일에는 .bss 세그먼트에 대한 정보만 포함되며, 실제 데이터는 포함되지 않는다.
이는 .bss 세그먼트가 프로그램의 메모리 이미지에서만 존재한다는 것을 의미한다. - 디버깅과 오류 추적:
초기화되지 않은 변수들이 자동으로 0으로 초기화되므로, 프로그래머가 의도하지 않은 변수 사용을 방지하고 디버깅을 용이하게 한다.
- 초기화되지 않은 데이터 저장:
- .bss 세그먼트는 특히 메모리 사용량과 프로그램 실행 파일의 크기 최적화에 중요하다.
초기화되지 않은 변수들을 효율적으로 관리하면서 동시에 메모리 사용을 최적화할 수 있다.
- _user_heap_stack (Heap Section)
- 위치: .bss 섹션 이후의 RAM
- 설명:
동적 메모리 할당(Malloc)을 위한 heap 섹션이다.
heap은 낮은 주소에서 높은 주소로 커진다.
일반적으로 임베디드 시스템 프로그래밍에서 사용되는 Symbol로, heap과 stack 메모리 영역을 정의하는 데 사용된다.
- heap 메모리 정의:
'user_heap_stack' 은 동적 메모리 할당을 위한 heap region의 시작점과 크기를 정의한다.
heap은 프로그램 실행 중에 필요에 따라 memory를 할당하고 해제하는 데 사용된다. - stack 메모리 정의:
이 심볼은 또한 stack region을 위한 공간을 지정한다.
stack은 함수 호출, 로컬 변수 저장 등에 사용되며, 후입선출(LIFO) 방식으로 동작한다. - 메모리 구분:
'user_heap_stack'을 사용하여 heap과 stack 메모리 영역을 명확히 구분하고 관리할 수 있다.
이는 memory collision과 overflow를 방지하는 데 중요하다. - 동적 메모리 관리:
heap 영역은 프로그램의 동적 메모리 요구 사항에 따라 확장 및 축소 될 수 있다.
'user_heap_stack' 을 통해 heap의 초기 위치와 최대 크기를 설정함으로서 메모리 관리의 유연성을 제공한다. - 링커 스크립트에서의 역할:
'user_heap_stack'은 링커 스크립트 내에서 정의되어, heap과 stack의 크기 및 위치를 제어한다.
이를 통해 개발자는 시스템의 메모리 구조에 맞게 이러한 영역을 최적화할 수 있다. - 메모리 사용 최적화:
특히 메모리가 제한된 임베디드 시스템에서, 'user_heap_stack'을 사용하여 heap과 stack의 메모리 사용을 효과적으로 최적화 할 수 있다.
- heap 메모리 정의:
- Stack과 Heap Size 설정:
링커스크립트에서는 최소 힙 크기(min_heap_size)와 최소 스택 크기(min_stack_size)를 사전에 정의할 수 있다.
이는 빌드 시점에서 실제 사용될 메모리 크기를 예측할 수 없기 때문이다.
- 메모리 배치 순서:
메모리에 각 섹션이 배치되는 순서는 일반적으로 Linker Script(.ld)에 명시된 순서대로 이루어진다.
이러한 구조는 특히 Embedded System에서 매우 중요하며, 각각의 MCU마다 메모리 사양이 다르기 때문에
메모리 레이아웃을 세밀하게 조정할 필요가 있기 때문에 존재한다.
728x90
반응형
'Firmware & Embedded > ARM' 카테고리의 다른 글
ST-Link V2 Debugger/Programmer Manual (0) | 2024.01.07 |
---|---|
Startup code (0) | 2024.01.07 |
Code Formatter Profile (0) | 2024.01.06 |
STM32 - Clock Configuration (0) | 2024.01.05 |
To build a simple build process (0) | 2024.01.01 |