This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM3894 DDR3 Init

Other Parts Discussed in Thread: AM3894, CCSTUDIO

Hello all.

I have custom board with AM3894 and DDR3

DDR3 (size 1GB, two chips K4B4G1646B-HIH9 x16 as one space x32)  connect to EMIF0, EMIF1 not use.

default Gel-file TI816x_DDR3 don't work

Calculated values according to the instructions given in the files DM816x_C6A816x_AM389x_EMIF4_Register_Settings and RatioSeed

and create the modified file AM3894_RW.gel

Connect to device and run DDR3_SlaveRatio_ByteWiseSearch_TI816x.out

Get optimal values for WR DQS, RD DQS and RD DQS GATE.

Change Gel-file.

DDR is working correctly.

But i need initialization DDR in the my program. When I initialize the DDR in your program using the same values as in Gel file, i read zero only from DDR space.

Core in Supervisor mode.

Init code:

#define _CONFIG_
#include "am3894.h"
#include "config.h"

unsigned long MAILPLL();
unsigned long DDRPLL();
unsigned long DDR_PRMC();


unsigned long MAILPLL(){

        pMAINPLL_CTRL |= 0x4;              //Set MAIN_BP bit in MAINPLL_CTRL to 1 to put MAINPLL in bypass mode.

        if(!(pMAINPLL_CTRL & 0x8)){                                        //Initializing and Enabling MAINPLL from Power Down Mode
            pMAINPLL_CTRL |= 0x8;                                        //Set MAIN_PLLEN bit in MAINPLL_CTRL to 1 to bring MAINPLL out of power-down mode.
        }

        pMAINPLL_PWD  &= 0x0B;     //Clear PWD_CLK1 to PWD_CLK7 bits in MAINPLL_PWD to 0
        pMAINPLL_CTRL &= 0xFFFFFFFE;                                    //Set or clear MAIN_LOC_CTL bit in MAINPLL_CTRL to select MAINPLL lock output polarity CLEAR
        pMAINPLL_CTRL = (((pMAINPLL_CTRL & 0xFF)|0x100)|0x00400000);    //Program the required pre-divider and multiplier values

        //Program MAIN_INTFREQx and MAIN_FRACFREQx bit fields
        pMAINPLL_FREQ2 = (1<<28)|(MAIN_INTFREQ2<<24)| MAIN_FRACFREQ2;
        pMAINPLL_FREQ4 = (1<<28)|(MAIN_INTFREQ4<<24)| MAIN_FRACFREQ4;
        pMAINPLL_FREQ5 = (1<<28)|(MAIN_INTFREQ5<<24)| MAIN_FRACFREQ5;

        //Program MAIN_MDIVx bit field
        pMAINPLL_DIV2 = MAIN_MDIV2;
        pMAINPLL_DIV4 = MAIN_MDIV4;
        pMAINPLL_DIV5 = MAIN_MDIV5;
        pMAINPLL_DIV6 = MAIN_MDIV6;
        pMAINPLL_DIV7 = MAIN_MDIV7;

        //set MAIN_LDMDIVx bit to 1 in MAINPLL_DIVx to load the Post Divider into Main Synthesizer x and
        //set MAIN_LDFREQx bit to 1 in MAINPLL_FREQx to load integer and fraction values into Main Synthesizer x.
        pMAINPLL_DIV2 |= (unsigned long)(1<<8);
        pMAINPLL_FREQ2 |= (unsigned long)(1<<31);
        pMAINPLL_DIV4 |= (unsigned long)(1<<8);
        pMAINPLL_FREQ4 |= (unsigned long)(1<<31);
        pMAINPLL_DIV5 |= (unsigned long)(1<<8);
        pMAINPLL_FREQ5 |= (unsigned long)(1<<31);
        pMAINPLL_DIV6 |= (unsigned long)(1<<8);
        pMAINPLL_DIV7 |= (unsigned long)(1<<8);

        if(pMAINPLL_CTRL & 0x1){
            while(pMAINPLL_CTRL & 0x80);
            pMAINPLL_CTRL &= 0xFFFFFFFB;

        }
        else{
            while(!(pMAINPLL_CTRL & 0x80));
            pMAINPLL_CTRL &= 0xFFFFFFFB;
        }

        return TRUE;
}

unsigned long DDRPLL(){

    pDDRPLL_CTRL &= 0xFFFFFFFB;                                        //Clear DDR_BP bit in DDRPLL_CTRL to 0 to put DDRPLL in bypass mode

    if(!(pDDRPLL_CTRL & 0x8)){                                        //Initializing and Enabling DDRPLL from Power Down Mode
        pDDRPLL_CTRL |= 0x8;                                        //Set DDR_PLLEN bit in DDRPLL_CTRL to 1 to bring DDRPLL out of power-down mode
    }

    pDDRPLL_PWD = 0x0;                                                //Clear PWD_CLK1 to PWD_CLK5 bits in DDRPLL_PWD to 0 to bring individual output clocks of DDRPLL out of power-down mode
    pDDRPLL_CTRL &= 0xFFFFFFFE;                                        //Set or clear DDR_LOC_CTL bit in DDRPLL_CTRL to select DDRPLL lock output polarity (DDR_LOCK bit in DDRPLL_CTRL). - CLEAR
    pDDRPLL_CTRL = (((pDDRPLL_CTRL & 0xFF)|0x100)|0x003B0000);        //Program the required pre-divider and multiplier values in DDR_P and DDR_N bit fields of DDRPLL_CTRL

    //Program DDR_INTFREQx and DDR_FRACFREQx bit fields
    pDDRPLL_FREQ2 = (1<<28)|(DDR_INTFREQ2<<24)|DDR_FRACFREQ2;
    pDDRPLL_FREQ3 = (1<<28)|(DDR_INTFREQ3<<24)|DDR_FRACFREQ3;

    //Program DDR_MDIVx bit field
    pDDRPLL_DIV1 = DDR_MDIV1;
    pDDRPLL_DIV2 = DDR_MDIV2;
    pDDRPLL_DIV3 = DDR_MDIV3;

    //set DDR_LDMDIVx bit to 1 in DDRPLL_DIVx to load the Post Divider into DDR Synthesizer x and
    //set DDR_LDFREQx bit to 1 in DDRPLL_FREQx to load integer and fraction values into DDR Synthesizer x.
    pDDRPLL_DIV1 |= (unsigned long)(1<<8);
    pDDRPLL_DIV2 |= (unsigned long)(1<<8);
    pDDRPLL_FREQ2 |= (unsigned long)(1<<31);
    pDDRPLL_DIV3 |= (unsigned long)(1<<8);
    pDDRPLL_FREQ3 |= (unsigned long)(1<<31);

    while (!(pDDRPLL_CTRL & 0x8));                                    //Wait for PLL to Lock: Poll for DDR_LOCK bit in DDRPLL_CTRL to become 1

    pDDRPLL_CTRL |= 4;                                                //Set the DDR_BP bit in DDRPLL_CTRL to 1 to bring DDRPLL out of bypass mode.

    pDDR_RCD = 0x1;                                                    //Set PWRDN bit in DDR_RCD to 1 to bring the Reset Clock Distribution module of DDR out of powerdown mode.
    return TRUE;
}

unsigned long DDR_PRMC()
{
    pCM_DEFAULT_FW_CLKCTRL = 0x2;
    pCM_DEFAULT_L3_FAST_CLKSTCTRL = 0x2;
    pCM_DEFAULT_EMIF_0_CLKCTRL = 0x2;
    pCM_DEFAULT_EMIF_1_CLKCTRL = 0x2;

    while((pCM_DEFAULT_L3_FAST_CLKSTCTRL & 0x300)!= 0x300);
    while((pCM_DEFAULT_EMIF_0_CLKCTRL & 0x30000)!= 0x0);
    while((pCM_DEFAULT_EMIF_1_CLKCTRL & 0x30000)!= 0x0);

    pCM_DEFAULT_DMM_CLKCTRL = 0x2;
    while((pCM_DEFAULT_DMM_CLKCTRL & 0x30000)!= 0x0);
    return TRUE;
}



unsigned long DDR_INIT(){

    DDRPLL();
    DDR_PRMC();
    //Program DDR PHY
        //Write 1 to DATA0/1/2/3_REG_PHY_USE_RANK0_DELAYS register to use rank 0 delays for all ranks during read/write operation.
    pDATA0_REG_PHY_USE_RANK0_DELAYS = 1;
    pDATA1_REG_PHY_USE_RANK0_DELAYS = 1;
    pDATA2_REG_PHY_USE_RANK0_DELAYS = 1;
    pDATA3_REG_PHY_USE_RANK0_DELAYS = 1;
        //Write 1 to CMD0/1/2_REG_PHY_INVERT_CLKOUT_0 register to send inverted DDR Clock to DRAM. 0 - NOT INVERT
    pCMD0_REG_PHY_INVERT_CLKOUT_0 = 1;
    pCMD1_REG_PHY_INVERT_CLKOUT_0 = 1;
    pCMD2_REG_PHY_INVERT_CLKOUT_0 = 1;
        //Program CMD0/1/2_REG_PHY_CTRL_SLAVE_RATIO_0 register. If CMD0/1/2_REG_PHY_INVERT_CLKOUT_0 is cleared to 0, program 80h; else, program to 100h
    if(pCMD0_REG_PHY_INVERT_CLKOUT_0 == 0) pCMD0_REG_PHY_CTRL_SLAVE_RATIO_0 = 0x80;
    else pCMD0_REG_PHY_CTRL_SLAVE_RATIO_0 = 0x100;
    if(pCMD1_REG_PHY_INVERT_CLKOUT_0 == 0) pCMD1_REG_PHY_CTRL_SLAVE_RATIO_0 = 0x80;
    else pCMD1_REG_PHY_CTRL_SLAVE_RATIO_0 = 0x100;
    if(pCMD2_REG_PHY_INVERT_CLKOUT_0 == 0) pCMD2_REG_PHY_CTRL_SLAVE_RATIO_0 = 0x80;
    else pCMD2_REG_PHY_CTRL_SLAVE_RATIO_0 = 0x100;
        //Write 5h to CMD0/1/2_IO_CONFIG_I_0 register.
    pCMD0_IO_CONFIG_I_0 = 0x5;
    pCMD1_IO_CONFIG_I_0 = 0x5;
    pCMD2_IO_CONFIG_I_0 = 0x5;
        //Write 5h to CMD0/1/2_IO_CONFIG_I_CLK_0 register
    pCMD0_IO_CONFIG_I_CLK_0 = 0x5;
    pCMD1_IO_CONFIG_I_CLK_0 = 0x5;
    pCMD2_IO_CONFIG_I_CLK_0 = 0x5;
        //Write 4h to DATA0/1/2/3_IO_CONFIG_I_0 register
    pDATA0_IO_CONFIG_I_0 = 0x4;
    pDATA1_IO_CONFIG_I_0 = 0x4;
    pDATA2_IO_CONFIG_I_0 = 0x4;
    pDATA3_IO_CONFIG_I_0 = 0x4;
        //Write 4h to DATA0/1/2/3_IO_CONFIG_I_CLK_0 register
    pDATA0_IO_CONFIG_I_CLK_0 = 0x4;
    pDATA1_IO_CONFIG_I_CLK_0 = 0x4;
    pDATA2_IO_CONFIG_I_CLK_0 = 0x4;
    pDATA3_IO_CONFIG_I_CLK_0 = 0x4;

    pDMM_LISA_MAP__0 = 0x80600100;        // WR_MEM_32(DMM_LISA_MAP__0, 0x80600100);
    //Enable Tiled Access
    pDMM_PAT_BASE_ADDR = 0x80000000;    //WR_MEM_32(DMM_PAT_BASE_ADDR, 0x80000000);

    pEMIF4_0_SDRAM_TIM_1 = EMIF_TIM1_DDR3;                        //0x1557B9BD
    pEMIF4_0_SDRAM_TIM_1_SHADOW = EMIF_TIM1_DDR3;
    pEMIF4_0_SDRAM_TIM_2 = EMIF_TIM2_DDR3;                       // 0x40C77FEB
    pEMIF4_0_SDRAM_TIM_2_SHADOW = EMIF_TIM2_DDR3;
    pEMIF4_0_SDRAM_TIM_3 = EMIF_TIM3_DDR3;                      //0x001F8EFF
    pEMIF4_0_SDRAM_TIM_3_SHADOW = EMIF_TIM3_DDR3;

    pEMIF4_0_SDRAM_CONFIG = EMIF_SDCFG_DDR3;           //0x62A73832

    pEMIF4_0_DDR_PHY_CTRL_1 = EMIF_PHYCFG_DDR3;    //0x00000110
    pEMIF4_0_DDR_PHY_CTRL_1_SHADOW = EMIF_PHYCFG_DDR3;            

    pEMIF4_0_SDRAM_REF_CTRL    = ((pEMIF4_0_SDRAM_REF_CTRL&0xFFFF0000)|EMIF_SDREF_DDR3);     //0x00001840

    pEMIF4_0_SDRAM_REF_CTRL |= 0x10000000;
    pEMIF4_0_SDRAM_REF_CTRL &= 0x7FFFFFFF;

    pDDR_VTP_CTRL_0    &= 0xFFFFFFEF;                //Write 0 WR_LEVEL bit in DDR_VTP_CTRL_0


    pDATA0_REG_PHY_FIFO_WE_SLAVE_RATIO_0 = SWLEVEL_DQS_GATE_BYTE_LANE0;
    pDATA1_REG_PHY_FIFO_WE_SLAVE_RATIO_0 = SWLEVEL_DQS_GATE_BYTE_LANE1;
    pDATA2_REG_PHY_FIFO_WE_SLAVE_RATIO_0 = SWLEVEL_DQS_GATE_BYTE_LANE2;
    pDATA3_REG_PHY_FIFO_WE_SLAVE_RATIO_0 = SWLEVEL_DQS_GATE_BYTE_LANE3;

    pDATA0_REG_PHY_WR_DQS_SLAVE_RATIO_0 = SWLEVEL_WR_DQS_RATIO_BYTE_LANE0;
    pDATA1_REG_PHY_WR_DQS_SLAVE_RATIO_0 = SWLEVEL_WR_DQS_RATIO_BYTE_LANE1;
    pDATA2_REG_PHY_WR_DQS_SLAVE_RATIO_0 = SWLEVEL_WR_DQS_RATIO_BYTE_LANE2;
    pDATA3_REG_PHY_WR_DQS_SLAVE_RATIO_0 = SWLEVEL_WR_DQS_RATIO_BYTE_LANE3;


    pDATA0_REG_PHY_WR_DATA_SLAVE_RATIO_0 = SWLEVEL_WR_DATA_RATIO_BYTE_LANE0;
    pDATA1_REG_PHY_WR_DATA_SLAVE_RATIO_0 = SWLEVEL_WR_DATA_RATIO_BYTE_LANE1;
    pDATA2_REG_PHY_WR_DATA_SLAVE_RATIO_0 = SWLEVEL_WR_DATA_RATIO_BYTE_LANE2;
    pDATA3_REG_PHY_WR_DATA_SLAVE_RATIO_0 = SWLEVEL_WR_DATA_RATIO_BYTE_LANE3;

    pDATA0_REG_PHY_RD_DQS_SLAVE_RATIO_0 = SWLEVEL_RD_DQS_RATIO_LINE0;
    pDATA1_REG_PHY_RD_DQS_SLAVE_RATIO_0 = SWLEVEL_RD_DQS_RATIO_LINE1;
    pDATA2_REG_PHY_RD_DQS_SLAVE_RATIO_0 = SWLEVEL_RD_DQS_RATIO_LINE2;
    pDATA3_REG_PHY_RD_DQS_SLAVE_RATIO_0 = SWLEVEL_RD_DQS_RATIO_LINE3;

    return TRUE;
}

unsigned long ConfigHardware(void)
{
 
    MAILPLL();
    DDR_INIT();
    return TRUE;
}

  • Hi Alexandr,

    Alexandr Zinin said:
    default Gel-file TI816x_DDR3 don't work

    Which GEL file do not work? Is it evm816x.gel v1.02? Or TI816x_DDR3.gel v1.5? Have you modify it like below?

    #define TWO_EMIF          0

    See if the below wiki pages will be in help:

    Regards,
    Pavel

  • Hi Pavel,

    First, I use TI816x_DDR3.gel v.1.5 on 03.Oct.2012. It don't work.
    I have made the necessary changes, and create gel file for my board. It work. I can read and write to DDR. Yes, i set define "TWO_EMIF" to 0.
    But when I initialize the DDR in MY program using the same values as in Gel file, i read zero only from DDR space. When i initialize the DDR in MY program, i use empty Gel-file.

  • Alexandr,

    Alexandr Zinin said:
    But when I initialize the DDR in MY program using the same values as in Gel file, i read zero only from DDR space. When i initialize the DDR in MY program, i use empty Gel-file.

    What is "MY program"??? Is this application created under CCStudio????

  • Pavel,
    Yes, this is CCStudio Project
  • Alexandr,

    So you want to use CCS out file without using GEL file at all? Have you transfer the CCS memory map setup from the GEL file to the CCS application?

    Best regards,
    Pavel
  • Pavel,
    No, i use GEL file for CCS memory map setup. I don't use GEL file for initialization PLL, PRMC, DDR. I want initialization PLL, PRMC, DDR in CCS Project.
  • Alexandr,

    Alexandr Zinin said:
    No, i use GEL file for CCS memory map setup.

    So finally you do not use empty GEL file, but GEL file which is reduced from PLL, PRCM and DDR init code, and this code is transferred to the CCS application, is this correct?

    I think CCS application is loaded in DDR (0x80000000) and DDR is not init, that is why the application does not work. Have you tried to load the CCS application into the AM389x internal SRAM (0x40300000)?

    BR
    Pavel




  • Yes, this is correct. Yes, i load application in inernal RAM with full verification. Application is executed, and i think it's executed right. After the execution of the program, I can see that the values in the respective registers have changed and changed correctly. But after the execution of the application , i open memory browser on 0x80000000 and see only zero. If I try to write to memory it does not result, see only zero/
  • Could you provide me your steps for loading and executing application (*.out file) into internal RAM?

    Regards,
    Pavel
  •  Load CCS

    Open Target Configuration.

    Launch Selected Configuration - AM3894.ccxml

    Connect to target.

    Load GEL-includes only memory map setting.

    Load *.out file with reset and without "Run to Main"

    Execute application.

  • Alexandr,

    Let me check this at my side (run out file from internal RAM) and update here.

    Meanwhile can you try with:

    - use full GEL file - all init in GEL file
    - run DDR memory test from SpectrumDigital TI EVM (modify the code as per your custom board) and see if it will pass
    - the Spectrum Digital DM816x/AM389x TI EVM DDR test is at:
    support.spectrumdigital.com/.../revg
    DM816x/C6A816x/AM389x EVM Software Resources -> Test Code -> tests/ddr/
  • Alexandr,

    Do you run the OCMCRAMClkEnable() function from the GEL file before loading the out file into the internal RAM? If no, please do it.

    BR
    Pavel
  • What you need from me for check at your side?
    Test result:

    [CortexA8] 01 Testing DDR...
    PASS

    ***ALL Tests Passed***

    I have not OCMCRAMClkEnable() function in GEL file, but i check CM_ALWON_OCMC_0_CLKCTRL and CM_ALWON_OCMC_0_CLKSTCTRL registers.

    CM_ALWON_OCMC_0_CLKSTCTRL is set to 0x102
    CM_ALWON_OCMC_0_CLKCTRL is set to 0x2
  • Alexandr,

    At what speed you are initializing the DDR3 memory? Can you try at 400MHz? Can you describe me your DDR test after the initialization, at which DDR0 address you are reading 0 only?

    BR
    Pavel
  • Speed 796,5 MHz.
    I solved this problem.
    According to AM389x TRM (SPRUGX7B) page 758 (7.5.2.3)
    "...
    12. Write 1 to the ASR bit in SDRRCR register to enable DDR3 auto self refresh.
    13. Write 0 to the INITREF_DIS bit in SDRRCR register to enable DDR3 initialization.
    ..."
    if i do it, like two different command:

    #define EMIF4_0_CFG_BASE_ADDR 0x4C000000
    #define pEMIF4_0_SDRAM_REF_CTRL *(volatile unsigned long*)(EMIF4_0_CFG_BASE_ADDR + 0x10)

    pEMIF4_0_SDRAM_REF_CTRL |= 0x10000000; Write 1 to the ASR bit in SDRRCR
    pEMIF4_0_SDRAM_REF_CTRL &= 0x7FFFFFFF; Write 0 to the INITREF_DIS bit in SDRRCR register

    i read only 0.

    But, if i do it in a different order

    pEMIF4_0_SDRAM_REF_CTRL &= 0x7FFFFFFF; Write 0 to the INITREF_DIS bit in SDRRCR register
    pEMIF4_0_SDRAM_REF_CTRL |= 0x10000000; Write 1 to the ASR bit in SDRRCR

    or do it, like one command:

    pEMIF4_0_SDRAM_REF_CTRL = ((pEMIF4_0_SDRAM_REF_CTRL&0x7FFFFFFF)|0x10000000);

    DDR is working.
  • Thank you for sharing the solution.

    Regards,
    Pavel