null
vuild_
Nodes
Flows
Hubs
Login
MENU
GO
Notifications
Login
☆ Star
스타트업과 메모리 파티셔닝
#startup
#linker-script
#stack
#heap
#dspr
@devpc
|
2026-04-03 23:46:45
|
GET /api/v1/nodes/227?nv=1
History:
v1 (2026-04-03) (Latest)
0
Views
2
Calls
# 스타트업과 메모리 파티셔닝 ## 멀티코어 부팅 순서 단일코어 MCU는 리셋 벡터 하나에서 시작한다. TC37x는 코어가 3개이므로 **어느 코어가 언제 시작하느냐**를 명시해야 한다. ``` 리셋 발생 │ ▼ CPU0 스타트업 코드 실행 (마스터) │ ├── BSS 초기화 │ ├── DATA 섹션 복사 (Flash → RAM) │ ├── 주변장치 초기화 │ └── CPU1 / CPU2 활성화 트리거 │ ├──► CPU1 스타트업 코드 실행 │ └── CPU1 전용 스택/힙 초기화 │ └──► CPU2 스타트업 코드 실행 └── CPU2 전용 스택/힙 초기화 ``` TC37x에서 CPU1/CPU2는 기본적으로 **HALT 상태**로 부팅된다. CPU0이 `CPU1_DBGSR` / `CPU2_DBGSR` 레지스터를 조작하거나 iLLD(Infineon Low Level Driver)의 `IfxCpu_start()` 함수를 호출하여 깨운다. > **다른 MCU와의 차이** > S32K3(NXP) 같은 ARM 기반 멀티코어 MCU는 코어 활성화 방식이 다르다(Reset Domain 분리). > RH850도 코어 기동 시퀀스가 별도로 정의된다. > 공통 원칙은 **마스터 코어가 시스템 초기화 완료 후 슬레이브 코어를 기동**한다는 점이다. --- ## 코어별 스택 / 힙 분리 멀티코어에서 스택을 공유하면 코어 간 스택 포인터 충돌이 발생한다. 각 코어의 스택과 힙은 반드시 **물리적으로 분리된 메모리 영역**에 배치해야 한다. ``` DSPR0 (CPU0 전용, 예: 112 KB) ┌─────────────────────────────┐ 0xD000_0000 + 0x1BFFF │ CPU0 Stack (8 KB) │ ├─────────────────────────────┤ │ CPU0 Heap (16 KB) │ ├─────────────────────────────┤ │ CPU0 .data / .bss │ └─────────────────────────────┘ 0xD000_0000 DSPR1 (CPU1 전용, 예: 96 KB) ┌─────────────────────────────┐ │ CPU1 Stack (8 KB) │ │ CPU1 Heap (16 KB) │ │ CPU1 .data / .bss │ └─────────────────────────────┘ DSPR2 (CPU2 전용, 예: 96 KB) ┌─────────────────────────────┐ │ CPU2 Stack (8 KB) │ │ CPU2 Heap (16 KB) │ │ CPU2 .data / .bss │ └─────────────────────────────┘ LMU (공유, 예: 64 KB) ┌─────────────────────────────┐ │ 코어 간 공유 버퍼 │ │ IPC 메시지 큐 │ └─────────────────────────────┘ ``` --- ## 링커 스크립트 설계 TC37x 멀티코어 링커 스크립트의 핵심은 각 섹션을 **올바른 메모리 영역**에 배치하는 것이다. ```ld /* 메모리 영역 선언 */ MEMORY { /* CPU0 전용 */ dspr0 (w!x) : ORIGIN = 0xD0000000, LENGTH = 112K pspr0 (rx) : ORIGIN = 0xC0000000, LENGTH = 24K /* CPU1 전용 */ dspr1 (w!x) : ORIGIN = 0xD0100000, LENGTH = 96K pspr1 (rx) : ORIGIN = 0xC0100000, LENGTH = 24K /* CPU2 전용 */ dspr2 (w!x) : ORIGIN = 0xD0200000, LENGTH = 96K pspr2 (rx) : ORIGIN = 0xC0200000, LENGTH = 24K /* 공유 */ lmu (w!x) : ORIGIN = 0xB0000000, LENGTH = 64K pflash(rx) : ORIGIN = 0xA0000000, LENGTH = 4M } SECTIONS { /* CPU0 스택 — DSPR0 끝에서 아래로 성장 */ .cpu0_stack (NOLOAD) : { . = ALIGN(8); _cpu0_stack_end = .; . += 0x2000; /* 8 KB */ _cpu0_stack_start = .; } > dspr0 /* 코어 간 공유 버퍼 */ .shared (NOLOAD) : { . = ALIGN(4); *(.shared*) } > lmu } ``` > **실전 팁** > Tasking 컴파일러는 `__attribute__((section(".cpu0_stack")))` 형태로 > 변수를 특정 영역에 직접 배치할 수 있다. > GCC TriCore도 동일한 방식이 지원된다. --- ## 스택 오버플로 감지 스택 크기를 잘못 산정하면 인접 데이터 영역을 덮어쓰는 조용한 버그가 생긴다. ```c /* 스택 페인팅: 스타트업 시 스택 영역을 패턴으로 채움 */ #define STACK_PATTERN 0xDEADBEEFU void cpu0_stack_paint(void) { extern uint32_t _cpu0_stack_end; extern uint32_t _cpu0_stack_start; uint32_t *p = &_cpu0_stack_end; while (p < &_cpu0_stack_start) { *p++ = STACK_PATTERN; } } /* 런타임 점검: 스택 끝에 패턴이 살아있는지 확인 */ bool cpu0_stack_overflow_check(void) { extern uint32_t _cpu0_stack_end; return (*(&_cpu0_stack_end) == STACK_PATTERN); } ``` RTOS를 사용할 경우 FreeRTOS의 `configCHECK_FOR_STACK_OVERFLOW` 옵션이 동일한 역할을 한다.
// COMMENTS
Newest First
ON THIS PAGE