Flash나 ROM으로 부터 복사한뒤 RAM에서 실행하기

기술노트 11578

아키텍처:

Arm, Renesas Synergy

컴포넌트:

general

업데이트:

2021-05-26 오전 4:16

소개

본 기술 노트는 RAM에서 응용프로그램을 최대한 많이 실행하는 방법에 대해 기술합니다.

Cortex-M 장비의 M3부터 상위버전에 적용할 수 있습니다.

RAM에서 IAR Development Guide for ArmRunning all code from RAM섹션에서 설명된 방법이 예상한 범위 내에서 프로그램을 RAM에 배치하지 않는 경우 본 가이드라인을 사용하세요.

논의

사용자 가이드의 Running all code from RAM 섹션의 방법을 따르세요.

IAR Development Guide for Arm에서 해당 섹션을 찾을 수 있습니다. 프로그램이 RAM에 충분히 배치되지 않은 경우 아래 제안사항을 읽어보시기 바랍니다.

최대한 많은 코드를 RAM에 배치

IAR 도구들은 프로그램이 시작될 때 최대한 많은 코드를 RAM에 복사할 수 있도록 돕습니다.

이렇게 하십시오:

  • .icf 파일을 수정하여, RAM에 복사를 활성화 한다.
  • 저 수준 소스코드를 수정하여, RAM에 2차 vector 테이블을 위치시키고 생성합니다.
  • 프로그램 소스코드를 수정하여, RAM의 vector 테이블을 가리킬 수 있도록 VTOR를 설정합니다.
  • [선택] RAM의 vector 테이블에 link-time protection을 추가합니다.

STM32F103RB(Cortex-M3) 장비를 위한 프로젝트를 통해 더 자세히 알 수 있습니다. STM32F103RB (Cortex-M3) example project IAR Embedded Workbench for ARM 8.32.1.

이 예제는 어셈블리어로 쓰여진 저수준 코드를 담고 있습니다. C로 다루기 위해선, C로 작성된 이 예제 본문을 참고하세요.

.icf파일을 수정하여, RAM에 복사를 활성화 한다.

  1. 프로젝트에 사용할 .icf 파일을 복사한다.
  2. Project>Options>Linker>Config 을 선택 후 기본으로 지정된 파일 대신 복사본을 지정한다.

Running all code from RAM 섹션에 기술한 대로 변경한다:

initialize by copy { readonly, readwrite };

.icf 파일을 변경한다.:

  • RAM vector 테이블이 들어갈 수 있도록 RAM region 시작 부분을 변경한다:
define symbol __ICFEDIT_region_RAM_start__ = 0x200000EC;
  • RAM vector 테이블의 시작 주소를 위해 심볼을 추가한다:
define symbol __RAM_intvec_start = 0x20000000;
  • RAM vector 테이블을 보관할 섹션을 배치한다:
place at address mem: __RAM_intvec_start { section .intvec_RAM };

RAM에 2차 vector 테이블을 위치시키고 생성합니다.

  1. vector 테이블을 담고있는 파일의 복사한다.
  2. 복사본을 프로젝트에 추가한다.

소스 파일 복사본에 다음의 변경사항을 수정한다:

  • 복사된 vector 테이블의 이름을 수정한다:
__vector_RAM_table
  • RAM 상의 vector 테이블 (__vector_RAM_table)은 인터럽트 핸들러들에 대한 참조를 포함합니다. (RAM 상의 vector 테이블은 원본 vector 테이블의 복사본이기 때문에, 테이블 자체를 수정할 필요가 없습니다)
  • C에서 RAM vector 테이블은 다음과 같습니다:
__root const IntVector __vector_RAM_table[] =
   {__ptr = __sfe( ‘CSTACK’ ) },
   __iar_program_start,
   NMI_Handler,
   HardFault_Handler,
   . . .
  • RAM vector 테이블을  .intvec_RAM섹션에 위치시킵니다.
  • RAM vector 테이블에 다음의 #pragma 라인을 추가합니다:
#pragma location = ".intvec_RAM"
__root const IntVector __vector_RAM_table[] =
. . .
  • ROM vector 테이블은 반드시 수정되어야 합니다.
  • __ptr = __sfe( ‘CSTACK’ ) 혹은 __iar_program_start 를 수정하면 안됩니다.
  • 다른 모든 테이블 항목은 Empty_Handler.라고 명명된 더미 핸들러를 참조해야 합니다.
  • ROM vector 테이블은 다음과 같습니다:
const IntVector __vector_table[] =
    {__ptr = __sfe( ‘CSTACK’ ) },
    __iar_program_start,
    Empty_Handler,
    Empty_Handler,
    Empty_Handler,
    Empty_Handler,
    . . .
  • 더미 Empty_Handler를 위해 다음처럼 소스를 작성하세요:
void Empty_Handler(void)
  {
    for(;;);
  }

RAM의 vector 테이블을 가리킬 수 있도록 VTOR 를 설정.

프로그램이 VTOR가 설정되어 있는 소스코드를 이미 포함하고 있다면, 그 코드를 수정해야 합니다. 아니면, 아래의 수정 부분을 프로그램 소스 코드 최상단에 포함시키시기 바랍니다. (최소한 인터럽트가 활성화되는 부분 위에)

  #pragma section = ".intvec_RAM"
  SCB->VTOR = (uint32_t)__section_begin(".intvec_RAM");

[선택] RAM의 vector 테이블에 link-time protection을 추가합니다.

RAM vector 테이블이 연결된 출력 이미지에 포함되어 있는지 확인하려면 다음을 수행합니다:

  • 다음의 코드 두 줄을 main() 함수의 정의부 이전에 추가합니다.
  extern void * __vector_RAM_table [];
  #pragma required=__vector_RAM_table
  void main(void)

주의 : 만일 본 기술 노트에서 언급한 [선택] 사항이 아닌 방법을 수행하지 않으면 ILINK 링커는 Li005 에러를 발생시킵니다.

.map 파일을 사용하여 수정사항에 대한 영향을 점검

.map 파일 내의 다음의 섹션을 점검합니다:

  • PLACEMENT SUMMARY ­– 어떤 메모리 객체가 배치되어 있는지 검사
  • MODULE SUMMARY ­– 객체의 배치를 검사 (r-o code vs r/w code)
  • ENTRY LIST ­– 함수들의 주소를 확인

MODULE SUMMARY 는 변경된 결과를 표시합니다.

원래 프로젝트의 MODULE SUMMARY 와:

  2 256 bytes of readonly  code memory
      0 bytes of readwrite code memory
     16 bytes of readonly  data memory
  2 052 bytes of readwrite data memory

수정된 프로젝트의 MODULE SUMMARY 를 비교:

    792 bytes of readonly  code memory
  1 808 bytes of readwrite code memory
  1 253 bytes of readonly  data memory
  2 054 bytes of readwrite data memory

주의! 스타트업 코드의 링커 보호

The linker protects sections that are referenced from the startup code from being affected by an initialize by copy directive. This includes:

링커는 스타트업 코드로 부터 참조되는 섹션이 initialize by copy 지시문에 의해 초기화의 영향을 받지 않고록 보호합니다. 이는 다음을 포함합니다:

  • __low_level_init 및 동일한 컴파일 단위(.c 파일)에서 호출 및/또는 정의된 모든 함수.
  • 글로벌 (정적으로 링크된) C/C++ 심볼

링커는 복사 초기화가 완료된 후 실행되는 코드만 RAM에 복사되도록 보장합니다. 따라서 초기화 명령에서는 읽기 전용을 추가하는 것이 안전합니다:

initialize by copy { readonly, readwrite };

결론

본 기술 노트에서 제시된 내용은 ROM에서 실행되고 있는 코드의 양을 최소화 합니다.

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

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