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.

DDR3 Inizialization failure in C6678

I've followed SPRABL2A (KeyStone DDR3 Initialization Application Report) for the inizialization of DDR3 module in my C6678

And it's not working.

I've noticed that all the configuration registers (except the 2 used for DDR3-PLL) remains 0 even after the writing of the correct values and the end of the configuration when i read them via watch window

I guess I'm forgetting something that is not listed in the guide. Where am I doing wrong?

Thanks

  • Nothing?

    In the datasheet it's written that the Logical 32-bit Address of the DDR3 EMIF configuration is from 0x21000000 to 0x210001FF while Physical 36-bit Address is from 1x00000000 to 1x000001FF. Is this the reason why I can not read these registers through watch window? Does it means that they are not physically within the dsp and also that a hardware issue to the DDR3 module could prevent me from accessing? 

  • Hi Henry,

    It's not clear from you post the method that you are using to configure the memory. Are you using a GEL? I would recommend that you start with the GEL file delivered with MCSDK, modify it with the values you calculated for you board and see if you can get the memory to initialize. Note that you should be able to see the values written using a memory window after the configuration is complete. It's best not to keep the memory window open while you are running the configuration. The constant refreshing of the window may distort some of the timing needed.

    Regards, Bill

  • Hi Bill.

    As i already wrote i've followed "KeyStone DDR3 Initialization" (SPRABL2A) step by step for the inizialization of my DDR3

    #define PLL2_PLLD 0 // Must be less than 64
    #define PLL2_PLLM 19 // Must be less than 4096
    DDR3PLLCTL1 |= 0x00000040; // Set ENSAT bit = 1
    DDR3PLLCTL0 |= 0x00800000; // Set BYPASS bit = 1
    // Clear and program PLLD field
    DDR3PLLCTL0 &= ~(0x0000003F);
    DDR3PLLCTL0 |= (PLL2_PLLD & 0x0000003F);
    // Clear and program PLLM field
    DDR3PLLCTL0 &= ~(0x0007FFC0);
    DDR3PLLCTL0 |= ((PLL2_PLLM << 6) & 0x0007FFC0 );
    // Clear and program BWADJ field
    PLL2_BWADJ = ((PLL2_PLLM + 1) >> 1) - 1;
    DDR3PLLCTL0 &= ~(0xFF000000);
    DDR3PLLCTL1 &= ~(0x0000000F);
    DDR3PLLCTL0 |= ((PLL2_BWADJ << 24) & 0xFF000000);
    DDR3PLLCTL1 |= ((PLL2_BWADJ >> 8) & 0x0000000F);
    DDR3PLLCTL1 |= 0x00002000; // Set RESET bit = 1
    for(i=0;i<10000;i++); // Wait at least 5us for reset complete
    DDR3PLLCTL1 &= ~(0x00002000); // Clear RESET bit
    for(i=0;i<70000;i++); // Wait at least 50us for PLL lock
    DDR3PLLCTL0 &= ~(0x00800000); // Clear BYPASS bit = 0

    DDR3_CONFIG_REG_0 &= ~(0x007FE000); // clear ctrl_slave_ratio field
    DDR3_CONFIG_REG_0 |= 0x00200000; // set ctrl_slave_ratio to 0x100
    DDR3_CONFIG_REG_12 |= 0x08000000; // Set invert_clkout = 1
    DDR3_CONFIG_REG_0 |= 0xF; // set dll_lock_diff to 15
    DATA0_WRLVL_INIT_RATIO = 0x99;
    DATA1_WRLVL_INIT_RATIO = 0x99;
    DATA2_WRLVL_INIT_RATIO = 0x99;
    DATA3_WRLVL_INIT_RATIO = 0x8D;
    DATA4_WRLVL_INIT_RATIO = 0x75;
    DATA5_WRLVL_INIT_RATIO = 0x77;
    DATA6_WRLVL_INIT_RATIO = 0x62;
    DATA7_WRLVL_INIT_RATIO = 0x5E;
    DATA8_WRLVL_INIT_RATIO = 0x80;
    DATA0_GTLVL_INIT_RATIO = 0xDF;
    DATA1_GTLVL_INIT_RATIO = 0xDF;
    DATA2_GTLVL_INIT_RATIO = 0xC2;
    DATA3_GTLVL_INIT_RATIO = 0xCE;
    DATA4_GTLVL_INIT_RATIO = 0xAE;
    DATA5_GTLVL_INIT_RATIO = 0xAC;
    DATA6_GTLVL_INIT_RATIO = 0xA4;
    DATA7_GTLVL_INIT_RATIO = 0xA7;
    DATA8_GTLVL_INIT_RATIO = 0xBE;
    DDR_PHYCTRL &= ~(0x00008000);
    DDR_PHYCTRL |= (0x00008000);
    DDR_PHYCTRL &= ~(0x00008000);

    TEMP = 0;
    TEMP |= 0x8 << 25; // T_RP bit field 28:25
    TEMP |= 0x8 << 21; // T_RCD bit field 24:21
    TEMP |= 0x9 << 17; // T_WR bit field 20:17
    TEMP |= 0x17 << 12; // T_RAS bit field 16:12
    TEMP |= 0x20 << 6; // T_RC bit field 11:6
    TEMP |= 0x7 << 3; // T_RRD bit field 5:3
    TEMP |= 0x4; // T_WTR bit field 2:0
    DDR_SDTIM1 = TEMP;

    TEMP = 0;
    TEMP |= 0x3 << 28; // T_XP bit field 30:28
    TEMP |= 0x71 << 16; // T_XSNR bit field 24:16
    TEMP |= 0x1ff << 6; // T_XSRD bit field 15:6
    TEMP |= 0x4 << 3; // T_RTP bit field 5:3
    TEMP |= 0x3; // T_CKE bit field 2:0
    DDR_SDTIM2 = TEMP;
    TEMP = 0;
    TEMP |= 0x5 << 28; // T_PDLL_UL bit field 31:28 (fixed value)
    TEMP |= 0x5 << 24; // T_CSTA bit field 27:24 (fixed value)
    TEMP |= 0x4 << 21; // T_CKESR bit field 23:21
    TEMP |= 0x3f << 15; // T_ZQCS bit field 20:15
    TEMP |= 0x6A << 4; // T_RFC bit field 12:4
    TEMP |= 0xf; // T_RAS_MAX bit field 3:0 (fixed value)
    DDR_SDTIM3 = TEMP;

    DDR_PHYCTRL  = 0x0010010F;

    DDR_ZQCFG    = 0x70073214;

    DDR_PMCTL    = 0x0;

    DDR_SDRFC    = 0x00005162;    // enable configuration

    TEMP = 0;
    TEMP |= 0x3 << 29; // SDRAM_TYPE bit field 31:29 (fixed value)
    TEMP |= 0x0 << 27; // IBANK_POS bit field 28:27
    TEMP |= 0x3 << 24; // DDR_TERM bit field 26:24
    TEMP |= 0x0 << 21; // DYN_ODT bit field 22:21
    TEMP |= 0x1 << 18; // SDRAM_DRIVE bit field 19:18
    TEMP |= 0x2 << 16; // CWL bit field 17:16
    TEMP |= 0x0 << 14; // NM bit field 15:14
    TEMP |= 0xA << 10; // CL bit field 13:10
    TEMP |= 0x4 << 7; // ROWSIZE bit field 9:7
    TEMP |= 0x3 << 4; // IBANK bit field 6:4
    TEMP |= 0x0 << 3; // EBANK bit field 3:3
    TEMP |= 0x2; // PAGESIZE bit field 2:0
    DDR_SDCFG = TEMP;

    for(i=0;i<1000;i++); //Wait 600us for HW init to complete
    DDR_SDRFC = 0x00001450; //Refresh rate = (7.8*666MHz]

    RDWR_LVL_RMP_CTRL = 0x80000000;
    RDWR_LVL_CTRL = 0x80000000;
    for(i=0;i<1000;i++); //Wait 3ms for leveling to complete

    RDWR_LVL_RMP_WIN = 0x00000502;
    RDWR_LVL_RMP_CTRL = 0x80030300;
    RDWR_LVL_CTRL = 0xFF090900;

    KICK0 = KICK0_LOCK; //lock kicker registers
    KICK1 = KICK1_LOCK;

    Of course using correct values for my DDR3 module from the datasheet

    After this the module don't work and if i read in the DDR3 registers i read only 0x0. Why?

  • Yes, it is probably due to the fact that you have not configured your XMC MPAX properly as you hinted at in one of your previous replies. That will block any writes from happening to the physical address of the DDR3 config space.

    Add this to your configuration (this is part of the standard MCSDK GEL) and run xmc_setup before you start the initialization procedure:

    /*--------------------------------------------------------------*/
    /* xmc_setup() */
    /* XMC MPAX register setting to access DDR3 config space */
    /*--------------------------------------------------------------*/

    #define XMC_BASE_ADDR (0x08000000)
    #define XMPAX2_L (*(int*)(XMC_BASE_ADDR + 0x00000010))
    #define XMPAX2_H (*(int*)(XMC_BASE_ADDR + 0x00000014))

    xmc_setup()
    {
    /* mapping for ddr emif registers XMPAX*2 */
    XMPAX2_L = 0x100000FF; /* replacement addr + perm*/
    XMPAX2_H = 0x2100000B; /* base addr + seg size*/

    }

  • Thank you very much Aditya.

    I've added your code and now i'm able to read the DDR3 configuration registers and i read the correct values i've written. And of course now i'm able to read and write in the DDR3 Memory module 

    I just had to configure the addrex extension. 
    In datasheets is written that by default that memory space is already configured to access the DDR3 Emif registers and the first 2 GB of external memory but clearly for access to DDR3 registers it still has to be configured.

    Thanks again

  • Henry,

    Good to know you are able to execute reads/write to DDR.

    If you are referring to this at the end of Table 2-2:

    "2 The memory map shows only the default MPAX configuration of DDR3 memory space..."

    Per the table, (2) applies only to DDR3 EMIF data space and not to the DDR3 EMIF config space. If there is something mentioned to the contrary in the datasheet, do let us know and we will get it fixed.

  • Hi Henry,

    I'm glad that the DDR3 is operating but after reviewing your initialization, I have a few concerns that I wanted to ask about.

    First, it looks like the values for write leveling initial ratios and the gate leveling initial ratios are identical to those found in 2.3 of the initialization application report. These values are calculated using the trace lengths of the DDR3 signals on your board. Did you calculate these values using the PHYCALC spreadsheet?

    Secondly, there is a statement to OR and write to register DDR3_CONFIG_REG_23 which is needed for partial automatic leveling.

    DDR3_CONFIG_REG_23 |= 0x00000200;

    This statement is missing from the initialization sequence that you provided. Note that the DDR3 may operate if initialized incorrectly but it may not operate correctly across temperature of for all devices.

    Regards, Bill 

  • Aditya

    Ah, ok, then I misunderstood
    I thought it was referring to both the memory space of the registers, and the memory space of the data for the DDR3

    Thanks Again.

     

    Bill Yes, the fact is that i've posted here the original code copied from the documentation i've used, because in my code I had used different names for the registers and I did not want to confuse.
    And of course in my code i've use the correct values, for the physical parameters calculated with the spreatsheet, and for the timing parameters obtained from the datasheet.

    i have not written the row DDR3_CONFIG_REG_23 |= 0x00000200; because i'm using the Full Leveling, not the partial leveling.
    I've seen from page 13 in SPRABL2A that for C6678 the Full leveling is supported  so i decided to use that