/* ============================================================================= * STM32F407VGTx_FLASH.ld - GNU ld 링커 스크립트 (ST 스타일) * * 대상: STM32F407VGT6 (Cortex-M4F) * FLASH 1024K @ 0x08000000 (코드/상수/초기화 데이터 원본) * RAM 128K @ 0x20000000 (SRAM1+SRAM2, .data/.bss/heap/stack) * CCMRAM 64K @ 0x10000000 (Core-Coupled Memory; DMA 접근 불가) * * CCMRAM 활용(중요): * CCMRAM 은 코어 전용 64K 버스로 데이터 접근 지연이 적다(코드 페치 불가, * DMA/이더넷 DMA 디스크립터/버퍼 사용 불가). 핫한 비-DMA 데이터를 두기에 좋다. * - FreeRTOS heap_4 의 ucHeap 을 CCMRAM 에 두려면 heap_4.c 가 참조하는 * 배열에 __attribute__((section(".ccmram"))) 를 부여하거나, configAPPLICATION_ * ALLOCATED_HEAP=1 로 두고 사용자 정의 ucHeap[] 를 .ccmram 에 배치한다. * - 특정 태스크 스택을 CCMRAM 에 두려면 static StackType_t 배열에 * section(".ccmram") 를 지정하고 xTaskCreateStatic() 으로 생성한다. * 주의: LwIP/ETH DMA 버퍼는 절대 CCMRAM 에 두지 말 것(이더넷 DMA 비접근). * ===========================================================================*/ /* 진입점(startup_stm32f407xx.s 의 리셋 핸들러). */ ENTRY(Reset_Handler) /* ── 스택/힙 최소 크기 (startup 어셈블리/sbrk 가 참조) ───────────────────── */ /* _estack: 메인 스택 포인터 초기값(RAM 최상단). 인터럽트/스케줄러 시작 전 사용. */ _Min_Heap_Size = 0x400; /* newlib malloc/sbrk 최소 힙 (FreeRTOS 는 자체 힙 사용) */ _Min_Stack_Size = 0x800; /* 메인/인터럽트 스택 최소 (2K) */ /* ── 메모리 영역 ─────────────────────────────────────────────────────────── */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K } /* RAM 최상단을 메인 스택 초기 포인터로 사용. */ _estack = ORIGIN(RAM) + LENGTH(RAM); /* ── 섹션 배치 ───────────────────────────────────────────────────────────── */ SECTIONS { /* 1) 인터럽트 벡터 테이블 — 플래시 선두(0x08000000). */ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) /* startup 의 벡터 테이블 (가비지 컬렉션 금지) */ . = ALIGN(4); } >FLASH /* 2) 코드 (.text). */ .text : { . = ALIGN(4); *(.text) *(.text*) *(.glue_7) /* ARM/Thumb 인터워킹 glue */ *(.glue_7t) *(.eh_frame) KEEP(*(.init)) KEEP(*(.fini)) . = ALIGN(4); _etext = .; /* 코드 끝 */ } >FLASH /* 3) 읽기 전용 데이터 (.rodata: const, 문자열, CA PEM 등). */ .rodata : { . = ALIGN(4); *(.rodata) *(.rodata*) . = ALIGN(4); } >FLASH /* ARM 예외 처리 인덱스(EHABI). nano/nosys 에서도 링크 정합성을 위해 유지. */ .ARM.extab : { . = ALIGN(4); *(.ARM.extab* .gnu.linkonce.armextab.*) . = ALIGN(4); } >FLASH .ARM : { . = ALIGN(4); __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; . = ALIGN(4); } >FLASH /* C++ / libc 초기화 배열(preinit/init/fini). startup 이 호출. */ .preinit_array : { . = ALIGN(4); PROVIDE_HIDDEN(__preinit_array_start = .); KEEP(*(.preinit_array*)) PROVIDE_HIDDEN(__preinit_array_end = .); . = ALIGN(4); } >FLASH .init_array : { . = ALIGN(4); PROVIDE_HIDDEN(__init_array_start = .); KEEP(*(SORT(.init_array.*))) KEEP(*(.init_array*)) PROVIDE_HIDDEN(__init_array_end = .); . = ALIGN(4); } >FLASH .fini_array : { . = ALIGN(4); PROVIDE_HIDDEN(__fini_array_start = .); KEEP(*(SORT(.fini_array.*))) KEEP(*(.fini_array*)) PROVIDE_HIDDEN(__fini_array_end = .); . = ALIGN(4); } >FLASH /* _sidata: 초기화 데이터(.data)의 "원본" 위치(플래시). startup 이 * _sdata.._edata 로 복사한다. */ _sidata = LOADADDR(.data); /* 4) 초기화된 데이터 (.data) — 실행 주소는 RAM, 로드 주소는 FLASH. */ .data : { . = ALIGN(4); _sdata = .; /* .data 시작 (RAM) — startup 이 참조 */ *(.data) *(.data*) *(.RamFunc) /* RAM 에서 실행해야 하는 함수(예: 플래시 프로그래밍) */ *(.RamFunc*) . = ALIGN(4); _edata = .; /* .data 끝 (RAM) */ } >RAM AT> FLASH /* 5) 초기화되지 않은 데이터 (.bss) — 0 으로 초기화(startup). */ .bss : { . = ALIGN(4); _sbss = .; /* .bss 시작 — startup 이 참조 */ __bss_start__ = _sbss; *(.bss) *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; /* .bss 끝 */ __bss_end__ = _ebss; } >RAM /* 6) 힙/스택 가드 — 최소 크기 확보(부족 시 링크 에러). */ ._user_heap_stack : { . = ALIGN(8); PROVIDE(end = .); /* newlib _sbrk 의 힙 시작(end / _end) */ PROVIDE(_end = .); . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(8); } >RAM /* 7) CCMRAM(.ccmram) — 코어 전용 64K. 비-DMA 데이터/스택 전용. * 배치 예: __attribute__((section(".ccmram"))) static uint8_t ucHeap[...]; * 초기화 필요한 .ccmram 데이터를 쓰려면 .data 처럼 별도 복사 루프가 필요하나, * 기본은 무초기화(NOLOAD) 영역으로 둔다(런타임에 명시 초기화 권장). */ .ccmram (NOLOAD) : { . = ALIGN(4); _sccmram = .; *(.ccmram) *(.ccmram*) . = ALIGN(4); _eccmram = .; } >CCMRAM /* 디버그/주석 섹션 제거(산출물 슬림화). */ /DISCARD/ : { *(.ARM.attributes) } }