u-boot 移植 --->4、Tiny210核心板的DDR初始化下详解

RAM的原理简单学习

     DDR是RAM的一种,RAM常见的类型有SRAM,SDRAM,DDR他们的共同特点是,随机存储意味着读写速度快,掉电后数据丢失,所以常用来存储程序中的变量。

SRAM

    静态随机存储器英文是static random-access memory 就是保持上电就可以保存数据而不需要刷新。数据线和地址线分离以IS62WV51216这个芯片为例,他数据位宽为16,大小为1MB,地址线宽是19。所以可以访问的空间大小就是2的19次方即524288=512KB,然后数据线是16位了,所以512KB*2 就是这个芯片的全部容量。然后在加上一些必要的控制线比如片选,字节选择等就可以完成读写控制,他的特点是不需要刷新读写速度快,但是价格高STM32单片机内部的RAM就是这种的。

SDRAM

     同步动态随机存储器英文是 synchronous Dynamic random access memory ,他就是为了解决SRAM的成本高的问题而被发明出来的,同步则说明SDRAM工作时需要时钟线,动态是因为需要不断的刷新从而避免数据丢失。他的特点是集成度高,功耗低,成本低,适合做大容量存储。他的发展过程是SDRAM,DDR SDRAM,DDR2 SDRAM,DDR3 SDRAM,DDR4 SDRAM 。同样本次也找一个芯片来学习,W9825G6KH为例,他是一个16bit位宽的32M的SDRAM,速度常见为200Mhz。SDRAM 的组成就相对复杂一些。

CLK:时钟

CKE:时钟使能

CS:片选

RAS;行选通

CAS:列选通

WE:写势能

A0-A12:地址线,其中A10比较特殊是预充电:关闭打开的行准备新的行。

BANK:SDRRAM多是由多个bank组成的,常见由2,4,8等,当前新有4个bank所以他有两个bank选择线BS0和BS1.

D0-D15:数据线

U/L DQM:高低字节选择,如果数据线是8bit宽就不需要。

DDR就是SDRAM的升级版本,工作原理相同,但不仅在时钟频率上提高,而写在一个时钟周期传输两次数据即上升沿和下降沿都传输数据。这就是预取2bit随着技术的发展预取已经可以在DDR3的时候做到8bit,所以对于速度的提高是成倍的。这里就不深究其实现原理。

这里主要就其寻址方式进行分析学习一下,同SDRAM一样DDR也是将地址线分为行和列地址通过行和列宣统信号来决定。就那当前举例的芯片来说,他讲地址线中的全部作为行地址而A0-A8作为列地址,所以可以寻址的空间就是2^13*2^9=4194304=4MB,数据位宽为2字节16bit所以真实可以寻址的空间是8M,然后这个芯片的总存储容量是32m,所以这里就是bank的作用了,前面的地址线寻址范围实际上是一个bank的空间,再加上bank选择线2^2=4  所以最后可以寻址的空间就是8*4 = 32M 的空间了。

Tiny210 的DDR配置

     我的板子是一个比较早的友善之臂的tiny210加他自家的TinySDK底板,不过DDR在核心板上所以核心板一样的原理都一样。核心板上一共有四颗DDR芯片型号为K4T1G084QQ-HCE6 ,通过查看手册知道这个芯片的是一个8bank的128M的内存芯片,具体的DDR初始化相关的参数配置细节这里不看了,主要看一下DDR的寻址配置。

    这个芯片的地址线是A0-A13一共14条地址线其中行地址占全部地址线,列地址为A0-A9共10条,数据线宽为8bit。所以通过前面的原理可以知道他的寻址空间是 2^14*2^10*8=134217728就是128Gb所以和芯片的大小刚刚好相同。现在来看友善的电路连接方式:

 

 

 

 

从图中可以看到友善采用的方式是将8片的数据脚并在一起从而组成一个数据位宽为32位的数据接口,所以最后地址线的寻址只需要1G/4=128M的寻址空间就可以完成整个板载内存的寻址访问。现在看来虽然很清晰但是刚开始配置这一块的时候还是迷茫了几个小时,最后没办法先去简单看了SDRAM的寻址原理之后在来看这儿就好多了。 首先要排除原理图中的ADDR14这个的影响,因为这个地址线是预留给2G的硬件的。

    

 

 

 通过芯片这部分的原理图可以看到,他将DDR芯片的bank脚B2接在了SOC的DDR控制器的片选脚Xm1CSn1/BA2上,而芯片的真正片选脚接在了Xm1CSn0上,所以这样看来应该是设计把两种方案,一是将四片DDR准备让控制器作为两片256的内存在驱动了,第二是作为一个DDR芯片来驱动此时这个脚就做BA2使用,在我自己调试这一部分时还是花了些时间搞明白这一点的。所以目前对于SOC的DDR控制器而言外部应该是接了32位数据位宽的4 bank的DDR芯片两片或者32位宽的8bank芯片;在DDR控制器看来是这样的外部的内存应该是数据位宽32bit,行地址14bit,列地址10bit,个bank的芯片2片或者行地址14bit,列地址10bit,个bank的芯片1片;当作为两片DDR内存时一个芯片的寻址范围就是2^14*2^10*4*4=268435456就是256MB,其中第一个4表示有4个bank,而后面的4 因为现在的数据线位32bit就是四个字节了,最后整个个SDRAM 的寻址空间就是256Gx2=512M;其次是 2^14*2^10*4*8 = 536890912即512M。其中第二种就是我目前U-boot的上512GB的DDR的配置方案了。说道这里的吐槽一下友善的DDR的裸机例程太坑了,虽然注释已经写了提供的历程不是他们的最后u-boot中的初始化配置方案,但是他的配置代码由多余的就不说了,还只是初始化了128M的内存空间,一开始以为大小最起码是正确的可能和他们真正用到u-boot中的初始化比稳定性差一点,所以我在移植u-boot时在代码重定向的地址就超过了128M所以就跑到了未初始化的地址范围外了,然后直接死掉这个问题查的我好苦最后才发现是给的DDR例程初始化只能128M内的空间可以正常使用。

最后来看一下代码的配置并验证一下,这里也是只重点看DRAM控制器的配置部分。参考三星的手册的部分我先在下面贴出来

 

 

 

 

 

 

s5p210_mem_init:

 

    @ 1. DMC0 Drive Strength (Setting 2X)
    ldr    r0, =S5PC100_GPIO_BASE
    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP1_0DRV_SR_OFFSET]
    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP1_1DRV_SR_OFFSET]
    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP1_2DRV_SR_OFFSET]
    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP1_3DRV_SR_OFFSET]
    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP1_4DRV_SR_OFFSET]
    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP1_5DRV_SR_OFFSET]
    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP1_6DRV_SR_OFFSET]
    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP1_7DRV_SR_OFFSET]
    ldr    r1, =0x00002AAA
    str    r1, [r0, #MP1_8DRV_SR_OFFSET]

    @ 2. ?????PHY DLL
    ldr    r0, =APB_DMC_0_BASE
    @step 3: PhyControl0 DLL parameter setting, manual 0x00101000
    ldr    r1, =0x00101000                    
    str    r1, [r0, #DMC_PHYCONTROL0]
    @PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case
    ldr    r1, =0x00000086                    
    str    r1, [r0, #DMC_PHYCONTROL1]
    
    @step 2: PhyControl0 DLL on
    ldr    r1, =0x00101002                    
    str    r1, [r0, #DMC_PHYCONTROL0]
    @step 4: PhyControl0 DLL start
    ldr    r1, =0x00101003                    
    str    r1, [r0, #DMC_PHYCONTROL0]

find_lock_val:
    @Loop until DLL is locked
    ldr    r1, [r0, #DMC_PHYSTATUS]            
    and    r2, r1, #0x7
    cmp    r2, #0x7                    
    bne    find_lock_val

    @Force Value locking
    and    r1, #0x3fc0
    mov    r2, r1, LSL #18
    orr    r2, r2, #0x100000
    orr    r2 ,r2, #0x1000
    orr    r1, r2, #0x3                    
    str    r1, [r0, #DMC_PHYCONTROL0]

    @ 3. ?????DMC0
    @step 5: ConControl auto refresh off
    ldr    r1, =0x0FFF2010                    
    str    r1, [r0, #DMC_CONCONTROL]
    @step 6: MemControl BL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
    @burst 4, num_chip 1  dw=32,type ddr2 ,PALL 0 
    @ 0x00202400  0x00212400
    @以上内容全部是参考网上的三星参考代码部分初始化的,一下才是我修改的
    @解释:
    @最低8个bit的00
        @关闭动态时钟
        @关闭power down 这部分都是降低功耗才会考虑的
    @ 4 我的DDR芯片是DDR2
    @ 2 前面说了用4个8bit组成了32bit数据宽度
    @ 0 四片等效成一片 前面也说了
    @ 2 根据手册只能是2
    ldr    r1, =0x00202400                
    str    r1, [r0, #DMC_MEMCONTROL]
    @step 7: MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
    @解释:
    @ 3 前面说了这个型号的DDR是内部由8个bank的
    @ 2  row地址宽14
    @ 3  col地址宽10
    @ 0  线性地址
    @ E0 不可用地址空间的掩码,手册中说如果你是F8则寻址空间就是0~0x07ffffff 很清楚把,
         所以我这里512M就是E0    就是0~0x1fffffff
    @ 20 这一片内存的基地址手册可以看出如果为20则就是0x20000000 所以DMC0上就是刚刚好全部映射20000000~3fffffff 
    ldr    r1, =0x20E00323                
    str    r1, [r0, #DMC_MEMCONFIG0]
    @MemConfig1 如果等效为两颗芯片,才需要配置第二个芯片
    @解释:
    @ 3 前面说了这个型号的DDR是内部由8个bank的,这里却配置为4个bank其实就是
        前面说的他巧用了一条片选线用来作为bank的第三条线
    @ 2  row地址宽14
    @ 3  col地址宽10
    @ 0  线性地址
    @ F0  不可用地址空间的掩码,手册中说如果你是F8则寻址空间就是0~0x07ffffff 很清楚把,所以我这里256M就是F0    
    @ 40 这一片内存的基地址手册可以看出如果为40则就是0x40000000加上我前面就是0x3fffffff 这里就是从RAM1的地址空间开始映射则就是
    @ldr    r1, =0x40F00323                
    @str    r1, [r0, #DMC_MEMCONFIG1]
    @以下内容全部是参考网上的三星参考代码部分初始化的,一上才是我修改的
    @step 8:PrechConfig
    ldr    r1, =0xFF000000                    
    str    r1, [r0, #DMC_PRECHCONFIG]
    @step 9:TimingAref    7.8us@133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)
    ldr    r1, =DMC0_TIMINGA_REF                
    str    r1, [r0, #DMC_TIMINGAREF]
    @TimingRow    for @200MHz
    ldr    r1, =DMC0_TIMING_ROW                
    str    r1, [r0, #DMC_TIMINGROW]
    @TimingData    CL=4
    ldr    r1, =DMC0_TIMING_DATA                
    str    r1, [r0, #DMC_TIMINGDATA]
    @TimingPower
    ldr    r1, =DMC0_TIMING_PWR                
    str    r1, [r0, #DMC_TIMINGPOWER]

    @ 4.DDR2 DRAM
    @DirectCmd    chip0 Deselect
    ldr    r1, =0x07000000                    
    str    r1, [r0, #DMC_DIRECTCMD]
    @step 16:DirectCmd    chip0 PALL
    ldr    r1, =0x01000000                    
    str    r1, [r0, #DMC_DIRECTCMD]
    @step 17:DirectCmd    chip0 EMRS2
    ldr    r1, =0x00020000                    
    str    r1, [r0, #DMC_DIRECTCMD]
    @step 18:DirectCmd    chip0 EMRS3
    ldr    r1, =0x00030000                    
    str    r1, [r0, #DMC_DIRECTCMD]
    @step 19:DirectCmd    chip0 EMRS1 (MEM DLL on, DQS# disable)
    ldr    r1, =0x00010400                    
    str    r1, [r0, #DMC_DIRECTCMD]
    @step 20:DirectCmd    chip0 MRS (MEM DLL reset) CL=4, BL=4
    ldr    r1, =0x00000542                    
    str    r1, [r0, #DMC_DIRECTCMD]
    @DirectCmd    chip0 PALL
    ldr    r1, =0x01000000                    
    str    r1, [r0, #DMC_DIRECTCMD]
    @DirectCmd    chip0 REFA
    ldr    r1, =0x05000000                    
    str    r1, [r0, #DMC_DIRECTCMD]
    @DirectCmd    chip0 REFA
    ldr    r1, =0x05000000                    
    str    r1, [r0, #DMC_DIRECTCMD]
    @DirectCmd    chip0 MRS (MEM DLL unreset)
    ldr    r1, =0x00000442                    
    str    r1, [r0, #DMC_DIRECTCMD]
    @DirectCmd    chip0 EMRS1 (OCD default)
    ldr    r1, =0x00010780                    
    str    r1, [r0, #DMC_DIRECTCMD]
    @DirectCmd    chip0 EMRS1 (OCD exit)
    ldr    r1, =0x00010400                    
    str    r1, [r0, #DMC_DIRECTCMD]
    @ConControl    auto refresh on
    ldr    r1, =0x0FFF2030                    
    str    r1, [r0, #DMC_CONCONTROL]
    @PwrdnConfig
    ldr    r1, =0xFFFF00FF                    
    str    r1, [r0, #DMC_PWRDNCONFIG]
    @MemControl    BL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
    ldr    r1, =DMC0_MEMCONTROL                    
    str    r1, [r0, #DMC_MEMCONTROL]

    mov    pc, lr

最后DDR的寻址范围就是0x20000000-0x40000000共512M的空间,采用间歇的四个点128M 256M  348M这几个点写入4K的数据再读出来验证是没有问题的,所以证实初始化是没有问题的。有空了在事实第二种等效成为两片芯片的情况配置一下试试。

有空试了一下,不成立最后分析原因,是因为硬件连接的方式只能支持这种配置,因为电路上将DDR芯片的片选接在了CS0上,如果配置为两片芯片,那么最终的后果就是只能访问256M的存储空间,因为配置成两片模式在访问第二片DDR的地址时,内存控制器就将片选脚失能了,此时DDR是无法访问的所以前面说的等效两片DDR的配置方式不成立。

posted @ 2020-07-07 23:04  Little_Village  阅读(1230)  评论(0编辑  收藏  举报