weiqi7777

基于S3C6410的ARM11学习(十一) DDR初始化

0
阅读(4282)

 

     之前的程序都是在内部的stepping stone中运行的。但是stepping stone的大小是很小的。ARM11只有8K的大小。这么小的空间,要运行大型程序肯定是不行的。所以就需要外部的存储器。ARM11的外部存储器用的是ddr。所以就要对ddr进行初始化,同时将代码拷贝到ddr中。

     先看看S3C6410nandflash的启动。在上电的时候,CPU会自动把外部的nandflash的前8k数据拷贝到内部的stepping stone中。Stepping stone的地址是从0x0c000000开始的。然后CPUstepping stone给映射到0x00000000地址处,然后CPU跳转到0地址处执行第一条代码。

clip_image002

不要被图中stepping stone64M空间迷惑,其实是没有这么大的。只有8K大小。因为这空间很小,所以就需要外部加存储器。图中也说明了,外部存储器的地址从0x50000000开始。大小总共可以有256M

0x00000000~0x07FFFFFF对应内部的镜像区。这个区用来镜像启动代码的。因为S3C6410支持多种启动方式。当选择一种外设存储设备启动方式的时候,会将该存储设备的首地址给映射到这个区域来。这样当cpu0地址开始运行代码,就相当于从外设存储设备的首地址运行了。

0x08000000~ 0x0bFFFFFFF对应着内部ROM,但是IROM实际只有32KB,选择从IROM启动的时候,首先运行就是这里面的程序BL0,这部分代码由三星固化。

0x0c000000~ 0x0FFFFFFF对应内部SRAM,实际就是8KBSteppingstone

0X10000000~0X3FFFFFFF对应主存储区,这个区域用来访问挂在外部总线上的设备,比如oneNAND,NORFLASH。这个区域内被分割成6bank。每个bank大小是128M。数据宽度最大支持16bit。每个bank由片选xm0CS[0]~xm0CS[5]选中。

0x50000000~0x6FFFFFFFDRAM区域。这个区分为两个区,分别占256MB。可以通过片选xm1CS[0]xm1CS[1]来进行选择。

 

我使用的OK6410ddr大小是128M。起始地址是从0x50000000开始。

S3C6410对这些存储设备的操作都是通过控制器来控制的。因为存储器驱动是相对来说比较麻烦的,要产生对应的时序,来对存储器进行读写。如果让CPU来控制产生这些时序的话,那对CPU来说是一个很大的负担,所以在芯片中有存储控制器,CPU通过对直接对存储控制器读写数据,存储控制器自动的把数据按照存储器的时序对存储器进行读写。

clip_image004

  这样的话,CPU访问数据就简单很多了。只需要向存储控制发读写信号,地址,数据就可以了。存储控制器自动的去外部存储器取数据或者写数据。

 因为外部存储器是有很多的,一个固定的存储控制器是很难兼容控制所有存储器的。所以这个存储控制器就必须是要可配置的,并且外部存储器的控制信号也要符合固定的标准,即时序要是一样的,时间间隔可以不一样。这样才能统一起来。所以这里的ddr初始化,就是去配置ddr的存储控制器。让这个存储器能控制外部的ddr存储器。

 

 这个时候的配置,就得要看外部的ddr存储器的数据手册了。知道各个时间间隔,这样才能配置ddr存储控制器。

 clip_image006

上图是ddr的数据手册,大小是64MBOK6410使用的是两片,所以总共大小是128M

下面就要来对ddr控制器进行配置。

手册中有对ddr控制器初始化有说明顺序。所以在对ddr控制器初始化的时候,就必须要按照这个规定的顺序来。

clip_image008

clip_image010

整个流程

1、  MEMC_CMD寄存器写入3’b100,使DRAM控制器进入配置状态

2、  写存储器时序参数,芯片配置,id配置寄存器。这里就要参考数据手册了。

3、  等待200us,让DRAM稳定。因为从上电到现在已经超过这时间了,所以这个可以省略

4、  执行存储器初始化序列

5、  MEMC_CMD寄存器写入3’b000,让DRAM控制器进入准备状态

6、  检查MEMC_STAT寄存器的存储状态为为2’b01,表示准备好。

 

DRAM控制器支持两种dram,一种是SDR,一种是DDR。板子用的是DDR,所以上面流程中的执行存储器初始化序列,这里就是执行DDR的初始化序列。

1、  MEM_CMD寄存器的命令位写入2’b11,使DRAM控制器产生NOP命令

2、  MEM_CMD寄存器的命令位写入2’b00,使DRAM控制器产生预充电命令

3、  MEM_CMD寄存器的命令位写入2’b01,使DRAM控制器产生自动刷新命令

4、  MEM_CMD寄存器的命令位写入2’b01,使DRAM控制器产生自动刷新命令

5、  MEM_CMD寄存器的命令位写入2’b10,使DRAM控制器产生MRS命令,EMRS的备份地址必须要设置

6、  MEM_CMD寄存器的命令位写入2’b10,使DRAM控制器产生MRS命令, MRS的备份地址必须要设置

 

手册中提供的参数有的有错误,实际要参考寄存器中说明的值。

 

下面就按照这个流程来进行初始化

先使用宏定义将地址都定义一下

image


第一步:

MEMC_CMD寄存器写入3’b100,使DRAM控制器进入配置状态

clip_image013

clip_image015

上图是这个寄存器的说明,只有低三位有用。写入100.也就是0x4

 

第二步:

写存储器时序参数,芯片配置,id配置寄存器。这里就要参考数据手册了。

  这里就要查看数据手册,对寄存器进行设置了。

clip_image017

clip_image019

 这个是设置刷新周期的时间。ddr刷新周期的概念可以百度。

在手册中,有下面这个说明

clip_image020

说明刷新周期是7.8us。寄存器设置中的值是刷新周期,不过这周期是通过时钟周期数来设置的。如果这时钟周期是100ns。那么设置的值是78,就刚好是7.8us。在之前的时钟初始化中,把这时间设置为133M了。所以需要去计算一下需要多少个时钟。但是这里,直接使用公式

7800 / ( 1000000000/133000000 ) + 1

   最前面的数是要设置的时间,以ns为单位。除的部分是表示133M时钟对应多少ns。这样一算下来,就可以得到需要多少个时钟可以得到7.8us。后面设置时间,也是通过这个方式,这样我们就不用去计算了。

clip_image021clip_image023

这个是设置CAS参数的。就设置3:1位。最低位这里为0.

 

在数据手册中也有说明,这个参数可以是2,也可以是3.这里就设置为3

clip_image024

 


clip_image025

clip_image027

这个是设置DQSS参数

也是查阅数据手册,在时序那一部分。

clip_image029

数据,这里就看前两列和最后一列,第一列是最小,第二列是最大。最后一个是单位。这里是以时钟为单位,最小是0.75个时钟。这里就可以设置为1.

 

clip_image030

clip_image032

  这个是设置MRD参数。

手册中,参数是2个时钟。

clip_image034

  这里,参数就设置为2.


clip_image036

clip_image038

  设置RAS参数。

  手册中

clip_image040

 参数是45ns。所以就要用之前那个式子。


以下就不说明了。一直把各个时序参数设置完就可以了。

配置完P1T_ESR寄存后,时序就配置完了。接着就对芯片进行配置


 clip_image042

对这个寄存器的第16位,第4位,第1位和第0位置1

clip_image044

配置读写突发模式是4.

clip_image046

  后面6位是配置ddr的行列数的。这个从ddr数据手册中得到,行是13,列是10。所以后面6位值就是6’b010010。刚好就是0x12

clip_image048



clip_image050

clip_image052

这个配置的位就多了。主要关心前面几个的配置。

clip_image054

这里,配置读延迟[12:11]01,手册中也说这个是mobile DDR SDRAM使用。板子用的就是mobile DDR。存储器类型[10:8]011,表示外部存储器是mobile DDR。存储器宽度[7:6]设置为01,表示是32位。一个DDR16位,但是使用两片拼接的,所以宽度就是32位。后面几位的设置功能目前还不知道有什么用。

 

clip_image056

clip_image058

  这个是对芯片的片选设置的。因DRAM可以有两个,所以有两个寄存器分别对应。板子只用了1个。就是chip0.所以这里就只设置第一个寄存器。

 当地址在0x50000000的时候,DDR的片选是应该要有效的,这样DRAM控制器才能访问到DDR。寄存器的[15:8]就是这只这个地址的。说明是这个值和AXI address[31:24]位比较决定芯片是否选中。所以这里的8位值应该为0x50

16位是存储器的选址方式。手册中有说明,bank-row-column。所以这一位要为1.

clip_image060

对于低8位。DDR的大小是128M。所以地址空间是0x5000_0000~0x57FF_FFFF。而低8位是屏蔽地址的。这里是设置为0XF8.就是将0x5000_0000~0x57FF_FFFF意外的地址屏蔽芯片使能。

所以这个参数的值就是0x150f8

 

clip_image062

clip_image064

 这里,参数都设置为0.选择最小延迟。

 


 以上就把ddr控制器时序,芯片配置给配置好了。下面就是要进入存储器初始化序列。

 

第三步:存储器初始化序列

   这个就按照序列来。

   首先发出nop命令。

      clip_image066

    clip_image068

     [19:18]位写入11。那么写入的值就是0x000c0000

 

    发出预充电命令

    clip_image070

 

    发出两次自动刷新命令

    clip_image072

 

   发出MRS命令,EMRSbank地址必须要设定

   发出MRS命令,MRSbank地址必须要设定

      clip_image074

     clip_image076

    芯片的后面18位设置BANK地址和存储地址。

    首先发第一个MRS命令,要设定EMRS BANK地址。这个也查手册

         clip_image078

       Bank地址是10,后面的地址都可以设置为0.

     所以写入的参数就是0x000a0000.

 

     发第一个MRS命令,要设定BANK地址。这个也查手册

         clip_image080

        Bank地址是00.因为之前设置CAS3,突发模式使4.所以后面的地址为0x32

 所以整个值就是0x00080032

        

     这样,就完成了存储器的序列配置了。


第三步:向MEMC_CMD寄存器写入3’b000,让DRAM控制器进入准备状态

clip_image081

就往寄存器中写0就可以了。

 

第四步:检查MEMC_STAT寄存器的存储状态为为2’b01,表示准备好。

          clip_image082

           clip_image084

         就是将这个寄存器的值给读出来,判断最后两位是否是01,不是的话就继续读,然后判断。是的话,说明DDR初始化完成。程序返回即可。

 

         最后,在补充一个东西。在DDR初始化代码的前面,要加入如下代码:

clip_image085

         这个寄存器是设置DDR的数据管脚作为数据线的。这个寄存器的第7位是设置DDR的数据线的。默认为是1,要改成0。这样DDR的数据管脚才作为DDR的数据线。

 

         通过以上这些步骤,就完成了DDR控制器的初始化了。这样,在后面就可以对这DDR进行使用了。可以往里面写值,可以读值。

         DDR初始化中,要紧密的结合数据手册,因为要设置很多时序的参数以及芯片的一些参数。


对比STM32

         STM32中没有内存初始化这一步,因为STM32将内存做进芯片中去了。这样STM32就可以直接进行访问内存,而不用再进行初始化这一步。就和51单片机一样,内部有256K大小的内存。只不过STM32的内存比较大而已。

         不过STM32也是外挂存储器的。因为STM32FSMC(静态存储器控制器),能控制4种接口器件。

clip_image086

        clip_image088

         STM32手册中,也说明了FSMC的地址映射。分为4个块。如果要使用外部存储器的话,就可以使用FSMC,不过使用之前,肯定是要对FSMC进行一些配置的。和S3C6410的存储器配置一样的。

         查阅资料,STM32是不支持DRAM的,支持PSRAM的。