Question

I am having trouble initializing the EMIF and DDR_PHY for the DDR2 memory on Texas Instruments' ICE evaluation board inside a bare-metal project. I wrote an init sequence based on the one found in the StarterWare bootloader example. However I cannot get the DDR to work.

The controller runs through the whole process, but the DDR looks kind of random with every step I do in the debugger. I am monitoring 0x80000000. Writing to this area with the debugger also does not work. The status register shows that the PHY is not ready.

Am I missing something? Do I have the wrong sequence of one command or another? Can anybody advise?

Here is my code:

{
  //! Switch to System Mode
  asm("    swi     #1;");

  //! Enable EMIF
  CM_PER->EMIF_FW_CLKCTRL             |= 2;
  CM_PER->EMIF_CLKCTRL                |= 2;
  while (!(CM_PER->L3_CLKSTCTRL & ((1 << 4) | (1 << 2))));

  //! Phy init
  CONTROL_MODULE->VTP_CTRL            |=  (1 << 6);
  CONTROL_MODULE->VTP_CTRL            &= ~(1 << 0);
  CONTROL_MODULE->VTP_CTRL            |=  (1 << 0);;
  while (!(CONTROL_MODULE->VTP_CTRL & (1 << 5)));

  DDR_PHY->CMD[0].SLAVE_RATIO          = DDR_CONFIG_PHY_CMD0_SLAVE_RATIO;
  DDR_PHY->CMD[0].SLAVE_FORCE          = DDR_CONFIG_PHY_CMD0_SLAVE_FORCE;
  DDR_PHY->CMD[0].SLAVE_DELAY          = DDR_CONFIG_PHY_CMD0_SLAVE_DELAY;
  DDR_PHY->CMD[0].DLL_LOCK_DIFF        = DDR_CONFIG_PHY_CMD0_LOCK_DIFF;
  DDR_PHY->CMD[0].INVERT_CLKOUT        = DDR_CONFIG_PHY_CMD0_INVERT_CLKOUT;

  DDR_PHY->CMD[1].SLAVE_RATIO          = DDR_CONFIG_PHY_CMD1_SLAVE_RATIO;
  DDR_PHY->CMD[1].SLAVE_FORCE          = DDR_CONFIG_PHY_CMD1_SLAVE_FORCE;
  DDR_PHY->CMD[1].SLAVE_DELAY          = DDR_CONFIG_PHY_CMD1_SLAVE_DELAY;
  DDR_PHY->CMD[1].DLL_LOCK_DIFF        = DDR_CONFIG_PHY_CMD1_LOCK_DIFF;
  DDR_PHY->CMD[1].INVERT_CLKOUT        = DDR_CONFIG_PHY_CMD1_INVERT_CLKOUT;

  DDR_PHY->CMD[2].SLAVE_RATIO          = DDR_CONFIG_PHY_CMD2_SLAVE_RATIO;
  DDR_PHY->CMD[2].SLAVE_FORCE          = DDR_CONFIG_PHY_CMD2_SLAVE_FORCE;
  DDR_PHY->CMD[2].SLAVE_DELAY          = DDR_CONFIG_PHY_CMD2_SLAVE_DELAY;
  DDR_PHY->CMD[2].DLL_LOCK_DIFF        = DDR_CONFIG_PHY_CMD2_LOCK_DIFF;
  DDR_PHY->CMD[2].INVERT_CLKOUT        = DDR_CONFIG_PHY_CMD2_INVERT_CLKOUT;

  DDR_PHY->DATA[0].RD_DQS_SLAVE_RATIO  = DDR_CONFIG_PHY_DATA0_RD_DQS_SLAVE_RATIO;
  DDR_PHY->DATA[0].WR_DQS_SLAVE_RATIO  = DDR_CONFIG_PHY_DATA0_WR_DQS_SLAVE_RATIO;
  DDR_PHY->DATA[0].FIFO_WE_SLAVE_RATIO = DDR_CONFIG_PHY_DATA0_FIFO_WE_SLAVE_RATIO;
  DDR_PHY->DATA[0].WR_DATA_SLAVE_RATIO = DDR_CONFIG_PHY_DATA0_WR_DATA_SLAVE_RATIO;

  DDR_PHY->DATA[1].RD_DQS_SLAVE_RATIO  = DDR_CONFIG_PHY_DATA1_RD_DQS_SLAVE_RATIO;
  DDR_PHY->DATA[1].WR_DQS_SLAVE_RATIO  = DDR_CONFIG_PHY_DATA1_WR_DQS_SLAVE_RATIO;
  DDR_PHY->DATA[1].FIFO_WE_SLAVE_RATIO = DDR_CONFIG_PHY_DATA1_FIFO_WE_SLAVE_RATIO;
  DDR_PHY->DATA[1].WR_DATA_SLAVE_RATIO = DDR_CONFIG_PHY_DATA1_WR_DATA_SLAVE_RATIO;

  //! Set control registers
  CONTROL_MODULE->DDR_CMD0_IOCTRL      = DDR_CONFIG_CMD0_IOCTRL;
  CONTROL_MODULE->DDR_CMD1_IOCTRL      = DDR_CONFIG_CMD1_IOCTRL;
  CONTROL_MODULE->DDR_CMD2_IOCTRL      = DDR_CONFIG_CMD2_IOCTRL;
  CONTROL_MODULE->DDR_DATA0_IOCTRL     = DDR_CONFIG_DATA0_IOCTRL;
  CONTROL_MODULE->DDR_DATA1_IOCTRL     = DDR_CONFIG_DATA1_IOCTRL;
  CONTROL_MODULE->DDR_IO_CTRL         &= DDR_CONFIG_IOCTRL;
  CONTROL_MODULE->DDR_CKE_CTRL        |= DDR_CONFIG_CKE_CTRL;

  //! Set memory interface control registers
  EMIF0->DDR_PHY_CTRL_1                = DDR_CONFIG_PHY_CTRL_1;
  EMIF0->DDR_PHY_CTRL_1               |= DDR_CONFIG_DYN_PWRDN;
  EMIF0->DDR_PHY_CTRL_1_SHDW           = DDR_CONFIG_PHY_CTRL_1_SHDW;
  EMIF0->DDR_PHY_CTRL_1_SHDW          |= DDR_CONFIG_DYN_PWRDN_SHDW;
  EMIF0->DDR_PHY_CTRL_2                = DDR_CONFIG_PHY_CTRL_2;

  //! Set memory interface timing registers
  EMIF0->SDRAM_TIM_1                   = DDR_CONFIG_SD_TIM_1;
  EMIF0->SDRAM_TIM_1_SHDW              = DDR_CONFIG_SD_TIM_1_SHDW;
  EMIF0->SDRAM_TIM_2                   = DDR_CONFIG_SD_TIM_2;
  EMIF0->SDRAM_TIM_2_SHDW              = DDR_CONFIG_SD_TIM_2_SHDW;
  EMIF0->SDRAM_TIM_3                   = DDR_CONFIG_SD_TIM_3;
  EMIF0->SDRAM_TIM_3_SHDW              = DDR_CONFIG_SD_TIM_3_SHDW;

  EMIF0->SDRAM_CONFIG                  = DDR_CONFIG_SD_CONFIG_BEFORE;
  EMIF0->SDRAM_REF_CTRL                = DDR_CONFIG_SD_REF_CTRL_BEFORE;
  EMIF0->SDRAM_REF_CTRL_SHDW           = DDR_CONFIG_SD_REF_CTRL_SHDW_BEFORE;

  //! Wait for changes to take effect
  uint32_t ulDelay = DDR_CONFIG_DELAY_INTERVAL;
  while(ulDelay--);
  EMIF0->SDRAM_REF_CTRL                = DDR_CONFIG_SD_REF_CTRL_AFTER;
  EMIF0->SDRAM_REF_CTRL_SHDW           = DDR_CONFIG_SD_REF_CTRL_SHDW_AFTER;

  EMIF0->ZQ_CONFIG                     = DDR_CONFIG_ZQ;
  EMIF0->SDRAM_CONFIG                  = DDR_CONFIG_SD_CONFIG_AFTER;
  CONTROL_MODULE->CONTROL_EMIF_SDRAM_CONFIG = DDR_CONFIG_SD_CONFIG_AFTER;

  //! Switch to User Mode
  asm("    swi     #0;");
}

The following #defines are set:

#define DDR_CONFIG_PHY_CMD0_SLAVE_RATIO            (0x00000080UL)
#define DDR_CONFIG_PHY_CMD0_SLAVE_FORCE            (0x00000000UL)
#define DDR_CONFIG_PHY_CMD0_SLAVE_DELAY            (0x00000000UL)
#define DDR_CONFIG_PHY_CMD0_LOCK_DIFF              (0x00000000UL)
#define DDR_CONFIG_PHY_CMD0_INVERT_CLKOUT          (0x00000000UL)

#define DDR_CONFIG_PHY_CMD1_SLAVE_RATIO            (0x00000080UL)
#define DDR_CONFIG_PHY_CMD1_SLAVE_FORCE            (0x00000000UL)
#define DDR_CONFIG_PHY_CMD1_SLAVE_DELAY            (0x00000000UL)
#define DDR_CONFIG_PHY_CMD1_LOCK_DIFF              (0x00000000UL)
#define DDR_CONFIG_PHY_CMD1_INVERT_CLKOUT          (0x00000000UL)

#define DDR_CONFIG_PHY_CMD2_SLAVE_RATIO            (0x00000080UL)
#define DDR_CONFIG_PHY_CMD2_SLAVE_FORCE            (0x00000000UL)
#define DDR_CONFIG_PHY_CMD2_SLAVE_DELAY            (0x00000000UL)
#define DDR_CONFIG_PHY_CMD2_LOCK_DIFF              (0x00000000UL)
#define DDR_CONFIG_PHY_CMD2_INVERT_CLKOUT          (0x00000000UL)

#define DDR_CONFIG_PHY_DATA0_RD_DQS_SLAVE_RATIO    (0x00000012UL)
#define DDR_CONFIG_PHY_DATA0_WR_DQS_SLAVE_RATIO    (0x00000000UL)
#define DDR_CONFIG_PHY_DATA0_FIFO_WE_SLAVE_RATIO   (0x00000080UL)
#define DDR_CONFIG_PHY_DATA0_WR_DATA_SLAVE_RATIO   (0x00000040UL)

#define DDR_CONFIG_PHY_DATA1_RD_DQS_SLAVE_RATIO    (0x00000012UL)
#define DDR_CONFIG_PHY_DATA1_WR_DQS_SLAVE_RATIO    (0x00000000UL)
#define DDR_CONFIG_PHY_DATA1_FIFO_WE_SLAVE_RATIO   (0x00000080UL)
#define DDR_CONFIG_PHY_DATA1_WR_DATA_SLAVE_RATIO   (0x00000040UL)

#define DDR_CONFIG_CMD0_IOCTRL                     (0x0000018BUL)
#define DDR_CONFIG_CMD1_IOCTRL                     (0x0000018BUL)
#define DDR_CONFIG_CMD2_IOCTRL                     (0x0000018BUL)
#define DDR_CONFIG_DATA0_IOCTRL                    (0x0000018BUL)
#define DDR_CONFIG_DATA1_IOCTRL                    (0x0000018BUL)
#define DDR_CONFIG_IOCTRL                          (0x0FFFFFFFUL)
#define DDR_CONFIG_CKE_CTRL                        (0x00000001UL)

#define DDR_CONFIG_PHY_CTRL_1                      (0x00000005UL)
#define DDR_CONFIG_DYN_PWRDN                       (0x00000000UL)
#define DDR_CONFIG_PHY_CTRL_1_SHDW                 (0x00000005UL)
#define DDR_CONFIG_DYN_PWRDN_SHDW                  (0x00000000UL)
#define DDR_CONFIG_PHY_CTRL_2                      (0x00000005UL)

#define DDR_CONFIG_SD_TIM_1                        (0x0666B3C9UL)
#define DDR_CONFIG_SD_TIM_1_SHDW                   (0x0666B3C9UL)
#define DDR_CONFIG_SD_TIM_2                        (0x243631CAUL)
#define DDR_CONFIG_SD_TIM_2_SHDW                   (0x243631CAUL)
#define DDR_CONFIG_SD_TIM_3                        (0x0000033FUL)
#define DDR_CONFIG_SD_TIM_3_SHDW                   (0x0000033FUL)

#define DDR_CONFIG_SD_CONFIG_BEFORE                (0x41805332UL)
#define DDR_CONFIG_SD_REF_CTRL_BEFORE              (0x00004650UL)
#define DDR_CONFIG_SD_REF_CTRL_SHDW_BEFORE         (0x00004650UL)

#define DDR_CONFIG_DELAY_INTERVAL                  (5000UL)

#define DDR_CONFIG_SD_CONFIG_AFTER                 (0x41805332UL)
#define DDR_CONFIG_SD_REF_CTRL_AFTER               (0x0000081AUL)
#define DDR_CONFIG_SD_REF_CTRL_SHDW_AFTER          (0x0000081AUL)

#define DDR_CONFIG_ZQ                              (0x00000000UL)
Was it helpful?

Solution

Problem solved...

I went through the existing initialization and came across the fact, that obviously some of the registers weren't needed to be set. In my code I still set them with default values for completeness. Generally to have them around in case I need to configure them in some kind of later project with maybe a different RAM attached to it. I would never have thought doing so would break something. But it obviously did. I took all unneeded registers out of the setup and just programmed the necessary ones, and it worked! Also I let go of the two staged SDRAM_CONTROL and SDRAM_REF_CTRL setup, changing the settings after a delay to the final values. I just took the final values directly.

This code works:

  //! Switch to System Mode
  asm("    swi     #1;");

  //! Enable EMIF
  CM_PER->EMIF_CLKCTRL                 = 2;
  //! Poll for functional peripheral
  while (CM_PER->EMIF_CLKCTRL != 2);

  //! Enable VTP
  CONTROL_MODULE->VTP_CTRL             = 0;
  CONTROL_MODULE->VTP_CTRL             = 6;
  CONTROL_MODULE->VTP_CTRL            |=  (1 << 6);
  CONTROL_MODULE->VTP_CTRL            &= ~(1 << 0);
  CONTROL_MODULE->VTP_CTRL            |=  (1 << 0);
  //! Poll for VTP ready
  while (!(CONTROL_MODULE->VTP_CTRL & (1 << 5)));

  //! Configure DDR Phy command macros
  DDR_PHY->CMD[0].SLAVE_RATIO          = DDR_CONFIG_PHY_CMD0_SLAVE_RATIO;
  DDR_PHY->CMD[0].INVERT_CLKOUT        = DDR_CONFIG_PHY_CMD0_INVERT_CLKOUT;

  DDR_PHY->CMD[1].SLAVE_RATIO          = DDR_CONFIG_PHY_CMD1_SLAVE_RATIO;
  DDR_PHY->CMD[1].INVERT_CLKOUT        = DDR_CONFIG_PHY_CMD1_INVERT_CLKOUT;

  DDR_PHY->CMD[2].SLAVE_RATIO          = DDR_CONFIG_PHY_CMD2_SLAVE_RATIO;
  DDR_PHY->CMD[2].INVERT_CLKOUT        = DDR_CONFIG_PHY_CMD2_INVERT_CLKOUT;

  //! Configure DDR Phy data macros
  DDR_PHY->DATA[0].RD_DQS_SLAVE_RATIO[0]  = DDR_CONFIG_PHY_DATA0_RD_DQS_SLAVE_RATIO;
  DDR_PHY->DATA[0].WR_DQS_SLAVE_RATIO[0]  = DDR_CONFIG_PHY_DATA0_WR_DQS_SLAVE_RATIO;
  DDR_PHY->DATA[0].WRLVL_INIT_RATIO[0]    = DDR_CONFIG_PHY_DATA0_WRLVL_INIT_RATIO;
  DDR_PHY->DATA[0].GATELVL_INIT_RATIO[0]  = DDR_CONFIG_PHY_DATA0_GATELVL_INIT_RATIO;
  DDR_PHY->DATA[0].FIFO_WE_SLAVE_RATIO[0] = DDR_CONFIG_PHY_DATA0_FIFO_WE_SLAVE_RATIO;
  DDR_PHY->DATA[0].WR_DATA_SLAVE_RATIO[0] = DDR_CONFIG_PHY_DATA0_WR_DATA_SLAVE_RATIO;
  DDR_PHY->DATA[0].DLL_LOCK_DIFF          = DDR_CONFIG_PHY_DATA0_DLL_LOCK_DIFF;

  DDR_PHY->DATA[1].RD_DQS_SLAVE_RATIO[0]  = DDR_CONFIG_PHY_DATA1_RD_DQS_SLAVE_RATIO;
  DDR_PHY->DATA[1].WR_DQS_SLAVE_RATIO[0]  = DDR_CONFIG_PHY_DATA1_WR_DQS_SLAVE_RATIO;
  DDR_PHY->DATA[1].WRLVL_INIT_RATIO[0]    = DDR_CONFIG_PHY_DATA1_WRLVL_INIT_RATIO;
  DDR_PHY->DATA[1].GATELVL_INIT_RATIO[0]  = DDR_CONFIG_PHY_DATA1_GATELVL_INIT_RATIO;
  DDR_PHY->DATA[1].FIFO_WE_SLAVE_RATIO[0] = DDR_CONFIG_PHY_DATA1_FIFO_WE_SLAVE_RATIO;
  DDR_PHY->DATA[1].WR_DATA_SLAVE_RATIO[0] = DDR_CONFIG_PHY_DATA1_WR_DATA_SLAVE_RATIO;
  DDR_PHY->DATA[1].DLL_LOCK_DIFF          = DDR_CONFIG_PHY_DATA1_DLL_LOCK_DIFF;

  //! Set control registers
  CONTROL_MODULE->DDR_CMD0_IOCTRL      = DDR_CONFIG_CMD_IOCTRL;
  CONTROL_MODULE->DDR_CMD1_IOCTRL      = DDR_CONFIG_CMD_IOCTRL;
  CONTROL_MODULE->DDR_CMD2_IOCTRL      = DDR_CONFIG_CMD_IOCTRL;
  CONTROL_MODULE->DDR_DATA0_IOCTRL     = DDR_CONFIG_DATA_IOCTRL;
  CONTROL_MODULE->DDR_DATA1_IOCTRL     = DDR_CONFIG_DATA_IOCTRL;
  CONTROL_MODULE->DDR_IO_CTRL         &= DDR_CONFIG_IOCTRL;
  CONTROL_MODULE->DDR_CKE_CTRL        |= DDR_CONFIG_CKE_CTRL;

  //! Set memory interface control registers
  EMIF0->DDR_PHY_CTRL_1                = DDR_CONFIG_PHY_CTRL_1;
  EMIF0->DDR_PHY_CTRL_1_SHDW           = DDR_CONFIG_PHY_CTRL_1;
  EMIF0->DDR_PHY_CTRL_2                = DDR_CONFIG_PHY_CTRL_2;

  //! Set memory interface timing registers
  EMIF0->SDRAM_TIM_1                   = DDR_CONFIG_SD_TIM_1;
  EMIF0->SDRAM_TIM_1_SHDW              = DDR_CONFIG_SD_TIM_1;
  EMIF0->SDRAM_TIM_2                   = DDR_CONFIG_SD_TIM_2;
  EMIF0->SDRAM_TIM_2_SHDW              = DDR_CONFIG_SD_TIM_2;
  EMIF0->SDRAM_TIM_3                   = DDR_CONFIG_SD_TIM_3;
  EMIF0->SDRAM_TIM_3_SHDW              = DDR_CONFIG_SD_TIM_3;

  EMIF0->SDRAM_REF_CTRL                = DDR_CONFIG_SD_REF_CTRL;
  EMIF0->SDRAM_REF_CTRL_SHDW           = DDR_CONFIG_SD_REF_CTRL;

  EMIF0->SDRAM_CONFIG                  = DDR_CONFIG_SD_CONFIG;

  //! Poll for DDR Phy ready indicator
  while(!(EMIF0->STATUS & (1 << 2)));

  //! Switch to User Mode
  asm("    swi     #0;");

The #defines posted inside the question are all correct.

OTHER TIPS

If you have taken this code from an existing project that works, it is unlikely to be a sequence issue. The timing and signalling parameter of SD-RAM are critical and vary between devices, and the actual register values for timing related parameters will depend on the clock speed of your processor. So unless your DDR2 device is the same part as that used in the original project, and you are running the processor at the same speed, the parameters are unlikely to be correct.

You need to carefully match the settings you are applying to the memory controller to the parameters provided in tour RAM part's data sheet. This is often not straightforward as RAM vendors often define parameters from different references and using different terms than used by the processor vendor. Usually it is simplest to use the timing diagrams in both to select compatible parameters.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top