我在一个裸金属项目中初始化德州仪器ICE评估板上DDR2内存的EMIF和DDR_PHY时遇到问题。我根据StarterWare引导程序示例中的init序列编写了一个init序列。然而,我无法让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;");
}
设置了以下#定义:
#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)
问题已解决。。。
我进行了现有的初始化,发现很明显,有些寄存器不需要设置。在我的代码中,为了完整性,我仍然使用默认值设置它们。通常情况下,如果我需要在以后的项目中配置它们,可能会附带一个不同的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;");
问题中张贴的#define
都是正确的。
如果您从一个有效的现有项目中获取了此代码,则不太可能是序列问题。SD-RAM的定时和信号参数至关重要,并且在不同设备之间有所不同,与定时相关的参数的实际寄存器值将取决于处理器的时钟速度。因此,除非你的DDR2设备与原始项目中使用的设备相同,并且你以相同的速度运行处理器,否则参数不太可能是正确的。
您需要将应用于内存控制器的设置与tour RAM部件数据表中提供的参数仔细匹配。这通常并不简单,因为RAM供应商通常从不同的参考文献中定义参数,并使用与处理器供应商不同的术语。通常,使用两者中的时序图来选择兼容的参数是最简单的。