0

我在一个裸机项目中为德州仪器公司的 ICE 评估板上的 DDR2 内存初始化 EMIF 和 DDR_PHY 时遇到问题。我根据 StarterWare 引导加载程序示例中的序列编写了一个初始化序列。但是我无法让 DDR 工作。

控制器运行整个过程,但是我在调​​试器中执行的每一步 DDR 看起来都是随机的。我正在监视 0x80000000。使用调试器写入该区域也不起作用。状态寄存器显示 PHY 未就绪。

我错过了什么吗?我有一个或另一个命令的错误顺序吗?有人可以建议吗?

这是我的代码:

{
  //! 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;");
}

设置了以下#defines:

#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)
4

2 回答 2

1

问题解决了...

我经历了现有的初始化并发现了一个事实,显然某些寄存器不需要设置。在我的代码中,为了完整性,我仍然使用默认值设置它们。一般来说,如果我需要在以后的某种项目中配置它们,可能会有不同的 RAM 连接到它。我从没想过这样做会破坏某些东西。但它显然做到了。我把所有不需要的寄存器都从设置中取出,只对必要的寄存器进行了编程,它起作用了!此外,我放弃了两个阶段性的 SDRAM_CONTROL 和 SDRAM_REF_CTRL 设置,在延迟后将设置更改为最终值。我只是直接取了最终值。

此代码有效:

  //! 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;");

问题内张贴的#defines 都是正确的。

于 2014-08-06T07:09:49.557 回答
0

如果您从一个有效的现有项目中获取此代码,则不太可能是序列问题。SD-RAM 的时序和信号参数至关重要,并且因设备而异,时序相关参数的实际寄存器值将取决于处理器的时钟速度。因此,除非您的 DDR2 设备与原始项目中使用的部件相同,并且您以相同的速度运行处理器,否则参数不太可能是正确的。

您需要仔细地将应用到内存控制器的设置与巡演 RAM 部分数据表中提供的参数相匹配。这通常并不简单,因为 RAM 供应商经常从不同的参考文献中定义参数,并使用与处理器供应商不同的术语。通常使用两者中的时序图来选择兼容参数是最简单的。

于 2014-04-18T07:15:15.003 回答