uboot-step 8 内存初始化

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容