XLINK를 통한 IAR 제품 내 RAM 코드 세그먼트 오버레이

기술노트 62554

아키텍처:

All

컴포넌트:

linker

업데이트:

2021-06-29 오전 4:12

개요 

본 자료에서는 동일한 RAM을 가지고 시기 별로 다른 코드를 실행하도록 하는 방법을 소개합니다. 여기서는 이를 위해 ROM 내용을 서로 다른 복수의 세그먼트로부터 동일한 RAM 상의 주소로 복사하는 방식을 사용합니다. 

ROM에서 자료를 RAM으로 복사하는 기본적인 방법에 대해서는 기술 문서 80460를 참고 하세요. 

적용 대상 

본 기술 문서는 IAR XLINK 링커를 사용하는 버전에 적용됩니다. 

기본 사항 

RAM 내에 복수의 코드 세그먼트를 오버레이 하기 위해서는 다음의 단계를 반드시 밟아야 합니다.  

  1. 이러한 각각의 “로드 유닛”을 각각 해당하는 세그먼트에 위치시킵니다. 
  2. -Q 링커 옵션을 각각의 세그먼트에 사용해서 initializer 세그먼트를 생성합니다. 
  3. 원래의 세그먼트를 RAM 상에 오버레이 합니다. 
  4. Initializer 세그먼트를 ROM 내에 위치시킵니다. 
  5. 각각의 initializer 세그먼트로부터 바이트를 사용 전 그 세그먼트로 복사합니다. 
  6. 오버레이가 되어 있는 세그먼트가 다른 오버레이 세그먼트를 참조해서는 안되므로 주의 하십시오. 

1. 세그먼트 내 컨텐츠 배치 

기술 문서 80460 참고. 

"built in" 키워드(like __ramfunc)는 대부분의 경우 자료를 둘 이상의 서로 다른 세그먼트에 투입하지는 못합니다. 이때는 아마 #pragma 방식을 사용해야 할 것입니다. 

2. initializer 세그먼트 생성 

기술 문서 80460 참고. 

-QRAMCODE1=RAMCODE1_ID
-QRAMCODE2=RAMCODE2_ID

3. RAM 내 세그먼트 오버레이 

IAR XLINK Linker는  -Z 세그먼트 배치 명령어 @에서 사용하는 배치 modifier를 지니고 있습니다. 이것은 배치 범위 내에서 이전에 배치된 자료를 무시해 버립니다. 

-Z@(DATA)CODE_A,CONST_A,DATA_A=RAM_OVERLAY_START-RAM_OVERLAY_END

-Z@ 명령어는 -Z에서 사용하는 모든 일반 규칙을 준수합니다. 단지 해당 범위에 기존에 배치된 자료를 무시할 뿐입니다. 세그먼트는 지정된 순서로, RAM_OVERLAY_START부터 순차적으로 배치됩니다. 

이어서 다음 오버레이를 동일한 주소에 배치합니다. 

-Z@(DATA)CODE_B,CONST_B,DATA_B=RAM_OVERLAY_START-RAM_OVERLAY_END 

이를 통해 지정된 *_B-세그먼트를 *_A segments 에서 사용한 동일한 주소에 배치합니다. 이것은 의도적으로 오버랩을 발생시키며, 여기서는 복수의 RAM 세그먼트들이 동일한 주소를 지니게 됩니다. 

IAR XLINK 링커에서는 이렇게 발생한 세그먼트 오버랩을 탐지하고, 이에 대한 에러를 생성합니다. 오버랩 에러는 끄거나, 경고로 바꿀 수가 있습니다. 여기서 문제는 에러를 완전히 꺼 버리게 되면 실제 오버랩도 무시되는 사태가 발생할 수가 있다는 것입니다. 에러를 경고로 전환시키면 프로그램이 링크 될 때마다 복수의 경고 메시지가 출력될 것입니다. 링커 옵션 --disable_overlap_check을 사용해 선택적으로 지정된 세그먼트 오버레이에 대한 오버레이 에러 만 끌 수도 있습니다. 

--disable_overlap_check=CODE_A,CONST_A,DATA_A,CODE_B,CONST_B,DATA_B 

… 이 코드를 사용해, 대상 세그먼트 오버랩 에러를 끌 수가 있습니다. 이 코드를 사용하면 관련 세그먼트의 에러를 끕니다. 그러나, 이는 대상 세그먼트 범위 내의 다른 세그먼트와 오버랩 될 때에만 그렇습니다. CODE_A와 다른 세그먼트(다른 --disable_overlap_check 옵션 상에 수록 여부 불문) 간의 오버랩은 그래도 계속 보고가 될 것입니다. 

4. Initializer 세그먼트를 ROM 내에 위치시킵니다. 

기술 문서 80460 참고. 

-Z(CONST)CODE_A_ID,CONST_A_ID=ROMSTART-ROMEND 
-Z(CONST)CODE_B_ID,CONST_B_ID=ROMSTART-ROMEND 

5. initializer 세그먼트로부터 바이트를 대상 세그먼트로 복사합니다. 

기술 문서 80460 참고. 

6. 오버레이 된 세그먼트 참조를 확인합니다. 

오버레이가 된 RAMCODE 세그먼트는 단일 RAMCODE 세그먼트와 비교하여 좀 더 복잡합니다. 이들은 가장 중요한 측면입니다. 

  • 오버레이 된 세그먼트는 동시에는 절대로 사용할 수가 없으며, 각각의 세그먼트를 대상으로 참조하는 것은 세그먼트가 “활성화”(active) 되어 있는 상태에서만 가능합니다. 이를 실제로 실행할 지의 여부는 사용자의 재량입니다. 컴파일러나 링크 상에서 이를 탐지해 낼 수 있는 기능은 지원되지 않고 있습니다. 활성화 되어 있지 않은 세그먼트를 참조하는 경우, 정의되지 않은 반응(undefined behavior)으로 이어질 수 있습니다. 
  • 하나의 오버레이 세그먼트는 오버레이 된 다른 세그먼트 내의 자료를 절대 참조할 수가 없습니다. 왜냐하면, 이들은 절대 동시에 활성화 될 수가 없기 때문입니다. 현재로서는 컴파일러도, 링커도 이러한 참조는 탐지해 내지 못합니다. 두 개의 RAMCODE 세그먼트가 동시에 활성화되는 오버레이 상황을 만드는 것이 불가능하지는 않습니다(예: 하나는   0x2000-0x23FF 나머지 하나는 0x2400-2FFF 상에 위치하며 다른 서그먼트들은 0x2000-0x2FFF 상에 위치하는 경우. -- 이 경우 둘은 서로 오버레이가 되지 않습니다.) 그러나 이러한 기법의 처리는 모두 프로그래머가 직접 해야 합니다. 
  • RAM 구역의 디버그 정보는 평상시에 미치지 못하게 되는데, 그 이유는 RAM 중에 일부분이 디버그 정보로 포화(동일 주소에 저장되어 있는 모든 세그먼트에 하나의 디버그 정보 세트 만이 할당) 되어 있으며, 디버거에 상당한 혼란이 발생해 정확한 함수를 제시하지 못할 수가 있기 때문입니다. 코드는 예상대로 작동할 터이지만, 어셈블리를 제외한 그 어느 단계에서도 디버깅이 쉽지는 않게 됩니다. 
  • 만일 코드의 구조 상 각각의 “로드 유닛”이 별도의 파일 상에 위치하는 경우 디버그 정보 없이도 모듈을 컴파일 할 수가 있습니다. 디버그 하고자 하는 로드 유닛을 포함하고 있는 모듈 만이 디버그 정보를 포함하고 있는 경우, 디버거가 더 나은 성능을 발휘할 수가 있습니다. 
  • 만일에 충분한 RAM 공간이 있다고 한다면, 디버그 하고자 하는 로드 유닛을 그 자체의 메모리 공간에 배치하는 방법도 생각할 수가 있습니다. 그렇게 함으로써 일반적인 디버그 정보를 얻을 수가 있습니다. 

 

모든 제품 이름은 해당 소유자의 상표 또는 등록 상표입니다.

죄송하지만, 당사 사이트에서는 Internet Explorer를 지원하지 않습니다.보다 편안한 사이트를 위해 Chrome, Edge, Firefox 등과 같은 최신 브라우저를 사용해 주시길 부탁드립니다.