뭐라도 만들어보자!!( 프로젝트 )/임베디드

2. 임베디드 실습 : ldscript 작성

잡학다식을꿈꾼다 2024. 1. 21. 15:35
반응형

 컴파일한 오브젝트 파일들은 대부분 바로 실행할 수 있는 형태가 아니다. 오브젝트 파일들을 그룹 짓고, 심볼 간 의존성을 해결해야 하는데, 이러한 작업을 링킹(Linking)이라고 한다.

 링커 스크립트는 타깃에서의 메모리 섹션의 서술을 담은 파일이다. 링커가 플래시의 올바른 위치에 심볼을 위치시키고, 코드가 참조할 수 있는 메모리 매핑 영역의 특수위치에 대해 소프트웨어 구성요소에 지시하기 위해 사전에 알고 있어야하는 정보이다. 스크립트는 C 코드와 상호작용할 수 있고, 스크립트에 의해 정의된 심볼을 내보낼 수 있다.

 다음은 실습에 사용할 스크립트 파일의 내용이다.

 

MEMORY
{
    FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K
    RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
}

ENTRY(isr_reset)

SECTIONS
{
    .text :
    {
        _start_text = .;
        KEEP(*(.isr_vector))
        *(.text*)
        *(.rodata*)
        . = ALIGN(4);
        _end_text = .;
    } > FLASH

    _stored_data = .;

    .data : AT (_stored_data)
    {
        _start_data = .;
        *(.data*)
        . = ALIGN(4);
        _end_data = .;
    } > RAM

    .bss :
    {
        _start_bss = .;
        *(.bss*)
        *(COMMON)
        . = ALIGN(4);
        _end_bss = .;
        _end = .;
    } > RAM

}

PROVIDE(_start_heap = _end);
PROVIDE(_end_stack  = ORIGIN(RAM) + LENGTH(RAM));

 

 위에서부터 설명할 생각이다. 

 

MEMORY
{
    FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K
    RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
}

 

 이 부분은 시스템에서 두 메모리 영역이 사용되고 있음을 서술하고 있다. 첫번 째 부분은 FLASH 영역으로, 총 128K Byte만큼 사용할려고 하며, 읽기와 실행이 가능하다는 것을 명시하고 있으며, 시작 주소는 0x800 0000 이다. 두 번째 영역은 RAM 영역으로 총 20K Byte만큼 사용할려고 하며, 시작주소는 0x2000 0000이다. 시작 주소와 최대로 할당할 수 있는 메모리 크기는 데이터시트를 보고 참조해야 한다. (참조해야 하는 데이터 시트는 올려 두겠다.)

 FLASH 영역에는 명령어에 해당하는 코드들이 위치하게 된다. 프로그램이 실행되는 와중에 이 영역은 데이터가 변경되어야 하는 일이 없어야 한다. 반면 RAM 영역은 실제 프로그램이 실행되면서 사용되는 영역으로 읽기, 쓰기, 실행이 모두 가능해야 한다. 

cortex-m3 programming reference

 그 밑으로 가보자. 

ENTRY(isr_reset) //프로그램이 실행될 때 제일먼저 isr_reset 함수가 실행된다!!

SECTIONS
{
    .text :
    {
        _start_text = .; //_start_text에 현재 출력 위치 카운터 저장(정수형태)
        KEEP(*(.isr_vector))  //_start_text에 현재 출력 위치 카운터 저장(정수형태)
        *(.text*)	// .text~ 이로 정의된 모든 섹션들을 넣어라
        *(.rodata*)	// .rodata~ 이로 정의된 모든 섹션들을 넣어라
        . = ALIGN(4); //ALIGN() : exp 바운더리에 정렬된 현재 위치 카운터를 반환
        								마이크로 컨트롤러가 word 단위(4byte)로 메모리를 입출력하기 때문에 사용
        _end_text = .;	//_end_text에 현재 출력 위치 카운터 저장(정수형태)
    } > FLASH //FLASH 영역에 .text 저장

	//밑에 내용은 위의 주석 참고

    _stored_data = .; //_stored_text에 현재 출력 위치 카운터 저장(정수형태)

    .data : AT (_stored_data) //AT : LMA(Loade Memory Address) :  링커에 의해 실행 파일이 만들어질 때 결정되는 주소
    					// VMA(Virtual Memory Address) : 프로그램이 돌아가면서 참조하게 되는 주소
                         // AT 명령어를 사용하여 LMA를 명확하게 지정해준다.(즉 LMA 상으로는 .text 바로 다음에 위치해 있을 것)
                        // LMA에 있는 데이터 섹션을 VMA 영역에 복사해줄 필요가 있다!! 
    {
        _start_data = .; 
        *(.data*)
        . = ALIGN(4);
        _end_data = .; 
    } > RAM

    .bss :
    {
        _start_bss = .;
        *(.bss*)
        *(COMMON) //어디에도 초기화 되지 않은 데이터
        . = ALIGN(4);
        _end_bss = .;
        _end = .;
    } > RAM

}

 

 메모리 섹션에 대해서 정의를 해주었으니 각 섹션에 어떤 영역들이 저장되어야 하는지 명시를 해주어야 한다. 그 전에 앞서서 프로세스 메모리 영역이 어떻게 구성되어 있는 지 알아야한다.

 

 

  • text : 사용자가 작성한 프로그램 함수, 명령어 등이 저장됨
  • data : 프로그램이 사용하는 데이터 공간, 전역변수, static 변수 등이 저장
  • bss : 변수가 할당되었음에도 아직 초기화되지 않은 변수들이 저장되는 영역
  • heap : 프로그래머가 필요할 때 사용하는 공간
  • stack : 호출된 함수의 수행을 마치고 복귀할 주소, 데이터를 임시로 저장하는 영역

 text 영역은 FLASH 섹션에, data, bss 영역은 RAM 섹션에 할당되어야 한다. 각 섹션에 들어갈 내용을 채우는 방식은 배열과 비슷하다. 먼저 오는 부분이 주소 상 앞쪽에 위치하게 된다.  ldscript의 내용은 주석을 참고하기 바란다. 더 자세하게 알고 싶다면 다음의 문서를 확인하기를 바란다.

 

http://korea.gnu.org/manual/release/ld/ld-sjp/ld-ko_3.html

 

GNU 링커, LD 사용하기 - 명령 언어(Command Language)

Go to the first, previous, next, last section, table of contents. 명령 언어는 링크 프로세스에 대한 명시적인 제어를 제공한다. 링커의 입력 파일들과 출력 사이의 완전한 맵핑 스펙을 지원한다. 이것은 다음

korea.gnu.org

 

PROVIDE(_start_heap = _end);
PROVIDE(_end_stack  = ORIGIN(RAM) + LENGTH(RAM));

 

 마지막으로 힙과 스택에 대한 내용이다. PROVIDE는 링크에 포함된 어떠한 오브젝트에서도 정의가 되지 않았을 때, 심볼을 정의하는 방식이다. 여기서는 힙의 시작과 스택의 끝을 정의하고 있다. 스택의 경우 시작 주소가 아닌 끝 주소를 정의하고 있는데, 그 이유는 스택이 큰 주소에서 작은 주소로 데이터를 저장하기 때문이다. 

 

 이번 글에서 링커 스크립트를 작성해 보았다. 링커 스크립트 파일은 일종의 설계도면으로 프로그램이 어떻게 구성되어 있는지, 실행될 때는 어느영역을 참조해야하는 지 등의 내용을 담고 있다. 링커 스크립트를 작성해봄으로써 이제 실습에 첫 걸을 떼었다고 봐도 무방할 것이다. 다음 글에서는 진짜로 main 함수를 호출해볼려고 한다!!

cortex-m3 programming manual.pdf
2.00MB
stm32f reference manual.pdf
12.51MB

반응형