内存的初始化

内存的分类

内存由于具备访问速度快,访问方式简单等优点,成为了PC或者是嵌入式硬件平台上不可或缺的元件。在开始学习如何使用内存之前,非常有必要先了解一下内存的分类:

内存的初始化_第1张图片

DRAM:它的基本原件是小电容,电容可以在两个极板上保留电荷,但是需要定期的充电(刷新),否则数据会丢失。缺点:由于要定期刷新存储介质,存取速度较慢。

SRAM:它是一种具有静止存取功能的内存,不需要定期刷新电路就能保存它内部存储的数据。其优点:存取速度快; 但是缺点是:功耗大,成本高。常用作存储容量不高,但存取速度快的场合,比如stepping stone。

在嵌入式硬件体系中,除了CPU内部的“垫脚石”采用SRAM外,板载内存一般会采用DRAM,而DRAM又可以分为SDRAM,DDR,DDR2等。

SDRAM(Synchronous Dynamic Random AccessMemory):同步动态随机存储器
同步: 内存工作需要有同步时钟,内部的命令的发送与数据的传输都以该时钟为基准。
动态:存储阵列需要不断的刷新来保证数据不丢失。
随机:是指数据不是线性依次存储,而是自由指定地址进行数据读写。

DDR (Double Data Rate SDRAM),即“双倍速率同步动态随机存储器”。与早期的SDRAM相比,DDR 除了可以在时钟脉冲的上升沿传输数据,还可以在下降沿传输信号,这意味着在相同的工作频率下,DDR 的理论传输速率为SDRAM的两倍。DDR2 则在DDR 的基础上再次进行了改进,使得数据传输速率在DDR 的基础上再次翻倍。

内存的内部结构

表结构:
内存的内部如同表格,数据就存放在每个单元格中。数
据读写时,先指定行号(行地址),再指定列号(列地
址) ,我们就可以准确地找到所需要的单元格。而这张表格的称为:Logical Bank(L-Bank)。

内存的初始化_第2张图片

由于技术、成本等原因,一块内存不可能把所有的单元格都做到一个L-Bank,现在内存内部基本都会分割成4个L-Bank。

内存的初始化_第3张图片

需要向芯片提供以下3个信息来做到寻址:
1、L-Bank选择信号
2、行地址
3、列地址

OK6410开发板上的内存资源:
128M字节Mobile DDR内存。
2片KSX51163PC芯片:
每一片为:32M*16,总共128M

上面的16有两重含义:1、每个内存单元的大小为16位; 2、内存芯片的数据宽度为16位。ARM芯片的数据线为32位,剩下的16位连入另一个内存芯片。

这里写图片描述
4 * 2^13 * 2^10 = 32M

2440内存初始化

2440开发板配置的是SDRAM内存。

S3c2440芯片对外提供的引脚上,只给出了27根地址线Addr[0:26]。单靠芯片上的 27 根引脚,它只能访问128M 的外设空间。

为了扩大外设的访问范围,S3c2440芯片又提供了8个片选信号nGCS0~nGCS7。当某个片选信号nGCSx有效时,则可以通过27根地址线去访问对应这个片选的128MB空间。由于有8个片选,所以2440芯片能访问的外设空间总共为8*128MB=1GB。而1G (0x40000000)以上的空间,则安排给了2440内部的寄存器,访问这些内部的寄存器,则是通过32位的处理器内部总线来完成的。

一般把内存放置在片选6和片选7的位置,因此编写程序时,内存的起始地址为0x30000000。

内存的初始化_第4张图片

对于某一个地址,首先有存储控制器进行分解,然后对相应的存储设备进行操作。因此,对内存的初始化,其实就是对存储控制器的初始化。

初始化存储寄存器:(mini2440开发板)

#define mem_contrl 0x48000000
init_sdram:
    ldr r0, =mem_contrl 
    add r3, r0, #4*13 @最后一个地址
    adrl r1, mem_data

0:
    ldr r2, [r1], #4 @加载并且更新地址
    str r2, [r0], #4 @存储并且更新地址
    cmp r0, r3
    bne 0b           @不等于就跳到分支
    mov pc, lr

mem_data:
    .long 0x22000000 
    .long 0x00000700
    .long 0x00000700
    .long 0x00000700
    .long 0x00000700
    .long 0x00000700
    .long 0x00000700
    .long 0x00018001
    .long 0x00018001
    .long 0x008c04f5
    .long 0x000000b1
    .long 0x00000030
    .long 0x00000030

6410内存初始化

6410开发板配置的是DDR内存。

S3C6410处理器拥32位地址总线,其寻址空间为4GB。其中高2GB为保留区,低2GB区域又可划分为两部分:主存储区和外设区。

内存的初始化_第5张图片

保留区没有使用。外设区放置6410芯片中的寄存器,访问这些内部寄存器就通过这些地址。主存储区

主存储区的划分:

内存的初始化_第6张图片

boot启动镜像区:
这个区域的作用正如它的名字所述,是用来启动ARM系统的。但是这个区域并没有固定的存储 介质与之对应。而是通过修改启动选项,把不同的启动介质映射到该区域。比如说选择了IROM 启动方式后,就把IROM映射到该区域。

内部存储区:
这个区域对应着内部的内存地址,iROM和SRAM都是分布在这个区间。0x08000000~0x0bffffff对应着内部ROM,但是IROM实际只有32KB,选择从IROM启动的时候,首先运行就是这里面的程序BL0,BL0这部分代码由三星固化。0x0c000000~0x0fffffff对应内部SRAM,实际就是8KB的Steppingstone。

静态存储区:
这个区域用于访问挂在外部总线上的设备,比如说NOR flash、oneNand等。这个区域被分割为6个bank,每个bank为128MB,数据宽度最大支持16bit,每个bank由片选Xm0CS[0]~Xm0CS[5] 选中。

动态存储区:
该区域从0x50000000~0x6fffffff,又分为2个区间,分别占256MB,可以片选Xm1CS[0]~Xm1CS[1]来进行着2个区间的选择。我们6410开发板上256MB的DDR内存就安排在这个区域,这也就是为什么6410的内存地址是从0x50000000开始的原因。

内存芯片的连接方式:

6410芯片手册中的存储控制器
芯片手册第5章,DRAM CONTROLLER

5.4节介绍了内存控制器初始化的流程。

uboot代码中的cpu\s3c64xx\s3c6410文件下的cpu_init.S文件下的标号mem _ ctrl _ asm _ init下的代码就是对存储控制器进行初始化的代码。

代码举例:(OK6410开发板)

.text
.global mem_init
mem_init:

    ldr r0, =0x7e00f120 @设置数据线
    mov r1, #0x8
    str r1, [r0]

    ldr r0, =0x7e001004  @make DRAM Controller enter ‘Config’ state
    mov r1, #0x4         
    str r1, [r0]

    ldr r0, =0x7e001010  @鍒锋柊瀵勫瓨鍣ㄥ湴鍧€
    ldr r1, =( ( 7800 / ( 1000000000/133000000 ) + 1 ) )      @璁剧疆鍒锋柊鏃堕棿
    str r1, [r0]

    ldr r0, =0x7e001014  @CAS latency瀵勫瓨鍣?
    mov r1, #(3 << 1)
    str r1, [r0]

    ldr r0, =0x7e001018  @t_DQSS瀵勫瓨鍣?
    mov r1, #0x1
    str r1, [r0]

    ldr r0, =0x7e00101c  @T_MRD瀵勫瓨鍣?
    mov r1, #0x2
    str r1, [r0]

    ldr r0, =0x7e001020   @t_RAS瀵勫瓨鍣?
    ldr r1, =( ( 45 / ( 1000000000 / 133000000 ) + 1 ) )
    str r1, [r0]

    ldr r0, =0x7e001024   @t_RC瀵勫瓨鍣?
    ldr r1, =( ( 68 / ( 1000000000 / 133000000 ) + 1 ) )
    str r1, [r0]

    ldr r0, =0x7e001028   @t_RCD瀵勫瓨鍣?
    ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )
    str r1, [r0]

    ldr r0, =0x7e00102c   @t_RFC瀵勫瓨鍣?
    ldr r1, =( ( 80 / ( 1000000000 / 133000000 ) + 1 ) )
    str r1, [r0]

    ldr r0, =0x7e001030   @t_RP瀵勫瓨鍣?
    ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )
    str r1, [r0]

    ldr r0, =0x7e001034   @t_rrd瀵勫瓨鍣?
    ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )
    str r1, [r0]

    ldr r0, =0x7e001038   @t_wr瀵勫瓨鍣?
    ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )
 @  ldr r2, [r0]
    str r1, [r0]

    ldr r0, =0x7e00103c   @t_wtr瀵勫瓨鍣?
    mov r1, #0x07
    str r1, [r0]

    ldr r0, =0x7e001040   @t_xp瀵勫瓨鍣?
    mov r1, #0x02
    str r1, [r0]

    ldr r0, =0x7e001044   @t_xsr瀵勫瓨鍣?
    ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )
    str r1, [r0]

    ldr r0, =0x7e001048   @t_esr瀵勫瓨鍣?
    ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )
    str r1, [r0]

    ldr r0, =0x7e00100c   @鍐呭瓨鎺у埗閰嶇疆瀵勫瓨鍣?
    ldr r1, =0x00010012   @閰嶇疆鎺у埗鍣?
    str r1, [r0]

    ldr r0, =0x7e00104c   @32浣岲RAM閰嶇疆鎺у埗瀵勫瓨鍣?
    ldr r1, =0x0b45
    str r1, [r0]

    ldr r0, =0x7e001200   @鐗囬€夊瘎瀛樺櫒
    ldr r1, =0x150f8
    str r1, [r0]

    ldr r0, =0x7e001304   @鐢ㄦ埛閰嶇疆瀵勫瓨鍣?
    mov r1, #0x0
    str r1, [r0]

    ldr r0, =0x7e001008   @从这一步开始,初始化内存,设置mem_cmd为nop
    ldr r1, =0x000c0000
    str r1, [r0]

    ldr r1, =0x00000000   @‘Prechargeall’ 
    str r1, [r0]

    ldr r1, =0x00040000   @‘Autorefresh’2次
    str r1, [r0]
    str r1, [r0]

    ldr r1, =0x000a0000   @MRS
    str r1, [r0]

    ldr r1, =0x00080032   @Mode Reg
    str r1, [r0]

    ldr r0, =0x7e001004   @memc_cmd‘3’b000’
    mov r1, #0x0          @DRAM Controller enter ‘Ready’ state
    str r1, [r0]

check_dmc1_ready:         @检查内存状态 ‘2’b01’, which means'Ready’
    ldr r0, =0x7e001000 
    ldr r1, [r0]
    mov r2, #0x3
    and r1, r1, r2
    cmp r1, #0x1
    bne check_dmc1_ready
    nop
    mov pc, lr

210内存初始化

210开发板配置的是DDR2内存。
内存的初始化_第7张图片

内存起始地址为0x20000000

210开发板的内存通常采用8片或者4片128M*8bit芯片级联的办法。

代码举例(OK210开发板)

#define DMC_PHYCONTROL0 0xf0000018
#define DMC_PHYCONTROL1 0xf000001c
#define DMC_CONCONTROL  0xf0000000
#define DMC_MEMCONTROL  0xf0000004
#define DMC_MEMCONFIG0  0xf0000008
#define DMC_MEMCONFIG1  0xf000000c
#define DMC_PRECHCONFIG 0xf0000014
#define DMC_TIMINGAREF  0xf0000030
#define DMC_TIMINGROW   0xf0000034
#define DMC_TIMINGDATA  0xf0000038
#define DMC_TIMINGPOWER 0xf000003c
#define DMC_PHYSTATUS   0xf0000040
#define DMC_DIRECTCMD   0xf0000010
#define DMC_PWRDNCONFIG 0xf0000028

#define DMC0_MEMCONTROL         0x00202400
#define DMC0_MEMCONFIG_0        0x20F00313  
#define DMC0_MEMCONFIG_1        0x00F00313  

#define DMC0_TIMINGA_REF        0x00000618
#define DMC0_TIMING_ROW         0x2B34438A
#define DMC0_TIMING_DATA        0x24240000
#define DMC0_TIMING_PWR         0x0BDC0343      

.globl mem_init
mem_init:
    @ step 2.1
    ldr r0, =DMC_PHYCONTROL0
    ldr r1, =0x00101000             
    str r1, [r0]

    @ step 2.2
    ldr r0, =DMC_PHYCONTROL0
    ldr r1, =0x00101002                 
    str r1, [r0]

    @ step 4
    ldr r0, =DMC_PHYCONTROL0
    ldr r1, =0x00101003                 
    str r1, [r0]

    @ step 5
    ldr r0, =DMC_CONCONTROL             
    ldr r1, =0x0FFF1350
    str r1, [r0]

    @ step 6
    ldr r0, =DMC_MEMCONTROL
    ldr r1, =DMC0_MEMCONTROL                
    str r1, [r0]

    @ step 7
    ldr r0, =DMC_MEMCONFIG0
    ldr r1, =DMC0_MEMCONFIG_0               
    str r1, [r0]

    @ step 8
    ldr r0, =DMC_PRECHCONFIG
    ldr r1, =0xFF000000                 
    str r1, [r0]

    @ step 9.1
    ldr r0, =DMC_TIMINGAREF
    ldr r1, =DMC0_TIMINGA_REF               
    str r1, [r0]

    @ step 9.2
    ldr r0, =DMC_TIMINGROW
    ldr r1, =DMC0_TIMING_ROW                
    str r1, [r0]

    @ step 9.3
    ldr r0, =DMC_TIMINGDATA
    ldr r1, =DMC0_TIMING_DATA               
    str r1, [r0]

    @ step 9.4
    ldr r0, =DMC_TIMINGPOWER
    ldr r1, =DMC0_TIMING_PWR                
    str r1, [r0]

    @ step 11
wait_lock:
    ldr r0, =DMC_PHYSTATUS 
    ldr r1, [r0]            
    and r2, r1, #0x4
    cmp r2, #0x4                    
    bne wait_lock

    @ step 14
    ldr r0, =DMC_DIRECTCMD
    ldr r1, =0x07000000                 
    str r1, [r0]

    @ step 16
    ldr r1, =0x01000000                 
    str r1, [r0]

    @ step 17
    ldr r1, =0x00020000                 
    str r1, [r0]

    @ step 18
    ldr r1, =0x00030000                 
    str r1, [r0]

    @ step 19
    ldr r1, =0x00010400                 
    str r1, [r0]

    @ step 20
    ldr r1, =0x00000542                 
    str r1, [r0]

    @ step 21
    ldr r1, =0x01000000                 
    str r1, [r0]

    @ step 22.1 
    ldr r1, =0x05000000                 
    str r1, [r0]

    @ step 22.2
    ldr r1, =0x05000000                 
    str r1, [r0]

    @ step 23
    ldr r1, =0x00000442                 
    str r1, [r0]

    @ step 25.1
    ldr r1, =0x00010780                 
    str r1, [r0]

    @ step 25.2
    ldr r1, =0x00010400                 
    str r1, [r0]

    @ step 26, repeat step14~step25
    ldr r1, =0x07100000                 
    str r1, [r0]

    ldr r1, =0x01100000                 
    str r1, [r0]

    ldr r1, =0x00120000                 
    str r1, [r0]

    ldr r1, =0x00130000                 
    str r1, [r0]

    ldr r1, =0x00110400                 
    str r1, [r0]

    ldr r1, =0x00100542                 
    str r1, [r0]

    ldr r1, =0x01100000                 
    str r1, [r0]

    ldr r1, =0x05100000                 
    str r1, [r0]

    ldr r1, =0x05100000                 
    str r1, [r0]

    ldr r1, =0x00100442                 
    str r1, [r0]

    ldr r1, =0x00110780                 
    str r1, [r0]

    ldr r1, =0x00110400                 
    str r1, [r0]

    @ step 27
    ldr     r0, =DMC_CONCONTROL
    ldr r1, =0x0FF02030                 
    str r1, [r0]

    ldr     r0, =DMC_PWRDNCONFIG
    ldr r1, =0xFFFF00FF                 
    str r1, [r0]

    ldr     r0, =DMC_CONCONTROL
    ldr r1, =0x00202400                 
    str r1, [r0]

    mov pc, lr

你可能感兴趣的:(内存的初始化)