[TI TMS320F2837D] DSP SDRAM 사용하기

2022. 7. 8. 20:40프로젝트 로그/TI C2000 Firmware Update via CAN

반응형

EMIF Init 함수

void DSP_EMIF_INIT(void)
{
    EMIF_SyncConfig sdConfig;
    EMIF_SyncTimingParams tParam;
    EMIF_AsyncTimingParams tparam;

    setup_emif1_pinmux_async_16bit(GPIO_MUX_CPU1);
    setup_emif1_pinmux_sdram_16bit(GPIO_MUX_CPU1);

    // Configure to run EMIF1 on half Rate. (EMIF1CLK = CPU1SYSCLK/2)
    SysCtl_setEMIF1ClockDivider(SYSCTL_EMIF1CLK_DIV_2);

    // Grab EMIF1 For CPU1.
    EMIF_selectMaster(EMIF1CONFIG_BASE, EMIF_MASTER_CPU1_G);

    // Disable Access Protection. (CPU_FETCH/CPU_WR/DMA_WR)
    EMIF_setAccessProtection(EMIF1CONFIG_BASE, 0x0);

    // Commit the configuration related to protection. Till this bit remains set content of EMIF1ACCPROT0 register can't be changed.
    EMIF_commitAccessConfig(EMIF1CONFIG_BASE);

    // Lock the configuration so that EMIF1COMMIT register can't be changed any more.
    EMIF_lockAccessConfig(EMIF1CONFIG_BASE);

    // Configure SDRAM control registers. Needs to be
    // programmed based on SDRAM Data-Sheet. For this example:
    // T_RFC = 60ns = 0x6; T_RP  = 18ns = 0x1;
    // T_RCD = 18ns = 0x1; T_WR  = 1CLK + 6 ns = 0x1;
    // T_RAS = 42ns = 0x4; T_RC  = 60ns = 0x6;
    // T_RRD = 12ns = 0x1.
    tParam.tRfc = 0x1FU;
    tParam.tRp = 0x7U;
    tParam.tRcd = 0x7U;
    tParam.tWr = 0x7U;
    tParam.tRas = 0xFU;
    tParam.tRc = 0xFU;
    tParam.tRrd = 0x7U;

    EMIF_setSyncTimingParams(EMIF1_BASE, &tParam);

    // Configure Self Refresh exit timing.
    // Txsr = 70ns = 0x7.
    EMIF_setSyncSelfRefreshExitTmng(EMIF1_BASE, 0x7U);

    // Configure Refresh Rate.
    // Tref = 64ms for 8192 ROW, RR = 64000*100(Tfrq)/8192 = 781.25 (0x30E).
    EMIF_setSyncRefreshRate(EMIF1_BASE, 781);

    sdConfig.casLatency = EMIF_SYNC_CAS_LAT_2;
    sdConfig.iBank = EMIF_SYNC_BANK_4;
    sdConfig.narrowMode = EMIF_SYNC_NARROW_MODE_TRUE;
    sdConfig.pageSize = EMIF_SYNC_COLUMN_WIDTH_11;
    EMIF_setSyncMemoryConfig(EMIF1_BASE, &sdConfig);

    // Configures Normal Asynchronous Mode of Operation.
    EMIF_setAsyncMode(EMIF1_BASE, EMIF_ASYNC_CS2_OFFSET, EMIF_ASYNC_NORMAL_MODE);

    // Disables Extended Wait Mode.
    EMIF_disableAsyncExtendedWait(EMIF1_BASE, EMIF_ASYNC_CS2_OFFSET);

    // Configure EMIF1 Data Bus Width.
    EMIF_setAsyncDataBusWidth(EMIF1_BASE, EMIF_ASYNC_CS2_OFFSET, EMIF_ASYNC_DATA_WIDTH_16);

    // Configure the access timing for CS2 space.
    tparam.rSetup = 0;
    tparam.rStrobe = 3;
    tparam.rHold = 0;
    tparam.turnArnd = 0;
    tparam.wSetup = 0;
    tparam.wStrobe = 1;
    tparam.wHold = 0;

    EMIF_setAsyncTimingParams(EMIF1_BASE, EMIF_ASYNC_CS2_OFFSET, &tparam);
 }

 

Linker 설정

MEMORY
{
PAGE 1 : /* Data Memory */
         /* Memory (RAM/FLASH) blocks can be moved to PAGE0 for program allocation */

   SDRAM 		   : origin = 0x80000000, length = 0x10000000 /* 512Kx16 SDRAM */
}

SECTIONS
{
   .farbss         : >  SDRAM,                              PAGE = 1
}

 

변수를 SDRAM에 Mapping

#pragma DATA_SECTION(FW_DATA_BUFF,".farbss")

__attribute__ ((far)) volatile uint16_t FW_DATA_BUFF[102400];

삽질 포인트

처음 #pragma DATA_SECTION(FW_DATA_BUFF, ".farbss") 키워드를 이용하여 FW_DATA_BUFF를 0x80000000 주소에 Mapping 하는 것은 성공 하였다.

 

하지만 프로그램 상에서 FW_DATA_BUFF의 주소를 읽어 보면 0x80000000이 아닌 상대 Offset인 0, 2 값만 읽혀지면서 FW_DATA_BUFF[0]=0x11, FW_DATA_BUFF[1] = 0x22 와 같이 값을 쓰려고 해도 값이 써지지 않는 문제를 경험하였다.

 

이를 해결하기 위해 __attribute__ ((far)) 키워드를 넣어서 컴파일 하니 정상적으로 FW_DATA_BUFF의 주소가 0x80000000로 Mapping이 되며 FW_DATA_BUFF[0]에 값을 입력하면 정상적으로 값이 써지는 것을 확인 하였다.

 

반응형