NXP

IMX6Q的DDR3初始化配置

2019-07-12 13:05发布

  处理器:IMX6Q5EYM10ADDDR3时钟频率400MHz、528MHz
      DDR3:NT5CB128M16BP-CG16位667MHz时钟频率1333MHz数据频率
      相比于Exynos4412的内存,飞思卡尔IMX6的内存比较麻烦,耗费了比较多的时间调试才稳定,当然这也是因为我无缘无故改掉了内存拓扑结构和换了内存芯片型号的原因。
      飞思卡尔的方案里提供了两种很合适的拓扑方案,这两种方案适用于四片内存芯片的情况。第一种方案自然是采用fly-by拓扑,fly-by是DDR3的推荐使用拓扑结构,使用fly-by拓扑需要注意内存芯片是否有Write Leveling功能,没有该功能的芯片不能使用fly-by拓扑。虽然fly-by拓扑处理高频信号效果 优于星型拓扑,但需要在八层以上的板子上使用,才能很好的体现出这种拓扑的优势,对于一般的六层甚至四层板,可以考虑方案二。第二种方案采用星型拓扑,为了避免分支走线过长引起的分支信号反射和容性干扰,将四块内存芯片分为两组分别放在TOP层和BOTTOM层,这样降低分支长度提高星型拓扑的应用范围。       硬件设计参照天嵌的E9开发板设计,令人遗憾的是设计之初没有找到飞思卡尔提供的设计手册,也没有完全按照E9的方案设计,在6层板上使用了菊花链的拓扑结构,可想而知地址线的走线能有多长,达到了4个inch的长度,硬件设计上就存在比较大的缺陷,所幸的是时钟信号与数据信号的长度差并没有太大,于是寄希望于DDR3地址线自动时间补偿和逆天的Write Leveling补上硬件设计上的漏洞。。       如果参数配置不对系统运行不稳定,甚至会无法启动,下面介绍的内容均是根据我个人在调试中遇到的问题得出的经验,仅供参考交流。
      IMX6Q的内存初始化程序放在uboot的board/freescale/mx6q_sabresd/flash_header.S文件中,E9提供的源码中没有这个文件,只有一个编译结果flash_header.module,可以通过反汇编指令:arm-linux-objdump -S -EB flash_header.module,获取该模块中的内容并自己写一个flash_header.S文件。       flash_header.S文件起始部分配置CPU内存引脚电气特性,如IO驱动电阻的值。驱动电阻值的大小需要根据PCB板中相应引脚走线阻抗设置。有些引脚引出来之后在TOP层或BOTTOM层走线,表层走线为微带线,微带线的阻抗一般是75ohm,对于这些引脚其驱动电阻值应设置在80ohm;有些引脚通过过孔直接引导内部走线层,带状线的阻抗一般为50ohm,这些引脚的驱动电阻值应设置在48ohm。IO驱动电阻的值必须仔细认真设置,特别是数据信号线和时钟信号线,因为它俩的频率最高。设置好IO驱动电阻值使信号在CPU端具有良好的阻抗特性,保证信号有良好的电气特性和质量,这是后期一切配置的基础条件,即时时序在匹配信号完整性受到干扰,内存仍然不能稳定运行。       IMX6Q的DDR控制和时序寄存器主要是0x021b0000~0x021b0040(0x021b4000~0x021b4040)。控制寄存器如MMDC1_MDCTL(0x021b0000)比较直观,设置起来不难,这里主要讲时序配置方法和一些重要时序参数。由于处理器端时钟频率(528MHz)和DDR3运行时钟频率(667MHz)不同,处理器时序配置不能简单按照528MHz或667MHz的标准配置,也就是不能照抄DDR的数据手册进行配置。外频与内频不一致时,通常以频率主动方为设置单位,根据被动方的时钟要求设置主动方周期数。内存时序参数时以IMX6Q内存时钟周期1.894ns为基本单位,如667MHz的DDR3要求列地址选通脉冲时延CL=13.125ns,则MMDC0_MDCFG0(0x021b000c)寄存器的tCL设置为13.125ns/1.894ns=7cycles(MMDC0_MDCFG0[3:0]=4),这里如果简单粗暴直接使用DDR3时序参数CL=9cycles是不正确的。其他时序参数也要用类似方法计算获得。时序配置方面IMX6Q提供了时序计算工具I.MX6DQSDL DDR3 Script Aid V0.10,在该excel表格的Register Configuration项填好相应参数,会自动生成IMX6Q寄存器的配置,简化时序计算的过程。       虽然飞思卡尔提供了时序配置计算工具,但有几个重要的时序参数需要注意。在处理器端配置处理器寄存器中tCL=tRCD=tRP=7cycles,那么通过0x021b001c寄存器去配置内存芯片寄存器的时候,要求内存tCL=7cycles与处理器参数相同,即MR0[6:4,2]=6。处理器时序参数与内存时序参数不一致的时候,处理器将无法启动。Write Leveling、DQS Gating和数据读写校准这几个参数会影响系统稳定性,不合适的参数使系统启动的时候就出现内存错误,飞思卡尔提供DDR_Stress_Tester工具用于获取这些校准参数,但个人经验觉得这个工具得到的结果并不理想,沿用原本的参数会更稳定一些。       配置代码如下: [plain] view plain copy  print?在CODE上查看代码片派生到我的代码片
  1. #include   
  2. #include   
  3.   
  4. #ifdef  CONFIG_FLASH_HEADER  
  5. #ifndef CONFIG_FLASH_HEADER_OFFSET  
  6. # error "Must define the offset of flash header"  
  7. #endif  
  8.   
  9. #define CPU_2_BE_32(l)   
  10.        ((((l) & 0x000000FF) << 24) |   
  11.     (((l) & 0x0000FF00) << 8)  |   
  12.     (((l) & 0x00FF0000) >> 8)  |   
  13.     (((l) & 0xFF000000) >> 24))  
  14.   
  15. #define MXC_DCD_ITEM(i, addr, val)     
  16. dcd_node_##i:                          
  17.         .word CPU_2_BE_32(addr) ;       
  18.         .word CPU_2_BE_32(val)  ;       
  19.   
  20. .section ".text.flasheader", "x"  
  21.     b   _start  
  22.     .org    CONFIG_FLASH_HEADER_OFFSET  
  23.   
  24. ivt_header:       .word 0x402000D1 /* Tag=0xD1, Len=0x0020, Ver=0x40 */  
  25. app_code_jump_v:  .word _start  
  26. reserv1:          .word 0x0  
  27. dcd_ptr:          .word dcd_hdr  
  28. boot_data_ptr:    .word boot_data  
  29. self_ptr:         .word ivt_header  
  30. app_code_csf:     .word 0x0  
  31. reserv2:          .word 0x0  
  32.   
  33. boot_data:        .word TEXT_BASE  
  34. image_len:        .word _end_of_copy  - TEXT_BASE + CONFIG_FLASH_HEADER_OFFSET  
  35. plugin:           .word 0x0  
  36.   
  37. dcd_hdr:          .word 0x40a002D2 /* Tag=0xD2, Len=83*8 + 4 + 4, Ver=0x40 */  
  38. write_dcd_cmd:    .word 0x049c02CC /* Tag=0xCC, Len=83*8 + 4, Param=0x04 */  
  39.    
  40. /* DCD */  
  41. //corrected to 2GB MT41K256M16HA-125:E based on Sabre AI  
  42. MXC_DCD_ITEM(1, IOMUXC_BASE_ADDR + 0x798, 0x000C0000)  
  43. MXC_DCD_ITEM(2, IOMUXC_BASE_ADDR + 0x758, 0x00000000)  
  44.   
  45. MXC_DCD_ITEM(3, IOMUXC_BASE_ADDR + 0x588, 0x00000030)   //CLK_0  
  46. MXC_DCD_ITEM(4, IOMUXC_BASE_ADDR + 0x594, 0x00000030)   //CLK_1  
  47.   
  48. MXC_DCD_ITEM(5, IOMUXC_BASE_ADDR + 0x56c, 0x00000030)   //ADDR_OHM  
  49. MXC_DCD_ITEM(6, IOMUXC_BASE_ADDR + 0x578, 0x00000030)   //ADDR_OHM  
  50. MXC_DCD_ITEM(7, IOMUXC_BASE_ADDR + 0x74c, 0x00000030)   //ADDR_OHM  
  51.    
  52. MXC_DCD_ITEM(8, IOMUXC_BASE_ADDR + 0x57c, 0x00000030)   //XIA CMOS_RSET  
  53.    
  54. MXC_DCD_ITEM(9, IOMUXC_BASE_ADDR + 0x58c, 0x00000000)  
  55. MXC_DCD_ITEM(10, IOMUXC_BASE_ADDR + 0x59c, 0x00000030)  
  56. MXC_DCD_ITEM(11, IOMUXC_BASE_ADDR + 0x5a0, 0x00000030)  
  57. MXC_DCD_ITEM(12, IOMUXC_BASE_ADDR + 0x78c, 0x00000030)  
  58.    
  59. MXC_DCD_ITEM(13, IOMUXC_BASE_ADDR + 0x750, 0x00020000)  //XIA DQS_DIFF  
  60.    
  61. MXC_DCD_ITEM(14, IOMUXC_BASE_ADDR + 0x5a8, 0x00000018)  //120ohm效果变差,60ohm效果更差  
  62. MXC_DCD_ITEM(15, IOMUXC_BASE_ADDR + 0x5b0, 0x00000018)  //DQS  
  63. MXC_DCD_ITEM(16, IOMUXC_BASE_ADDR + 0x524, 0x00000018)  //DQS  
  64. MXC_DCD_ITEM(17, IOMUXC_BASE_ADDR + 0x51c, 0x00000018)  //DQS  
  65. MXC_DCD_ITEM(18, IOMUXC_BASE_ADDR + 0x518, 0x00000018)  //DQS  
  66. MXC_DCD_ITEM(19, IOMUXC_BASE_ADDR + 0x50c, 0x00000018)  //DQS  
  67. MXC_DCD_ITEM(20, IOMUXC_BASE_ADDR + 0x5b8, 0x00000018)  //DQS  
  68. MXC_DCD_ITEM(21, IOMUXC_BASE_ADDR + 0x5c0, 0x00000018)  //DQS  
  69.    
  70. MXC_DCD_ITEM(22, IOMUXC_BASE_ADDR + 0x774, 0x00020000)  //DP_DIFF  
  71.    
  72. MXC_DCD_ITEM(23, IOMUXC_BASE_ADDR + 0x784, 0x00000018)  //DP  
  73. MXC_DCD_ITEM(24, IOMUXC_BASE_ADDR + 0x788, 0x00000018)  //DP  
  74. MXC_DCD_ITEM(25, IOMUXC_BASE_ADDR + 0x794, 0x00000018)  //DP  
  75. MXC_DCD_ITEM(26, IOMUXC_BASE_ADDR + 0x79c, 0x00000018)  //DP  
  76. MXC_DCD_ITEM(27, IOMUXC_BASE_ADDR + 0x7a0, 0x00000018)  //DP  
  77. MXC_DCD_ITEM(28, IOMUXC_BASE_ADDR + 0x7a4, 0x00000018)  //DP  
  78. MXC_DCD_ITEM(29, IOMUXC_BASE_ADDR + 0x7a8, 0x00000018)  //DP  
  79. MXC_DCD_ITEM(30, IOMUXC_BASE_ADDR + 0x748, 0x00000018)  //DP  
  80.    
  81. MXC_DCD_ITEM(31, IOMUXC_BASE_ADDR + 0x5ac, 0x00000018)  //DQM  
  82. MXC_DCD_ITEM(32, IOMUXC_BASE_ADDR + 0x5b4, 0x00000018)  //DQM  
  83. MXC_DCD_ITEM(33, IOMUXC_BASE_ADDR + 0x528, 0x00000018)  //DQM  
  84. MXC_DCD_ITEM(34, IOMUXC_BASE_ADDR + 0x520, 0x00000018)  //DQM  
  85. MXC_DCD_ITEM(35, IOMUXC_BASE_ADDR + 0x514, 0x00000018)  //DQM  
  86. MXC_DCD_ITEM(36, IOMUXC_BASE_ADDR + 0x510, 0x00000018)  //DQM  
  87. MXC_DCD_ITEM(37, IOMUXC_BASE_ADDR + 0x5bc, 0x00000018)  //DQM  
  88. MXC_DCD_ITEM(38, IOMUXC_BASE_ADDR + 0x5c4, 0x00000018)  //DQM  
  89.    
  90. MXC_DCD_ITEM(39, MMDC_P0_BASE_ADDR + 0x800, 0xA1390003)  
  91.    
  92. # write leveling  
  93. MXC_DCD_ITEM(40, MMDC_P0_BASE_ADDR + 0x80c, 0x001F001F) //Bety1-0     
  94. MXC_DCD_ITEM(41, MMDC_P0_BASE_ADDR + 0x810, 0x001F001F) //Bety3-2     
  95. MXC_DCD_ITEM(42, MMDC_P1_BASE_ADDR + 0x80c, 0x001F001F) //Bety5-4     
  96. MXC_DCD_ITEM(43, MMDC_P1_BASE_ADDR + 0x810, 0x001F001F) //Bety7-6     
  97.   
  98. # DQS gating, read delay, write delay calibration values  
  99. MXC_DCD_ITEM(44, MMDC_P0_BASE_ADDR + 0x83c, 0x4333033f)   
  100. MXC_DCD_ITEM(45, MMDC_P0_BASE_ADDR + 0x840, 0x032c031d)   
  101. MXC_DCD_ITEM(46, MMDC_P1_BASE_ADDR + 0x83C, 0x43200332)   
  102. MXC_DCD_ITEM(47, MMDC_P1_BASE_ADDR + 0x840, 0x031a026a)   
  103.    
  104. MXC_DCD_ITEM(48, MMDC_P0_BASE_ADDR + 0x848, 0x4d464746)   
  105. MXC_DCD_ITEM(49, MMDC_P1_BASE_ADDR + 0x848, 0x47453f4d)   
  106.    
  107. MXC_DCD_ITEM(50, MMDC_P0_BASE_ADDR + 0x850, 0x3e434440)   
  108. MXC_DCD_ITEM(51, MMDC_P1_BASE_ADDR + 0x850, 0x47384839)   
  109.   
  110. MXC_DCD_ITEM(52, MMDC_P0_BASE_ADDR + 0x81c, 0x33333333)  
  111. MXC_DCD_ITEM(53, MMDC_P0_BASE_ADDR + 0x820, 0x33333333)  
  112. MXC_DCD_ITEM(54, MMDC_P0_BASE_ADDR + 0x824, 0x33333333)  
  113. MXC_DCD_ITEM(55, MMDC_P0_BASE_ADDR + 0x828, 0x33333333)  
  114. MXC_DCD_ITEM(56, MMDC_P1_BASE_ADDR + 0x81c, 0x33333333)  
  115. MXC_DCD_ITEM(57, MMDC_P1_BASE_ADDR + 0x820, 0x33333333)  
  116. MXC_DCD_ITEM(58, MMDC_P1_BASE_ADDR + 0x824, 0x33333333)  
  117. MXC_DCD_ITEM(59, MMDC_P1_BASE_ADDR + 0x828, 0x33333333)  
  118.    
  119. MXC_DCD_ITEM(60, MMDC_P0_BASE_ADDR + 0x8b8, 0x00000800)  
  120. MXC_DCD_ITEM(61, MMDC_P1_BASE_ADDR + 0x8b8, 0x00000800)  
  121.   
  122. MXC_DCD_ITEM(62, MMDC_P0_BASE_ADDR + 0x004, 0x00020036)  
  123. MXC_DCD_ITEM(63, MMDC_P0_BASE_ADDR + 0x008, 0x09444040)  
  124. MXC_DCD_ITEM(64, MMDC_P0_BASE_ADDR + 0x00c, 0x54597974)   
  125. MXC_DCD_ITEM(65, MMDC_P0_BASE_ADDR + 0x010, 0xDB338F64)   
  126. MXC_DCD_ITEM(66, MMDC_P0_BASE_ADDR + 0x014, 0x01FF00DB)  
  127. MXC_DCD_ITEM(67, MMDC_P0_BASE_ADDR + 0x018, 0x00001740)   
  128.    
  129. MXC_DCD_ITEM(68, MMDC_P0_BASE_ADDR + 0x01c, 0x00008000)  
  130. MXC_DCD_ITEM(69, MMDC_P0_BASE_ADDR + 0x02c, 0x000026D2)  
  131. MXC_DCD_ITEM(70, MMDC_P0_BASE_ADDR + 0x030, 0x00591023)   
  132. MXC_DCD_ITEM(71, MMDC_P0_BASE_ADDR + 0x040, 0x00000027)  
  133.   
  134. MXC_DCD_ITEM(72, MMDC_P0_BASE_ADDR + 0x000, 0x831A0000) //col=10,row=14 128M x 16b = 256MB  
  135.    
  136. MXC_DCD_ITEM(73, MMDC_P0_BASE_ADDR + 0x01c, 0x04088032) //Rtt_WR=120ohm  
  137. MXC_DCD_ITEM(74, MMDC_P0_BASE_ADDR + 0x01c, 0x00008033)  
  138. MXC_DCD_ITEM(75, MMDC_P0_BASE_ADDR + 0x01c, 0x00048031) //Rtt_NOM=60ohm  
  139. MXC_DCD_ITEM(76, MMDC_P0_BASE_ADDR + 0x01c, 0x09308030) //内存芯片的CAS Latency要和处理器相同  
  140. MXC_DCD_ITEM(77, MMDC_P0_BASE_ADDR + 0x01c, 0x04008040)  
  141.    
  142. MXC_DCD_ITEM(78, MMDC_P0_BASE_ADDR + 0x020, 0x00007800) //刷新频率  
  143.    
  144. MXC_DCD_ITEM(79, MMDC_P0_BASE_ADDR + 0x818, 0x00011117) //Rtt_NOM=120ohm稳定些  
  145. MXC_DCD_ITEM(80, MMDC_P1_BASE_ADDR + 0x818, 0x00011117)  
  146.    
  147. MXC_DCD_ITEM(81, MMDC_P0_BASE_ADDR + 0x004, 0x00025576)  
  148. MXC_DCD_ITEM(82, MMDC_P0_BASE_ADDR + 0x404, 0x00011006)  
  149. MXC_DCD_ITEM(83, MMDC_P0_BASE_ADDR + 0x01c, 0x00000000)  
  150. #endif  
转自 http://blog.csdn.net/qq405180763/article/details/44977449