uboot-step 8 内存初始化

作者: 2625K | 来源:发表于2016-08-07 00:15 被阅读442次

    uboot-step 8 内存初始化

    内存的初始化相比前面的那些步骤略微的麻烦了些,为了能够比较清楚地说明下内存的初始化,(ps:虽然我也不是特别的清楚),首先简单的说下这篇文章的大概流程:

    • 1.对内存相关的一些简单介绍
    • 2.s3c6410的内存控制器的初始化流程
    • 3.对照datasheet说明实现代码的工作流程

    关于内存

    内存的分类

    这里所说的内存仅指RAM(RandomAccessMemory,随机存取存储器),它具有可以随机读写访问的特点,并且存储的数据在断电后会自动消失,现在所用的主要有以下两种类型:

    • SRAM :静态RAM,不需要一直刷新,双稳态电路形式存储数据,集成度较低,体积大,造价高,容量小,通常用作Cache
    • DRAM : 动态RAM, 需要不断刷新,通过MOS电容存储电荷来存储数据,结构简单,集成度高,成本低,便于大容量制造,常见的几种DRAM:
      • SDRAM :Synchronous Dynamic RAM ,同步动态随机存储器,工作频率与系统的频率相同,逐渐被DDR SDRAM所取代
      • DDR SDRAM : Double Data Rate SDRAM 双倍同步动态随机存储器,习惯上称之为DDR,相比SDRAM,速度和容量上有所提升,本质上虽然没有提高时钟频率,但是可以在时钟的上升沿和下降沿同时传输数据,因此其速度是标准SDRAM 的两倍
      • mobile DDR : 相比pC端的DDR,电压更低,封装更小

    内存的结构

    内存的内部结构就像表格一样,每一张表格称为一个逻辑BANK,L_BANK,每张表格有若干行地址线和若干列地址线,寻址的时候,首先去找到数据在哪一个bank里面,然后在分别确定行地址和列地址,这样就可以找到需要的数据所在的单元了,由于成本,制造工艺的原因,无法将整个地址空间做到一个bank里面,现在一般都将整个地址空间分为4个L-bank,四个L-bank具有公用的行地址和列地址


    bank.png

    内存的容量

    Ram.png
    一般内存容量的表示方法如上图所示,64M表示有多少个存储单元,32表示每个存储单位的容量为多少bit,可以将其换算为Byte,如上图所示的内存容量为64M32bit=644Byte=256MByte。

    内存引脚说明

    rampin.png

    如上图所示,RAM的引脚主要有以下几种:

    • 电源引脚: 数据电源VDDQ,VSSQ,电源VDD,VSS
    • 时钟相关引脚: CK 上升沿和下降沿两个,CKE时钟使能引脚
    • 片选引脚: CS 低有效
    • 列,行地址,写使能引脚: 列,行地址选中使能,写使能引脚,低有效
    • DMx引脚:输入数据屏蔽引脚
    • BA0,1:bank选择引脚
    • A[n:0]:地址线
    • DQ:数据总线
    • DQSx:输出数据闸门

    下图是S3c6410 内存端口引脚说明,可以看出与上面的内存芯片的datasheet中的引脚说明正好一一对应


    rampin1.png

    硬件原理图如下图所示:


    ramsch.png

    更多内存相关的知识请找度娘或参考下面的链接
    终极图解内存上
    终极图解内存下

    s3c6410 DRAMC初始化流程

    S3c6410的DRAM 控制器支持SDR SDRAM,mobile SDR SDRAM ,DDR SDRAM,和mobile DDR SDRAM多种类型,根据芯片手册上的描述:
    DRAM 控制器支持多达两片同样类型的最大256M的内存,所有的内存片都共享同样的引脚,除了时钟使能和片选信号,当上电复位以后,软件必须初始化DRAM控制器和连接到DRAM控制器上的内存,初始化流程需要参考SDRAM datasheet,可供参考的初始化流程如下图,第一张图是DRAM 控制器的初始化流程,第二张图是内存的初始化流程:


    Dram1.png
    DRAM2.png

    由于所采用的开发板上的内存芯片为Mobile DDR SDRAM,因此这里只贴出了这种类型的内存初始化流程,先来看下DRAM控制器的初始化流程:

    • 1.编程memc_cmd 写入'3b100',使DRAM控制器进入Config (配置)状态
    • 2.向相关的寄存器中写入内存时序参数,内存片的配置,id配置相关
    • 3.等待200us,使内存上电和时钟稳定,但是其实当cpu开始工作的时候,内存电源和时钟都已经稳定了
    • 4.执行内存初始化流程,即下面的流程
    • 5.编程memc_cmd写入'3b000',使DRAM控制器进入’Ready‘(准备)状态
    • 6.检查寄存器memc_stat 内存状态域直到内存状态为’2b01‘,这意味着DRAM控制器已经准备好了

    看完了DRAM控制器的初始化流程,再来看下内存初始化的流程:

    • 1.编程mem_cmd 在direct_cmd 写入’2b11‘,使DRAM控制器发送'NOP'命令到内存
    • 2.编程mem_cmd 在direct_cmd 写入’2b00‘,使内存控制器发送’Prechargeall'命令到内存
    • 3.编程mem_cmd 在direct_cmd 写入‘2b11’,使DRAM控制器发送'Autorefresh'命令到内存
    • 4.编程mem_cmd 在direct_cmd 写入‘2b11’,使DRAM控制器发送'Autorefresh'命令到内存
    • 5.编程mem_cmd '2b10'在direct_cmd,使DRAM 控制器发送MRS内存命令-EMRS的bank地址一定要设定
    • 6.编程mem_cmd '2b10'在direct_cmd,使DRAM 控制器发送MRS内存命令-MRS的bank地址一定要设定

    接下来按照上面的流程来进行内存的初始化

    1,Dram控制器进入配置状态
    memc_cmd.png

    按照上图的说明,向memc_cmd寄存器中写入100即可

    2,内存时序参数,id等相关配置
    • Refresh period 配置


      refresh period.png

      内存刷新周期设置,根据下图内存芯片手册的值,由s3c6410的时钟体系配置,内存使用的为AHB总线时钟,为133Mhz,7.8us对应寄存器的值应为7800*(1000 000 000/133 000 000),此值不是一个整数,最后在加上1,即为寄存器中的值


      data refresh.png
    • CAS latency


      cas.png

      如下图,内存芯片手册上的数字为2或3,这里设为3


      data cas.png
    • t_DQSS


      t_dqss.png

      如下图,内存芯片手册上的为0.75到1.25之间,这里设为1


      data tdqss.png
    • t_MRD


      t mrd.png

      如下图,内存芯片手册上的为2

    data tmrd.png
    • t_RAS


      t_ras.png

      如下图,内存芯片手册上的为40 到70000ns之间,我们大概选个时间就好


      data tras.png
    • t_RC


      t_rc.png
    • t_RCD


      t_rcd.png
    • t_RFC


      t_rfc.png
    • t_RP


      t_rp.png
    • t_RRD


      t_rrd.png
    • t_WR


      t_wr.png
    • t_WTR


      t_wtr.png
    • t_XP


      t_xp.png
    • t_XSR


      t_xsr.png
    • t_ESR


      t_esr.png

    上面这些时序参数配置大部分在内存芯片手册上都可以找到,只要相应的填进去就好,实在没有的可以参考其它人的代码来写:


    data sheet.png
    data sheet1.png
    • MEMCFG 寄存器 行列地址,burst length,内存片数量


      memcfg.png
      memcfg1.png

      这里内存芯片只有一片,芯片手册上相关数据如下:


      data addr.png
      data burst.png
    • MEMCFG2 寄存器 配置,内存类型,数据宽度等信息,这里32bit,mobileDDR内存


      memcfg2.png
    • chipcfg 配置AXI 内存地址


      chipcfg.png
    • usrcfg 用户寄存器


      usrcfg.png
    3.这样就完成了内存参数的设置,下面进行内存初始化流程
    directcmd.png
    • 1、发送NOP命令
    • 2、发送Prechargeall命令
    • 3、发送Autofresh
    • 4、发送Autofresh
    • 5、发送mrs命令,设置mrs寄存器
    • 6、发送mrs命令,设置emrs寄存器
      对于5,6点的内存寄存器的设置需要根据内存芯片手册进行相关配置,如下图:


      data mrs.png
      data emrs.png
    4.完成了内存的初始化流程之后,就剩下最后的ready了
    • 发送ready到memc_cmd 命令000 使DRAM控制器进入ready状态
    • 检查mem_stat寄存器,检查DRAM控制器是否已经进入ready状态


      memstat.png

    代码实现如下:

    .text
    .global mem_init
    mem_init:
    
    ldr r0, =0x7e00f120  @设置xm1data引脚为dramc 数据引脚
    mov r1, #0x8
    str r1, [r0]
    
    ldr r0, =0x7e001004  @内存控制命令寄存器
    
    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位DRAM配置控制寄存器
    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
    ldr r1, =0x000c0000 @nop
    str r1, [r0]
    
    ldr r1, =0x00000000 @Prechargeall
    str r1, [r0]
    
    ldr r1, =0x00040000 @Autofresh
    str r1, [r0]
    
    ldr r1, =0x000a0000 @emrs 寄存器设置
    str r1, [r0]
    
    ldr r1, =0x00080032 @mrs 设置
    str r1, [r0]
    
    ldr r0, =0x7e001004  @发送ready命令
    mov r1, #0x0
    str r1, [r0]
    
    check_dmc1_ready: @检测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
    

    此去经年
    zhaiyk@sina.cn
    August 3, 2016

    相关文章

      网友评论

        本文标题:uboot-step 8 内存初始化

        本文链接:https://www.haomeiwen.com/subject/pcoksttx.html