1. 링커 스크립트 개요 (Overview of Linker Script)
STM32 마이크로컨트롤러의 링커 스크립트는 컴파일된 소스 코드를 실행 가능한 파일(.elf)로 변환할 때, 코드와 데이터를 메모리의 적절한 위치에 배치하는 역할을 합니다 (The Linker Script for STM32 microcontrollers controls the placement of code and data in memory when converting compiled source code into an executable file (.elf)). STM32는 ARM Cortex-M 기반의 32비트 마이크로컨트롤러로, 모터 제어, IoT, 임베디드 시스템 등 다양한 애플리케이션에 사용됩니다 (The STM32, a 32-bit ARM Cortex-M-based microcontroller, is used in various applications such as motor control, IoT, and embedded systems). 이 문서는 초보자도 쉽게 이해할 수 있도록 링커 스크립트의 역할, 구조, 작성 방법, 그리고 실용적인 예제를 한글과 영어로 상세히 설명합니다 (This document explains the role, structure, writing methods, and practical examples of Linker Scripts in both Korean and English, designed to be easily understood by beginners).
1.1 링커 스크립트의 역할 (Role of Linker Script)
링커 스크립트는 STM32의 메모리 관리에서 다음과 같은 중요한 역할을 합니다 (The Linker Script plays the following critical roles in STM32 memory management):
- 메모리 정의 (Memory Definition): STM32의 Flash, SRAM, CCM 같은 메모리 영역의 시작 주소와 크기를 정의합니다 (Defines the start address and size of memory regions like Flash, SRAM, and CCM in STM32).
- 섹션 배치 (Section Placement): 컴파일러가 생성한 코드(.text), 데이터(.data, .bss) 등을 적절한 메모리 영역에 배치합니다 (Places compiler-generated code (.text) and data (.data, .bss) into appropriate memory regions).
- 스택/힙 설정 (Stack/Heap Configuration): 프로그램 실행에 필요한 스택과 힙 메모리 크기를 지정합니다 (Specifies the stack and heap memory sizes required for program execution).
- 특수 섹션 관리 (Special Section Handling): 고속 실행을 위해 CCM에 코드를 배치하거나 FreeRTOS 같은 라이브러리용 섹션을 관리합니다 (Manages sections for high-speed execution in CCM or for libraries like FreeRTOS).
- 디버깅 지원 (Debugging Support): 메모리 배치를 명확히 정의해 ST-Link 같은 디버깅 도구로 메모리 상태를 쉽게 확인할 수 있도록 합니다 (Clearly defines memory placement to facilitate memory state inspection with debugging tools like ST-Link).
1.2 STM32F407 메모리 구조 (STM32F407 Memory Structure)
STM32F407(STM32F4 시리즈)의 메모리 구조를 이해하는 것은 링커 스크립트 작성의 첫걸음입니다 (Understanding the memory structure of the STM32F407, part of the STM32F4 series, is the first step in writing a Linker Script). 주요 메모리 영역은 다음과 같습니다 (The main memory regions are as follows):
- Flash:
- 크기 (Size): 1MB (0x08000000 ~ 0x08FFFFFF)
- 용도 (Purpose): 프로그램 코드, 상수, 부트로더 저장 (Stores program code, constants, and bootloader).
- SRAM:
- SRAM1: 112KB (0x20000000 ~ 0x2001BFFF), 메인 데이터, 스택, 힙 (Main data, stack, and heap).
- SRAM2: 16KB (0x2001C000 ~ 0x2001FFFF), 추가 데이터 또는 버퍼 (Additional data or buffers).
- CCM (Core-Coupled Memory): 64KB (0x10000000 ~ 0x1000FFFF), CPU와 직접 연결된 고속 메모리, 고속 코드/데이터 (High-speed memory directly connected to the CPU, used for high-speed code/data).
- Boot ROM:
- 크기 (Size): 30KB (0x1FFF0000 ~ 0x1FFF77FF)
- 용도 (Purpose): 시스템 부트로더, 읽기 전용 (System bootloader, read-only).
- Peripheral Registers:
- 주소 (Address): 0x40000000 ~ 0x400FFFFF
- 용도 (Purpose): 주변 장치(타이머, GPIO 등) 제어 레지스터 (Control registers for peripherals like timers and GPIO).
- Reset Vector:
- 주소 (Address): 0x08000004
- 용도 (Purpose): 부팅 시 프로그램이 시작되는 지점 (The point where the program starts upon boot).
1.3 링커 스크립트의 중요성 (Importance of Linker Script)
링커 스크립트는 STM32 프로젝트의 성공적인 실행을 위해 필수적입니다 (The Linker Script is essential for the successful execution of STM32 projects). 이유는 다음과 같습니다 (The reasons are as follows):
- 정확한 메모리 관리 (Accurate Memory Management): 잘못된 메모리 배치는 프로그램 충돌이나 비정상 동작을 유발할 수 있습니다 (Incorrect memory placement can cause program crashes or abnormal behavior).
- 성능 최적화 (Performance Optimization): 자주 실행되는 코드를 CCM이나 SRAM에 배치해 속도를 높입니다 (Placing frequently executed code in CCM or SRAM improves speed).
- 프로덕션 대비 (Production Readiness): Flash 기반 스크립트는 배포용, SRAM 기반 스크립트는 디버깅용으로 적합합니다 (Flash-based scripts are suitable for production, while SRAM-based scripts are ideal for debugging).
- 특수 기능 지원 (Special Feature Support): FreeRTOS, HAL, CMSIS 같은 라이브러리를 사용할 때 필요한 메모리 배치를 지원합니다 (Supports memory placement required for libraries like FreeRTOS, HAL, and CMSIS).
2. 링커 스크립트의 구조 (Structure of Linker Script)
링커 스크립트는 두 가지 주요 부분으로 구성됩니다 (The Linker Script consists of two main parts):
- MEMORY 섹션 (MEMORY Section): STM32의 물리적 메모리 영역(Flash, SRAM 등)을 정의합니다 (Defines the physical memory regions of STM32, such as Flash and SRAM).
- SECTIONS 섹션 (SECTIONS Section): 컴파일러가 생성한 코드와 데이터를 메모리 영역에 배치합니다 (Places compiler-generated code and data into memory regions).
2.1 MEMORY 섹션 (MEMORY Section)
MEMORY 섹션은 STM32의 메모리 영역을 이름, 시작 주소, 크기로 정의합니다 (The MEMORY section defines STM32’s memory regions by name, start address, and size).
구문 (Syntax):
MEMORY
{
NAME : ORIGIN = ADDRESS, LENGTH = SIZE
}
- NAME: 메모리 영역의 이름 (예: FLASH, SRAM1) (Name of the memory region, e.g., FLASH, SRAM1).
- ORIGIN: 메모리 영역의 시작 주소 (16진수) (Start address of the memory region in hexadecimal).
- LENGTH: 메모리 영역의 크기 (바이트 단위, 16진수) (Size of the memory region in bytes, in hexadecimal).
- 속성 (Attributes): 읽기(r), 쓰기(w), 실행(x) 가능 여부를 나타냅니다 (Indicates whether the region is readable (r), writable (w), or executable (x)).
예시 (Example):
MEMORY
{
/* Flash 메모리: 프로그램 코드 저장 (Flash memory: Stores program code) */
FLASH : ORIGIN = 0x08000000, LENGTH = 1024K /* 1MB */
/* SRAM1: 데이터, 스택, 힙 (SRAM1: Data, stack, heap) */
SRAM1 : ORIGIN = 0x20000000, LENGTH = 112K /* 112KB */
/* SRAM2: 추가 데이터 (SRAM2: Additional data) */
SRAM2 : ORIGIN = 0x2001C000, LENGTH = 16K /* 16KB */
/* CCM: 고속 코드/데이터 (CCM: High-speed code/data) */
CCM : ORIGIN = 0x10000000, LENGTH = 64K /* 64KB */
}
설명 (Description): 이 예시는 STM32F407의 주요 메모리 영역을 정의합니다 (This example defines the main memory regions of the STM32F407). 각 영역의 시작 주소와 크기를 정확히 명시하여 메모리 충돌을 방지합니다 (Specifying the start address and size of each region accurately prevents memory conflicts).
2.2 SECTIONS 섹션 (SECTIONS Section)
SECTIONS 섹션은 컴파일러가 생성한 섹션(.text, .data 등)을 메모리 영역에 매핑합니다 (The SECTIONS section maps compiler-generated sections like .text and .data to memory regions).
구문 (Syntax):
SECTIONS
{
.section_name : { contents } > MEMORY_NAME
}
- .section_name: 컴파일러가 생성한 섹션 이름 (예: .text, .data) (Name of the compiler-generated section, e.g., .text, .data).
- contents: 섹션에 포함될 오브젝트 파일의 내용 (Contents of the object files included in the section).
- MEMORY_NAME: MEMORY 섹션에서 정의한 메모리 영역 (Memory region defined in the MEMORY section).
주요 섹션 (Main Sections):
- .isr_vector: 인터럽트 벡터 테이블, 부팅 시 필요한 인터럽트 핸들러 주소 (Interrupt vector table, containing addresses of interrupt handlers needed at boot).
- .text: 실행 가능한 프로그램 코드 (Executable program code).
- .rodata: 읽기 전용 데이터, 상수 (Read-only data, constants).
- .data: 초기화된 전역/정적 변수 (Initialized global/static variables).
- .bss: 초기화되지 않은 전역/정적 변수 (Uninitialized global/static variables).
- .heap: 동적 메모리 할당을 위한 힙 (Heap for dynamic memory allocation).
- .stack: 함수 호출 및 로컬 변수 저장을 위한 스택 (Stack for function calls and local variables).
- .fastcode: CCM에 배치되는 고속 실행 코드 (High-speed code placed in CCM).
예시 (Example):
SECTIONS
{
/* 인터럽트 벡터 테이블: Flash 시작 주소에 배치 (Interrupt vector table: Placed at the start of Flash) */
.isr_vector : { *(.isr_vector) } > FLASH
/* 프로그램 코드: Flash에 배치 (Program code: Placed in Flash) */
.text : { *(.text*) } > FLASH
/* 읽기 전용 데이터: Flash에 배치 (Read-only data: Placed in Flash) */
.rodata : { *(.rodata*) } > FLASH
/* 초기화된 데이터: SRAM1에서 실행, Flash에 저장 (Initialized data: Executed in SRAM1, stored in Flash) */
.data : { *(.data) } > SRAM1 AT > FLASH
/* 초기화되지 않은 데이터: SRAM1에 배치 (Uninitialized data: Placed in SRAM1) */
.bss : { *(.bss) } > SRAM1
/* 힙: 동적 메모리 할당, SRAM1에 4KB 할당 (Heap: Dynamic memory allocation, 4KB in SRAM1) */
.heap : { . = ALIGN(4); _heap_start = .; . += 0x1000; _heap_end = .; } > SRAM1
/* 스택: 함수 호출 및 로컬 변수, SRAM1에 8KB 할당 (Stack: Function calls and local variables, 8KB in SRAM1) */
.stack : { . = ALIGN(4); _stack_start = .; . += 0x2000; _stack_end = .; } > SRAM1
}
2.3 고급 기능 (Advanced Features)
- LOAD/RUN 분리 (LOAD/RUN Separation): 섹션을 Flash에 저장(LOAD)하고 SRAM에서 실행(RUN)하도록 설정합니다 (Sets sections to be stored in Flash (LOAD) and executed in SRAM (RUN)).
- 예: .data : { *(.data) } > SRAM1 AT > FLASH는 데이터를 Flash에 저장하고 부팅 시 SRAM1으로 복사합니다 (Example: .data : { *(.data) } > SRAM1 AT > FLASH stores data in Flash and copies it to SRAM1 at boot).
- 스택/힙 설정 (Stack/Heap Configuration): 스택과 힙 크기를 명시적으로 정의하여 메모리 사용을 최적화합니다 (Explicitly defines stack and heap sizes to optimize memory usage).
- 엔트리 포인트 (Entry Point): ENTRY(Reset_Handler)로 부팅 시 프로그램의 시작 지점을 지정합니다 (Specifies the program start point at boot with ENTRY(Reset_Handler)).
3. 링커 스크립트 작성 절차 (Linker Script Writing Procedure)
링커 스크립트를 작성하는 단계는 초보자도 따라 할 수 있도록 간단히 정리했습니다 (The steps for writing a Linker Script are simplified for beginners to follow):
- 디바이스 메모리 맵 확인 (Check Device Memory Map):
- STM32F407의 레퍼런스 매뉴얼(RM0090)을 확인하여 Flash, SRAM, CCM의 주소와 크기를 파악합니다 (Check the STM32F407 Reference Manual (RM0090) to identify the addresses and sizes of Flash, SRAM, and CCM).
- STM32CubeMX에서 장치 설정을 확인하여 메모리 맵을 쉽게 파악할 수 있습니다 (Use STM32CubeMX to easily identify the memory map).
- MEMORY 섹션 작성 (Write MEMORY Section):
- Flash, SRAM1, SRAM2, CCM의 시작 주소와 크기를 정확히 정의합니다 (Define the start addresses and sizes of Flash, SRAM1, SRAM2, and CCM accurately).
- 예: Flash는 0x08000000에서 시작, 1MB 크기 (Example: Flash starts at 0x08000000 with a size of 1MB).
- SECTIONS 섹션 작성 (Write SECTIONS Section):
- 코드(.text, .rodata)는 Flash에, 데이터(.data, .bss)는 SRAM1에 배치합니다 (Place code (.text, .rodata) in Flash and data (.data, .bss) in SRAM1).
- 인터럽트 벡터(.isr_vector)는 Flash의 시작 주소에 배치합니다 (Place the interrupt vector (.isr_vector) at the start of Flash).
- 스택과 힙은 SRAM1에 적절한 크기로 할당합니다 (Allocate appropriate sizes for stack and heap in SRAM1).
- 특수 섹션 처리 (Handle Special Sections):
- 고속 실행이 필요한 코드는 CCM에 .fastcode로 배치합니다 (Place performance-critical code in CCM as .fastcode).
- FreeRTOS를 사용할 경우 힙 섹션을 추가로 정의합니다 (Define an additional heap section for FreeRTOS).
- 링커 옵션 설정 (Set Linker Options):
- ENTRY(Reset_Handler)로 엔트리 포인트를 지정합니다 (Specify the entry point with ENTRY(Reset_Handler)).
- 스택 크기와 힙 크기를 적절히 설정합니다 (Set appropriate stack and heap sizes).
- 검증 및 디버깅 (Validation and Debugging):
- 빌드 후 .map 파일을 확인하여 섹션이 올바르게 배치되었는지 점검합니다 (Check the .map file after building to ensure sections are correctly placed).
- STM32CubeIDE의 Memory View로 메모리 내용을 확인합니다 (Inspect memory contents using STM32CubeIDE’s Memory View).
- 메모리 오버플로우가 발생하면 MEMORY 크기나 SECTIONS 배치를 수정합니다 (If memory overflow occurs, adjust MEMORY sizes or SECTIONS placement).
4. 링커 스크립트 작성 고려사항 (Considerations for Writing Linker Scripts)
- 메모리 최적화 (Memory Optimization):
- 자주 실행되는 코드는 CCM에 배치하여 속도를 높입니다 (Place frequently executed code in CCM to increase speed).
- 상수(.rodata)는 Flash에 배치하여 SRAM을 절약합니다 (Place constants (.rodata) in Flash to save SRAM).
- 스택과 힙 (Stack and Heap):
- 기본 스택 크기: 8KB, 복잡한 애플리케이션에서는 더 크게 설정 (Default stack size: 8KB, increase for complex applications).
- 힙은 FreeRTOS나 동적 메모리 할당이 필요한 경우 적절히 설정합니다 (Set the heap size appropriately for FreeRTOS or dynamic memory allocation).
- Flash 프로그래밍 (Flash Programming):
- 부트로더와 애플리케이션 코드를 분리하여 Flash 메모리를 효율적으로 사용합니다 (Separate bootloader and application code to use Flash memory efficiently).
- Flash 섹터 구조를 고려하여 섹션 배치를 최적화합니다 (Optimize section placement considering Flash sector structure).
- 디버깅 vs. 프로덕션 (Debugging vs. Production):
- 디버깅: SRAM 기반 스크립트로 빠른 테스트를 수행합니다 (Debugging: Use SRAM-based scripts for quick testing).
- 프로덕션: Flash 기반 스크립트로 배포합니다 (Production: Use Flash-based scripts for deployment).
- STM32Cube 활용 (Using STM32Cube):
- STM32CubeMX 또는 STM32CubeIDE에서 제공하는 기본 링커 스크립트를 활용하여 시작합니다 (Start with default Linker Scripts provided by STM32CubeMX or STM32CubeIDE).
5. 링커 스크립트 예제 (Linker Script Examples)
다음은 STM32F407을 위한 다양한 링커 스크립트 예제입니다 (The following are various Linker Script examples for the STM32F407). 각 예제는 초보자도 이해할 수 있도록 주석을 상세히 추가했습니다 (Each example includes detailed comments to make it understandable for beginners).
5.1 예제 1: 기본 Flash 기반 링커 스크립트 (Example 1: Basic Flash-Based Linker Script)
/* File: STM32F407_flash.ld */
/* Description: STM32F407 Flash 기반 기본 링커 스크립트 (Basic Flash-based Linker Script for STM32F407) */
/* Compiler: GNU ARM GCC (STM32CubeIDE) */
/* Target: STM32F407 */
/* 프로그램 시작 지점 설정: Reset_Handler는 부팅 시 호출되는 함수 (Set the program entry point: Reset_Handler is the function called at boot) */
ENTRY(Reset_Handler)
/* 메모리 영역 정의 (Define memory regions) */
MEMORY
{
/* Flash: 프로그램 코드와 상수 저장, 1MB (Flash: Stores program code and constants, 1MB) */
FLASH : ORIGIN = 0x08000000, LENGTH = 1024K
/* SRAM1: 데이터, 스택, 힙 저장, 112KB (SRAM1: Stores data, stack, and heap, 112KB) */
SRAM1 : ORIGIN = 0x20000000, LENGTH = 112K
/* SRAM2: 추가 데이터 저장, 16KB (SRAM2: Stores additional data, 16KB) */
SRAM2 : ORIGIN = 0x2001C000, LENGTH = 16K
/* CCM: 고속 코드/데이터 저장, 64KB (CCM: Stores high-speed code/data, 64KB) */
CCM : ORIGIN = 0x10000000, LENGTH = 64K
}
/* 섹션 배치 정의 (Define section placement) */
SECTIONS
{
/* 인터럽트 벡터 테이블: Flash의 시작 주소에 배치 (Interrupt vector table: Placed at the start of Flash) */
.isr_vector :
{
KEEP(*(.isr_vector)) /* 인터럽트 벡터 유지 (Keep interrupt vectors) */
} > FLASH
/* 프로그램 코드: Flash에 저장 (Program code: Stored in Flash) */
.text :
{
*(.text*) /* 모든 .text 섹션 포함 (Include all .text sections) */
KEEP(*(.init)) /* 초기화 코드 유지 (Keep initialization code) */
KEEP(*(.fini)) /* 종료 코드 유지 (Keep finalization code) */
} > FLASH
/* 읽기 전용 데이터: 상수, Flash에 저장 (Read-only data: Constants, stored in Flash) */
.rodata :
{
*(.rodata*) /* 모든 .rodata 섹션 포함 (Include all .rodata sections) */
} > FLASH
/* 초기화된 데이터: SRAM1에서 실행, Flash에 저장 (Initialized data: Executed in SRAM1, stored in Flash) */
.data :
{
_sdata = .; /* .data 섹션 시작 주소 저장 (Store start address of .data section) */
*(.data) /* 모든 .data 섹션 포함 (Include all .data sections) */
_edata = .; /* .data 섹션 끝 주소 저장 (Store end address of .data section) */
} > SRAM1 AT > FLASH
/* 초기화되지 않은 데이터: SRAM1에 배치, 초기화 시 0으로 설정 (Uninitialized data: Placed in SRAM1, initialized to 0) */
.bss :
{
_sbss = .; /* .bss 섹션 시작 주소 저장 (Store start address of .bss section) */
*(.bss) /* 모든 .bss 섹션 포함 (Include all .bss sections) */
*(COMMON) /* 공용 데이터 포함 (Include common data) */
_ebss = .; /* .bss 섹션 끝 주소 저장 (Store end address of .bss section) */
} > SRAM1
/* 힙: 동적 메모리 할당, SRAM1에 4KB 할당 (Heap: Dynamic memory allocation, 4KB in SRAM1) */
.heap :
{
. = ALIGN(4); /* 4바이트 정렬 (Align to 4 bytes) */
_heap_start = .; /* 힙 시작 주소 (Heap start address) */
. += 0x1000; /* 4KB 힙 크기 (4KB heap size) */
_heap_end = .; /* 힙 끝 주소 (Heap end address) */
} > SRAM1
/* 스택: 함수 호출 및 로컬 변수, SRAM1에 8KB 할당 (Stack: Function calls and local variables, 8KB in SRAM1) */
.stack :
{
. = ALIGN(4); /* 4바이트 정렬 (Align to 4 bytes) */
_stack_start = .; /* 스택 시작 주소 (Stack start address) */
. += 0x2000; /* 8KB 스택 크기 (8KB stack size) */
_stack_end = .; /* 스택 끝 주소 (Stack end address) */
} > SRAM1
}
설명 (Description):
- 목적 (Purpose): 기본적인 Flash 기반 애플리케이션, 초보자가 이해하기 쉬운 구조 (Basic Flash-based application with a beginner-friendly structure).
- 메모리 배치 (Memory Placement):
- 코드(.text, .rodata)와 인터럽트 벡터(.isr_vector)는 Flash에 배치 (Code (.text, .rodata) and interrupt vectors (.isr_vector) are placed in Flash).
- 데이터(.data, .bss)는 SRAM1에 배치 (Data (.data, .bss) is placed in SRAM1).
- 스택과 힙은 SRAM1에 각각 8KB와 4KB로 할당 (Stack and heap are allocated 8KB and 4KB in SRAM1, respectively).
- 특징 (Features):
- 부팅 시 .data 섹션을 Flash에서 SRAM1으로 복사하여 초기화 (Copies .data section from Flash to SRAM1 at boot for initialization).
- 주석을 상세히 추가하여 각 섹션의 역할을 명확히 설명 (Detailed comments explain the role of each section).
5.2 예제 2: SRAM 기반 링커 스크립트 (디버깅용) (Example 2: SRAM-Based Linker Script for Debugging)
/* File: STM32F407_sram.ld */
/* Description: STM32F407 SRAM 기반 디버깅용 링커 스크립트 (SRAM-based Linker Script for debugging STM32F407) */
/* Compiler: GNU ARM GCC (STM32CubeIDE) */
/* Target: STM32F407 */
/* 프로그램 시작 지점 설정: Reset_Handler는 부팅 시 호출되는 함수 (Set the program entry point: Reset_Handler is the function called at boot) */
ENTRY(Reset_Handler)
/* 메모리 영역 정의 (Define memory regions) */
MEMORY
{
/* SRAM1: 코드, 데이터, 스택, 힙 저장, 112KB (SRAM1: Stores code, data, stack, and heap, 112KB) */
SRAM1 : ORIGIN = 0x20000000, LENGTH = 112K
/* SRAM2: 추가 데이터 저장, 16KB (SRAM2: Stores additional data, 16KB) */
SRAM2 : ORIGIN = 0x2001C000, LENGTH = 16K
/* CCM: 고속 코드/데이터 저장, 64KB (CCM: Stores high-speed code/data, 64KB) */
CCM : ORIGIN = 0x10000000, LENGTH = 64K
}
/* 섹션 배치 정의 (Define section placement) */
SECTIONS
{
/* 인터럽트 벡터 테이블: SRAM1에 배치 (Interrupt vector table: Placed in SRAM1) */
.isr_vector :
{
KEEP(*(.isr_vector)) /* 인터럽트 벡터 유지 (Keep interrupt vectors) */
} > SRAM1
/* 프로그램 코드: SRAM1에 배치 (Program code: Placed in SRAM1) */
.text :
{
*(.text*) /* 모든 .text 섹션 포함 (Include all .text sections) */
KEEP(*(.init)) /* 초기화 코드 유지 (Keep initialization code) */
KEEP(*(.fini)) /* 종료 코드 유지 (Keep finalization code) */
} > SRAM1
/* 읽기 전용 데이터: SRAM1에 배치 (Read-only data: Placed in SRAM1) */
.rodata :
{
*(.rodata*) /* 모든 .rodata 섹션 포함 (Include all .rodata sections) */
} > SRAM1
/* 초기화된 데이터: SRAM1에 배치 (Initialized data: Placed in SRAM1) */
.data :
{
_sdata = .; /* .data 섹션 시작 주소 저장 (Store start address of .data section) */
*(.data) /* 모든 .data 섹션 포함 (Include all .data sections) */
_edata = .; /* .data 섹션 끝 주소 저장 (Store end address of .data section) */
} > SRAM1
/* 초기화되지 않은 데이터: SRAM1에 배치, 초기화 시 0으로 설정 (Uninitialized data: Placed in SRAM1, initialized to 0) */
.bss :
{
_sbss = .; /* .bss 섹션 시작 주소 저장 (Store start address of .bss section) */
*(.bss) /* 모든 .bss 섹션 포함 (Include all .bss sections) */
*(COMMON) /* 공용 데이터 포함 (Include common data) */
_ebss = .; /* .bss 섹션 끝 주소 저장 (Store end address of .bss section) */
} > SRAM1
/* 힙: 동적 메모리 할당, SRAM1에 4KB 할당 (Heap: Dynamic memory allocation, 4KB in SRAM1) */
.heap :
{
. = ALIGN(4); /* 4바이트 정렬 (Align to 4 bytes) */
_heap_start = .; /* 힙 시작 주소 (Heap start address) */
. += 0x1000; /* 4KB 힙 크기 (4KB heap size) */
_heap_end = .; /* 힙 끝 주소 (Heap end address) */
} > SRAM1
/* 스택: 함수 호출 및 로컬 변수, SRAM1에 8KB 할당 (Stack: Function calls and local variables, 8KB in SRAM1) */
.stack :
{
. = ALIGN(4); /* 4바이트 정렬 (Align to 4 bytes) */
_stack_start = .; /* 스택 시작 주소 (Stack start address) */
. += 0x2000; /* 8KB 스택 크기 (8KB stack size) */
_stack_end = .; /* 스택 끝 주소 (Stack end address) */
} > SRAM1
}
설명 (Description):
- 목적 (Purpose): 디버깅을 위한 SRAM 기반 스크립트, 빠른 테스트를 지원 (SRAM-based script for debugging, supports quick testing).
- 메모리 배치 (Memory Placement):
- 모든 코드와 데이터는 SRAM1에 배치 (All code and data are placed in SRAM1).
- 스택과 힙은 SRAM1에 각각 8KB와 4KB로 할당 (Stack and heap are allocated 8KB and 4KB in SRAM1, respectively).
- 특징 (Features):
- Flash를 사용하지 않아 빌드와 테스트가 빠릅니다 (No Flash usage enables fast build and test cycles).
- 주석이 상세히 추가되어 초보자가 각 섹션의 역할을 쉽게 이해할 수 있습니다 (Detailed comments help beginners understand the role of each section).
5.3 예제 3: CCM 활용 링커 스크립트 (Example 3: Linker Script Utilizing CCM)
/* File: STM32F407_ccm.ld */
/* Description: STM32F407 CCM 활용 링커 스크립트 (Linker Script utilizing CCM for STM32F407) */
/* Compiler: GNU ARM GCC (STM32CubeIDE) */
/* Target: STM32F407 */
/* 프로그램 시작 지점 설정: Reset_Handler는 부팅 시 호출되는 함수 (Set the program entry point: Reset_Handler is the function called at boot) */
ENTRY(Reset_Handler)
/* 메모리 영역 정의 (Define memory regions) */
MEMORY
{
/* Flash: 프로그램 코드와 상수 저장, 1MB (Flash: Stores program code and constants, 1MB) */
FLASH : ORIGIN = 0x08000000, LENGTH = 1024K
/* SRAM1: 데이터, 스택, 힙 저장, 112KB (SRAM1: Stores data, stack, and heap, 112KB) */
SRAM1 : ORIGIN = 0x20000000, LENGTH = 112K
/* SRAM2: 추가 데이터 저장, 16KB (SRAM2: Stores additional data, 16KB) */
SRAM2 : ORIGIN = 0x2001C000, LENGTH = 16K
/* CCM: 고속 코드/데이터 저장, 64KB (CCM: Stores high-speed code/data, 64KB) */
CCM : ORIGIN = 0x10000000, LENGTH = 64K
}
/* 섹션 배치 정의 (Define section placement) */
SECTIONS
{
/* 인터럽트 벡터 테이블: Flash의 시작 주소에 배치 (Interrupt vector table: Placed at the start of Flash) */
.isr_vector :
{
KEEP(*(.isr_vector)) /* 인터럽트 벡터 유지 (Keep interrupt vectors) */
} > FLASH
/* 프로그램 코드: Flash에 저장 (Program code: Stored in Flash) */
.text :
{
*(.text*) /* 모든 .text 섹션 포함 (Include all .text sections) */
KEEP(*(.init)) /* 초기화 코드 유지 (Keep initialization code) */
KEEP(*(.fini)) /* 종료 코드 유지 (Keep finalization code) */
} > FLASH
/* 읽기 전용 데이터: 상수, Flash에 저장 (Read-only data: Constants, stored in Flash) */
.rodata :
{
*(.rodata*) /* 모든 .rodata 섹션 포함 (Include all .rodata sections) */
} > FLASH
/* 고속 코드: CCM에 배치, 인터럽트 핸들러 등 빠른 실행 필요 (High-speed code: Placed in CCM, needed for interrupt handlers, etc.) */
.fastcode :
{
*(.fastcode) /* .fastcode 섹션 포함 (Include .fastcode section) */
} > CCM
/* 초기화된 데이터: SRAM1에서 실행, Flash에 저장 (Initialized data: Executed in SRAM1, stored in Flash) */
.data :
{
_sdata = .; /* .data 섹션 시작 주소 저장 (Store start address of .data section) */
*(.data) /* 모든 .data 섹션 포함 (Include all .data sections) */
_edata = .; /* .data 섹션 끝 주소 저장 (Store end address of .data section) */
} > SRAM1 AT > FLASH
/* 초기화되지 않은 데이터: SRAM1에 배치, 초기화 시 0으로 설정 (Uninitialized data: Placed in SRAM1, initialized to 0) */
.bss :
{
_sbss = .; /* .bss 섹션 시작 주소 저장 (Store start address of .bss section) */
*(.bss) /* 모든 .bss 섹션 포함 (Include all .bss sections) */
*(COMMON) /* 공용 데이터 포함 (Include common data) */
_ebss = .; /* .bss 섹션 끝 주소 저장 (Store end address of .bss section) */
} > SRAM1
/* 힙: 동적 메모리 할당, SRAM1에 4KB 할당 (Heap: Dynamic memory allocation, 4KB in SRAM1) */
.heap :
{
. = ALIGN(4); /* 4바이트 정렬 (Align to 4 bytes) */
_heap_start = .; /* 힙 시작 주소 (Heap start address) */
. += 0x1000; /* 4KB 힙 크기 (4KB heap size) */
_heap_end = .; /* 힙 끝 주소 (Heap end address) */
} > SRAM1
/* 스택: 함수 호출 및 로컬 변수, SRAM1에 8KB 할당 (Stack: Function calls and local variables, 8KB in SRAM1) */
.stack :
{
. = ALIGN(4); /* 4바이트 정렬 (Align to 4 bytes) */
_stack_start = .; /* 스택 시작 주소 (Stack start address) */
. += 0x2000; /* 8KB 스택 크기 (8KB stack size) */
_stack_end = .; /* 스택 끝 주소 (Stack end address) */
} > SRAM1
}
설명 (Description):
- 목적 (Purpose): CCM을 활용한 고속 실행 애플리케이션, 성능 최적화 (Application utilizing CCM for high-speed execution and performance optimization).
- 메모리 배치 (Memory Placement):
- 코드(.text, .rodata)는 Flash에, 고속 코드(.fastcode)는 CCM에 배치 (Code (.text, .rodata) is placed in Flash, high-speed code (.fastcode) is placed in CCM).
- 데이터(.data, .bss)는 SRAM1에 배치 (Data (.data, .bss) is placed in SRAM1).
- 스택과 힙은 SRAM1에 각각 8KB와 4KB로 할당 (Stack and heap are allocated 8KB and 4KB in SRAM1, respectively).
- 특징 (Features):
- CCM을 사용하여 인터럽트 핸들러나 자주 호출되는 함수의 실행 속도를 높입니다 (Uses CCM to improve the execution speed of interrupt handlers or frequently called functions).
- 주석이 초보자가 이해하기 쉽게 각 섹션의 용도를 설명합니다 (Comments explain the purpose of each section in a beginner-friendly way).
6. 링커 스크립트 사용 방법 (How to Use Linker Scripts)
6.1 환경 설정 (Environment Setup)
- STM32CubeIDE 설치 (Install STM32CubeIDE): STM32CubeIDE는 링커 스크립트 템플릿과 디버깅 도구를 제공합니다 (STM32CubeIDE provides Linker Script templates and debugging tools).
- 프로젝트 생성 (Create Project):
- STM32CubeIDE에서 STM32F407 타겟으로 새 프로젝트를 생성합니다 (Create a new project targeting STM32F407 in STM32CubeIDE).
- 링커 스크립트(.ld 파일)를 프로젝트 폴더에 추가합니다 (Add the Linker Script (.ld file) to the project folder).
- 프로젝트 속성 > C/C++ Build > Settings > Tool Settings > MCU GCC Linker > General에서 .ld 파일 경로를 지정합니다 (Specify the .ld file path in Project Properties > C/C++ Build > Settings > Tool Settings > MCU GCC Linker > General).
6.2 링커 스크립트 적용 (Applying Linker Scripts)
- .ld 파일을 프로젝트 폴더에 복사합니다 (Copy the .ld file to the project folder).
- STM32CubeIDE에서 빌드 설정에 .ld 파일 경로를 추가합니다 (Add the .ld file path to the build settings in STM32CubeIDE).
- 빌드 후 .map 파일을 확인하여 섹션 배치가 올바른지 점검합니다 (Check the .map file after building to verify correct section placement).
6.3 디버깅 (Debugging)
- .map 파일 분석 (Analyze .map File):
- 빌드 후 생성된 .map 파일에서 각 섹션의 주소와 크기를 확인합니다 (Check the addresses and sizes of each section in the .map file generated after building).
- 메모리 오버플로우가 발생하면 섹션 크기나 메모리 배치를 조정합니다 (If memory overflow occurs, adjust section sizes or memory placement).
- Memory View:
- STM32CubeIDE의 Memory View를 사용하여 Flash, SRAM, CCM의 내용을 확인합니다 (Use STM32CubeIDE’s Memory View to inspect the contents of Flash, SRAM, and CCM).
- 링커 에러 (Linker Errors):
- "section overflow": MEMORY 섹션의 크기를 늘리거나 SECTIONS 배치를 수정합니다 (Increase MEMORY section sizes or modify SECTIONS placement).
- "undefined symbol": Reset_Handler가 올바르게 정의되었는지 확인합니다 (Verify that Reset_Handler is correctly defined).
7. 결론 (Conclusion)
이 문서는 STM32F407의 링커 스크립트를 초보자도 이해할 수 있도록 한글과 영어로 상세히 설명하며, Flash 기반, SRAM 기반, CCM 활용 예제를 제공했습니다 (This document provides a beginner-friendly explanation of STM32F407 Linker Scripts in both Korean and English, with examples for Flash-based, SRAM-based, and CCM-utilizing applications). 상세한 주석과 보강된 설명을 통해 링커 스크립트의 역할과 작성 방법을 쉽게 이해할 수 있습니다 (Detailed comments and enhanced explanations make it easy to understand the role and writing methods of Linker Scripts). STM32CubeIDE와 레퍼런스 매뉴얼을 활용하여 초보자와 숙련된 개발자 모두 효율적으로 사용할 수 있습니다 (Both beginners and experienced developers can use it efficiently with STM32CubeIDE and reference manuals).
키워드 (Keywords): STM32, 링커 스크립트 (Linker Script), 메모리 맵 (Memory Map), Flash, SRAM, CCM, ARM Cortex-M, 섹션 배치 (Section Placement), 스택 (Stack), 힙 (Heap), STM32CubeIDE, 디버깅 (Debugging), 성능 최적화 (Performance Optimization).
'MCU > STM32' 카테고리의 다른 글
[ STM32]STM32L432KC로 Modbus RTU Slave 코드 구현: DMA와 저전력 최적화 (0) | 2025.08.13 |
---|---|
[STM32G474] 를 이용한 동일 어드레스를 갖는 64채널 I2C 디바이스 제어 (0) | 2025.08.12 |
[STM32H503RB] 로 I3C 프로토콜 구현: 초보자를 위한 상세 가이드 (0) | 2025.08.10 |