裸机——DDR

1.DDR介绍

  DDR,是SDRAM的改进,是双通道的SDRAM,

  SDRAM是同步动态随机访问存储器。

  SDRAM与SRAM相对于,二者的特点是:

    SDRAM  需要初始化,使用时许访问,价格便宜。

    SRAM    不需要初始化,价格贵。

  与之相似的还有 Norflash 和 Nandflash

  RAM之所掉电丢失数据,是因为RAM使用电容实现0,1二进制表示。

  最后,还需要了解,地球上制造RAM的公司多,但是一线大厂只有几家,一线大厂的RAM各有不同,但是二线厂商的RAM都向一线厂商靠,所以二线厂商的DDR如果是使用三星的SoC,那么直接使用三星的DDR初始化程序都可能成功初始化二线厂商的DDR。

2.初始化DDR

  (1)首先看原理图

    看原理图的目的:

      获得板子上的DDR芯片名

      知道板子上的DDR是怎么接的

  下面是 SoC 上给DDR的接口:

  可以看出:

    这款SoC有三个接口,

    每个接口的先分为三类:数据线,地址线,时序线,

    另外注意到地址线并不是 32根,而是14根,这说明一个接口可以连接的内存片存储最大值为 2^14B

  然后再看接的内存片的原理图:

  可以看出:

    实际使用SoC内存接口为:Port1, Port2

    芯片正好与SoC的接口对齐,也分为:数据线,地址线,时序线,并且注意BA0,BA1,BA2位片选线(后面会用)

    芯片无晶振,说明使用SoC提供频率,由于SoC频率低,所以芯片本身需要倍频,

    一片内存位宽为16位,使用两片构成32位。

    芯片信号:K4T1G164QQ

  

  总结:

      通过查看原理图,了解开发板上芯片和SoC的连接情况,和芯片编号。

  接下来利用芯片编号,找到芯片的手册,大致了解下芯片情况。

  芯片编号为 K4T1G164QQ

   芯片手册是各种规格的集合,需要根据芯片编号得知自己的芯片规格,再看对应的说明

  芯片编号的解读方法如下:

  K4T1G164QQ

  1 :K 说明是三星的

  2: 4 说明是DRAM

  3:T  是 DDR2 

  4:1G 密度和刷新速度,为 1Gb也就是 128MB

  5:16 位宽为16bit

  6:4   8Bank

  7:电压

  后面没用了

  总结为 : DDR2  1Gb  16bit 8Bank

  根据上面数据找到这张图

   现在需要知道内存是如何确定每个 bit 的位置的。

   内存是多个 Bank组成,每个Bank是个二维地址有col和row确定的存储单元,这样就构成了三维的矩阵。

    所以每个bit先要确定 Bank,然后再是 row 和 col。

    对应上面的图可以知道,一共17根线传输这些地址数据,3位用来选Bank(BA0,BA1,BA2),也就 8 Bank

    10位 Col,14位Row,所以 1Bank 就是 2^24 B = 16MB

    8Bank = 128MB

  完成了上面工作,对板子上的内存芯片就有了足够的认识,

  就下来应该结合 SoC UM 和 参考代码进行分析,

  因为知道使用的是DDR2,所以看SoC UM 对DDR2初始化的部分,一共有27步,应该结合参考代码看。

(1)设置驱动强度

    /* DMC0 Drive Strength (Setting 2X) */
    
    ldr    r0, =ELFIN_GPIO_BASE

    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP1_0DRV_SR_OFFSET]        // 寄存器中对应0b10,就是2X

    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]

    
    /* DMC1 Drive Strength (Setting 2X) */
    
    ldr    r0, =ELFIN_GPIO_BASE
    
    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP2_0DRV_SR_OFFSET]

    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP2_1DRV_SR_OFFSET]

    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP2_2DRV_SR_OFFSET]

    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP2_3DRV_SR_OFFSET]

    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP2_4DRV_SR_OFFSET]

    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP2_5DRV_SR_OFFSET]

    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP2_6DRV_SR_OFFSET]

    ldr    r1, =0x0000AAAA
    str    r1, [r0, #MP2_7DRV_SR_OFFSET]

    ldr    r1, =0x00002AAA
    str    r1, [r0, #MP2_8DRV_SR_OFFSET]

(2)设置PLL,因为DDR使用SoC提供时钟,频率太低,需要倍频,所以需要使用PLL

    /* DMC0 initialization at single Type*/
    ldr    r0, =APB_DMC_0_BASE

    ldr    r1, =0x00101000                @PhyControl0 DLL parameter setting, manual 0x00101000
    str    r1, [r0, #DMC_PHYCONTROL0]

    ldr    r1, =0x00000086                @PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case
    str    r1, [r0, #DMC_PHYCONTROL1]

    ldr    r1, =0x00101002                @PhyControl0 DLL on
    str    r1, [r0, #DMC_PHYCONTROL0]

    ldr    r1, =0x00101003                @PhyControl0 DLL start
    str    r1, [r0, #DMC_PHYCONTROL0]

find_lock_val:
    ldr    r1, [r0, #DMC_PHYSTATUS]        @Load Phystatus register value
    and    r2, r1, #0x7
    cmp    r2, #0x7                @Loop until DLL is locked
    bne    find_lock_val
    
    and    r1, #0x3fc0 
    mov    r2, r1, LSL #18
    orr    r2, r2, #0x100000
    orr    r2 ,r2, #0x1000    
        
    orr    r1, r2, #0x3                @Force Value locking
    str    r1, [r0, #DMC_PHYCONTROL0]

这一步和时序相关,看不懂

    ldr    r1, =0x0FFF2010                @ConControl auto refresh off
    str    r1, [r0, #DMC_CONCONTROL]

对应文档中的这几步

 接下来

#define DMC0_MEMCONFIG_0 0x20F01323 // MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
#define
DMC1_MEMCONTROL 0x00202400 // MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off

ldr r1, =DMC0_MEMCONTROL @MemControl BL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
str r1, [r0, #DMC_MEMCONTROL]

ldr r1, =DMC0_MEMCONFIG_0 @MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
str r1, [r0, #DMC_MEMCONFIG0]

这里按照硬件连接情况设置。

接下来比较重要

    ldr    r1, =DMC0_MEMCONFIG_1            @MemConfig1    #define DMC0_MEMCONFIG_1    0x30F00312    // MemConfig1        默认值
    str    r1, [r0, #DMC_MEMCONFIG1]

看UM

可以看出,31-24设置内存的基地址,基地址该如何设置应该看SoC安排的Memory Map

  地址向上生长,DRAM0使用 0x3000_0000

  23-16是使用掩码的方式设置长度,根据 Memory Map 可以看出DRAM0长度最大0x3FFF_FFFF,这里设置的也是这个

其他的按照前面查的数据填。

  

  其他的代码基本上时序,没得可以变的,也看不懂。

  这样 DDR的初始化就完了。

总结:

  通过这次初始化,学习如何使用芯片手册,SoC手册,参考代码,原理图。

  简单说是:

    先看原理图,了解SoC和芯片实际连接,和使用的芯片类型。

    再看芯片手册,了解下芯片,当然前提需要知道硬件的基本常识。

    再依照参考代码看SoC手册,期间需要结合芯片手册确定某些特殊数据。

  

  可以看出 DDR 的初始化基本上没得可以改的,也不会改,

  需要注意的就是内存的起始地址和长度的设置部分,这里可以变通。

猜你喜欢

转载自www.cnblogs.com/yangxinrui/p/9926731.html
ddr
今日推荐