본문 바로가기
DSP, MCU/TMS320F2838x (C28x)

TMS320F28388D ] 라이브러리 램에 복사해 실행

by eteo 2023. 4. 22.

 

Flash API 라이브러리를 램에 올려서 실행할 필요가 있다. 단순히 time critical 코드를 고속으로 사용하려는 것 뿐만은 아니고 예를 들어 부트로더를 만들 때 필요하다.

 

Application이 코드영역에서 한창 동작하고 있는데 이 코드영역을 중간에 erase하려고 하면 프로그램이 halt될 것이 아닌가.

하지만 전부 Ram에서 동작하는 함수를 사용하면 코드영역을 침범해 조작해도 halt 되지 않는다. 근데 Flash API를 호출해서 사용하는 copyData()라는 사용자정의 함수가 있다고 하면 이걸 Ram에 올린다고 다 되는 게 아니라, 그 안에 있는 모든 함수들이 램에서 동작해야하고 사용하는 버퍼도 램에 올라간 데이터여야 한다.

 

아래와 같은 과정을 거치지 않고 Flahs API를 사용한다면 breakpoint를 찍고 호출 스택을 확인했을 때 Flash주소가 찍힌것을 볼 수 있을 것이다.

 

 

 

첫번째 방법

 

SECTIONS
{
// ...
    GROUP
    {
        .TI.ramfunc
        { -l F2838x_CM_FlashAPI.lib}

    }  LOAD = CMBANK0_SECTOR0,
       RUN = C0RAM,
       LOAD_START(RamfuncsLoadStart),
       LOAD_SIZE(RamfuncsLoadSize),
       LOAD_END(RamfuncsLoadEnd),
       RUN_START(RamfuncsRunStart),
       RUN_SIZE(RamfuncsRunSize),
       RUN_END(RamfuncsRunEnd),
       ALIGN(16)
// ...
}

 

가장 간단한 방법이다. .cmd 파일 sections 영역에 다음과 같이 쓴다.

이렇게 링커 커맨드를 내리고, 명시적으로 Flash에 로드된 것을 Ram에 복사하는 코드가 필요한데 .TI.ramfunc 은 범용적으로 쓰기 위해 TI가 만들어둔 섹션이라서 이미 Device_init() 안에서 그렇게 하고 있다.

마지막에 ALIGN(16)한거는 CM코어라서 그렇고 C28x코어는 ALIGN(8) 해야한다.

 

 

 

 

 

두번째 방법

 

SECTIONS
{
// ...
	flashapi
    {
       --library=F2838x_CM_FlashAPI.lib(.text)
    } LOAD = CMBANK0_SECTOR0,
                     RUN = C0RAM,
                     LOAD_START(flashapiLoadStart),
                     LOAD_SIZE(flashapiLoadSize),
                     LOAD_END(flashapiLoadEnd),
                     RUN_START(flashapiRunStart),
                     RUN_SIZE(flashapiRunSize),
                     RUN_END(flashapiRunEnd),
                     ALIGN(16)

// ...
}

 

extern uint16_t flashapiLoadStart;
extern uint16_t flashapiLoadEnd;
extern uint16_t flashapiLoadSize;
extern uint16_t flashapiRunStart;
extern uint16_t flashapiRunEnd;
extern uint16_t flashapiRunSize;

// ...

memcpy(&flashapiRunStart, &flashapiLoadStart, (size_t)&flashapiLoadSize);

Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, DEVICE_FLASH_WAITSTATES);

 

.cmd 파일에 새로운 섹션을 추가하고 Device_init() 함수에서 Flash_initModule() 하기전에 해당 섹션을 램으로 복사하는 memcpy()를 호출해준다.

 

 

 

 

 

 

 

 

 

만약 라이브러리를 통째로 올리기엔 램 공간이 부족해 부담된다면 .map 파일을 확인해 특정 .obj 파일만 복사해 램에서 실행하는 방법도 있다.

 

SECTIONS
{
// ...
	flashapi
    {
       F2838x_CM_FlashAPI.lib<FlashStateMachine.obj>(.text)
       F2838x_CM_FlashAPI.lib<Program.obj>(.text)
       F2838x_CM_FlashAPI.lib<Read.obj>(.text)
    } LOAD = CMBANK0_SECTOR0,
                     RUN = C0RAM,
                     LOAD_START(flashapiLoadStart),
                     LOAD_SIZE(flashapiLoadSize),
                     LOAD_END(flashapiLoadEnd),
                     RUN_START(flashapiRunStart),
                     RUN_SIZE(flashapiRunSize),
                     RUN_END(flashapiRunEnd),
                     ALIGN(16)

// ...
}

 

 

 

 

 

 

링커 커맨드 파일 작성 방법은 아래 문서에서 자세히 볼 수 있다.

 

https://downloads.ti.com/ccs/esd/documents/sdto_cgt_Linker-Command-File-Primer.html

 

TI Linker Command File Primer

 

downloads.ti.com