임베디드/임베디드 레시피

Scatter Loading 주의점, heap 및 stack

twoweeks-within 2024. 12. 2. 11:26



1)
 우리 나름대로의 Stack과 Heap을 사용하게됨
  > 자동으로 Compiler가 만들어주는 Stack과 Heap은 안씀

"그런데, 우리가 만들어낸 image의 ZI에 포함되지 않는 여기서의 Stack과 Heap은 도대체 뭐냐! 
 Default Memory model > RO, RW, ZI : Application 하나 올린것
<> Embedded OS (또는 Kernel)같은 복잡한 것이 porting되지 않았음
    > Application이 사용하는 Stack과 Standard Library가 사용하는 (malloc같은) Heap인것
     >  Compiler가 알아서 Stack과 Heap영역을 만들어줌

/*
스택(stack) 영역
함수의 호출과 관계되는 지역 변수와 매개변수가 저장되는 영역
 > 함수 종료시 소멸
 푸시(push) > 데이터 저장, 팝(pop) 동작 > 데이터 인출
후입선출(LIFO, Last-In First-Out) > 늦게 저장된게 가장 먼저 인출 
스택 영역은 메모리의 높은 주소에서 낮은 주소의 방향으로 할당 // 아래에서 위로

힙(heap) 영역
사용자가 직접 관리할 수 있는 ‘그리고 해야만 하는’ 메모리 영역
 > 동적 할당되고 해제됩니다.
 선입선출(FIFO) 낮은 주소에서 높은 주소의 방향으로 할당됩니다. // 위에서 아래로
*/

ScatterLoading > compiler가 만드는 몇개의 symbol 무시 .

Image$$RW$$Base
Image$$RW$$Limit
Image$$RO$$Base
Image$$RO$$Limit
Image$$ZI$$Base
Image$$ZI$$Limit

> Generation X 
    >  because ) Scatter Loading에서 이미 명시한 Region에 대한 RW, RO, ZI의 Base, Limit을 만들어 내므로
ex)
Scatterloading 사용 X > stack과 heap이 자동으로 정해짐

scatterloading 사용x 자동으로 stack heap 정해짐

 

 Compiler 가 자동으로 Stack, Heap  만들어 낼 때 > 자기가 만든 Symbol 참조 

   >  Image$$ZI$$Base, Image$$ZI$$Limit  >  Stack, Heap만들어냄

// Base : 낮은주소 > 높은주소 :: HEAP

// Limit : 높은주소 > 낮은주소 :: STACK

 

ZI영역 더 위쪽에 Stack과 Heap을 임의로 만들어냄

    > rt_entry에 진입 >  C Library안에 __user_initial_stackheap()이라는 함수에서 처리

 

Image$$ZI$$Base(Limit) Symbol이 없음 > Linker : 마지막에 Link Error

 

이럴땐 > 우리가 __user_initial_stackheap()라는 함수를 재정의 해줘야함

//  Bootup중에 꼭 들리는 함수

__userInitial_stackheap() 함수의 원형 

------------------------------------------------------------------------------------------------------------

#include
__value_in_regs struct __initial_stackheap

__user_initial_stackheap (unsigned R0, unsigned SP, unsigned R2, unsigned SL)

------------------------------------------------------------------------------------------------------------

보통 Scatter loading을 사용하고, RTOS를 사용하는 경우에는 

-----------------------------------------------------------------------------------------------------------

__value_in_regs struct __initial_stackheap

__user_initial_stackheap(unsigned R0, unsigned SP, unsigned R2, unsigned SL)
{
     return;
}

-----------------------------------------------------------------------------------------------------------

 initial stack과 heap을 만들어 주고 싶으면,

-----------------------------------------------------------------------------------------------------------

char _initial_heap[0x2000];
char _initial_stack[0x2000];

__value_in_regs struct __initial_stackheap

__user_initial_stackheap(unsigned r0, unsigned sp, unsigned r2, unsigned sl)
{
    struct __initial_stackheap config;

    config.heap_base = (unsigned)_initial_heap;     // 0x1000
    config.stack_base = (unsigned)_initial_stack + sizeof(_initial_stack) - 1;  0x1400
    config.heap_limit = (unsigned)_initial_heap + sizeof(_initial_heap) - 1; 0x1399
    config.stack_limit = (unsigned)_initial_stack; 0x 1400
    return config;
}

 

// heap : 낮 > 높

   : 낮은 주소 일수록 더 먼저 저장됨 > 흔히 알던 방식

// stack : 높 > 낮

    : 높은 주소 일수록 더 먼저 저장됨

      > limit 가 기준으로 stack 공간만큼 더한것 = base

-----------------------------------------------------------------------------------------------------------

 config라는 구조체에 값을 넣어주면 lib이 알아서 init을 해줌

     >  lib과의 통신을 위해서 정해져 있는 형식임



 

'임베디드 > 임베디드 레시피' 카테고리의 다른 글

Pointer  (0) 2024.12.04
Context와 AAPCS  (0) 2024.12.03
Reset Handler에서 main까지 (Entry Point)  (0) 2024.12.01
Coprocessor Assembly  (0) 2024.11.27
SWI 의 진실  (0) 2024.11.26