专题8-不用内存怎么行
第一课-我从内部看内存
- 内存分类
内存由于具有访问速度快,访问方式简单等优点,成为了PC或者是嵌入式硬件平台上不可或缺的原件。
DRAM:它的基本原件是小电容,电容可以在两个极板上保留电荷,但是需要定期的充电(刷新),否则数据就会丢失。缺点:由于要定期刷新存储介质,存取速度较慢
SRAM:它是一种具有静止存取功能的内存,不需要定期刷新电路就能保存它内部存储的数据。其优点:存取速度快;但是缺点是:功耗大,成本高。常用作存储量不高,但是存取速度快的场合,比如stepping stone(2440的垫脚石才4K)。
开发板用的基本上都是DRAM,PC机用的基本上都是SRAM
l SDRAM(synchronous dynamic random access memory):同步动态随机存储器。
同步:内存工作需要有同步时钟,内部的命令的发送与数据的传输都是以该时钟为基准的。
动态:存储阵列需要不断的刷新来保证数据不丢失。
随机:是指数据不是线性依次存储,而是自由指定地址进行数据读写
备注:2440开发板上使用的内存通常是SDRAM
l DDR(double data rate sdram),即“双倍速率同步动态随机存储器”。与早期的SDRAM相比,DDR除了可以在时钟脉冲的上升沿传输数据,还可以在下降沿传输信号,这意味着在相同的工作频率下,DDR的李璐传输速率为SDRAM的两倍。DDR2则是在DDR的基础上再次进行了改进,使得数据传输速率在DDR的基础上再次翻倍。
备注:6410开发板通常采用DDR内存,210开发板通常采用DDR2内存
- 内存内部结构
内存的内部如同表格,数据就存放在每个单元格中。数据的读时,现制定行号(行地址),再指定列号(列地址),我们就可以准确的知道所需要的单元格。而这张表格称为:Logical Bank(L-Bank)。
由于技术、成本等原因,一块内存不可能把所有的单元格都做大一个L-Bank,现在内存内部基本都分割成为4个L-Bank。
l 寻址信息-找到内存里面某个单元格:
(1)L-Bank选择信号
(2)行地址
(3)列地址
- 推导内存容量的计算公式
4*L-Bank容量
L-Bank=单元格数目*单元格容量
第二课-2440内存初始化
- 2440地址空间
(1)地址线:2440芯片有27根地址线,能访问128M的范围。只是从地址线出发没办法满足芯片的要求,引出片选信号。
(2)片选信号
为了扩大外设的访问范围,S3c2440芯片又提供了8个片选信号nGCS0-nGCS7。当某个片选信号nGCSx有效是,则可以通过27根地址线去访问对应这个片选的128MB。由于有8个片选,所以2440芯片能访问的外设空间总共有8*128MB=1GB。而1G(0X40000000)以上的空间,则安排给了2440内部的寄存器,访问这些内部寄存器,则是通过32位的处理器内部总线来完成的。
(3)外设空间
片选6和片选7一般留给SROM或者SDROM(2440用的),地址布局如下,能看出为什么2440的内存地址是0x30000000的原因:
(4)存储控制器
2440支持众多外设,内存放在片选6上,网卡芯片安排在片选3或者4上,nand flash安排在片选0上。
CPU本身不知道地址对应的是什么,他通过存储控制器进行相应的一些处理之后来访问对应的地址。我们需要通过存储控制器将地址分成片选信号、行地址和列地址,初始化内存实际上是初始化系统内部的存储控制器。
- 内存芯片的硬件连接
TQ2440和mini2440所使用的的芯片是一样的,规格是4M*4Bank*16bit I/O,它表示:
内存芯片由4个L-bank构成的,每个L-bank中有4M个单元格,16bit表示每一个单元格的容量是16bit,第二个意思是这个芯片的宽度是16bit。2440的数据线的宽度是32的,若要将内存芯片的32接口与内存芯片的16位接口连接,为了避免数据线的浪费,我们将两个内存芯片并联与2440核心芯片的连接。
- 设置2440存储控制寄存器
在2440的芯片手册上翻开第5章节,可以找到对应的控制器寄存器。
(1)在206页找到BWSCON寄存器,如下:
该寄存器的每一个位都对应着一个数字,32个位被分成8个组,因为我们有8个bank,每三个位控制一个bank。我们只看第7个bank的设置,对应设置0010:
Bank设置也为0010,之前的前28位目前不用,把它们保存为默认值,该寄存器的整体设置为:00100010000000000000000000000000,十六进制是0x22000000
(2)208页找到另一组寄存器BANKCON0-BANKCON5,可以保持它的默认值不变0x00000700。
BANKCON6-BANKCON7寄存器设置内存信息,在209页,需要设置:
它们的设置是相同的,可以参见芯片手册,在对应的内存芯片手册中,可以找到行地址和列地址的设置信息,整体寄存器的值设置成0x18001
(3)在210页找到寄存器,REFRESH,如下:
2440的电容是需要定期刷新的,在它下面的设置表中,设置它的值是:0x008c04f5
(4)211页BANKSIZE寄存器,设置成为:0x000000b1
(5)212页MRSRB6、MRSRB7寄存器,两个寄存器设置一样0x00000030
- 写代码
为了方便操作,使用循环语句进行操作。
reset:
bl set_svc
bl disable_watchdog
bl disable_interrupt
bl disable_mmu
bl init_clock
bl init_sdram @添加内存初始化
bl light_led
#define mem_contrl 0x48000000 @13个寄存器中的第一个寄存器的初始地址
init_sdram:
ldr r0, =mem_contrl @使用r0作为一个指针,指向的是寄存器
add r3, r0, #4*13 @使用r3作为二个指针,指向13个寄存器结束的地址
adrl r1, mem_data @使用r1表示表的基地址
0:
ldr r2, [r1], #4 @在r1中取出来数据,放在r2,同时移动4位
str r2, [r0], #4 @将地址值放在r0中,同时移动4位
cmp r0, r3 @对比r0和r3是否相等,不相等的话下移,进行循环
bne 0b
mov pc, lr
mem_data: @设置13个寄存器的地址放在一个表格李淼
.long 0x22000000 @long是伪指令,表示它的长度
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00018001
.long 0x00018001
.long 0x008c04f5
.long 0x000000b1
.long 0x00000030
.long 0x00000030
第3课-6410内存初始化
- 6410地址空间
S3C6410处理器拥有32位地址总线,其寻址空间为4G。其中高2G为保留区,低2G区域又可以划分为两个部分:主存储区和外设区。
主存储区划分:boot镜像区,内部存储区,静态存储区,保留区和动态存储区。
启动镜像区:这个区域的作用正如它的名字所述,是用来启动ARM系统的。但是这个区域并没有固定的存储介质与之对应。而是通过修改启动选项,把不同的启动介质映射到该区域。比选项,把不同的启动介质映射到该区域。比如说选择了IROM 启动方式后,就把IROM映射到该区域。
内部存储区:这个区域对应着内部的内存地址,iROM和SRAM都是分布在这个区间。
0x08000000~0x0bffffff对应着内部ROM,但是IROM实际只有32KB,选择从IROM启动的时候,首先运行就是这里面的程序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开始的原因。
- 内存芯片硬件连接
2440的内存芯片是32MB的两片并联变成而定64MB。在6410的内存芯片是两片128MB的芯片并联形成的256MB空间。
3.芯片手册导读(未做详细分析)
2440的内存初始化集中在处理13内寄存器的赋值,而且赋值是没有前后之分的。6410的控制器初始化在芯片手册的第五章,在192有着6410的初始化流程:
4. 写代码
reset:
bl set_svc
bl set_peri_port
bl disable_watchdog
bl disable_interrupt
bl disable_mmu
bl init_clock
bl mem_init
#define CLK_DIV0 0x7e00f020
#define OTHERS 0x7e00f900
#define MPLL_CON 0x7e00f010
#define APLL_CON 0x7e00f00c
#define CLK_SRC 0x7e00f01c
#define DIV_VAL ((0x0<<0)|(0x1<<9)|(0x1<<8)|(0x3<<12))
#define PLL_VAL ((1<<31)|(266<<16)|(3<<8)|(1<<0))
init_clock:
ldr r0, =CLK_DIV0
ldr r1, =DIV_VAL
str r1, [r0]
ldr r0, =OTHERS
ldr r1, [r0]
bic r1,r1,#0xc0
str r1, [r0]
ldr r0, =APLL_CON
ldr r1, =PLL_VAL
str r1, [r0]
ldr r0, =MPLL_CON
ldr r1, =PLL_VAL
str r1, [r0]
ldr r0, =CLK_SRC
mov r1, #0x3
str r1, [r0]
mov pc, lr
第4课-210内存初始化
- 地址空间
210芯片的地址从0x00000000到oxffffffff一共有4GB的空间2440的内存芯片是sdram,6410的内存芯片是DDR,210的内存芯片是DDR2。
6410的0地址是映射区,210的0地址也是映射区。
- 内存芯片硬件连接
2440和6410的用的都是16bit宽度的内存芯片,采用两片级联的方式生成32位地址。
210的采用4片128M*8bit芯片级联的办法。TQ210用的是8片,1Gb;Smart用的是4片,521Mb。
- 分析芯片手册
6410中的芯片手册中有内存的初始化步骤,210中同样也有内存的初始化流程。在芯片手册的598页显示了,210初始化DDR2的流程。
1.2.1.3 DDR2
Initialization sequence for DDR2 memory type:
1. To provide stable power for controller and memory device, the controller must assert and hold CKE to a logic low level. Then apply stable clock. Note: XDDR2SEL should be High level to hold CKE to low. (不去做了)
2. Set the PhyControl0.ctrl_start_point and PhyControl0.ctrl_inc bit-fields to correct value according to clock frequency. Set the PhyControl0.ctrl_dll_on bit-field to ‘1’ to turn on the PHY DLL. (设置PhyControl0为正确的位)
3. DQS Cleaning: Set the PhyControl1.ctrl_shiftc and PhyControl1.ctrl_offsetc bit-fields to correct value according to clock frequency and memory tAC parameters.
4. Set the PhyControl0.ctrl_start bit-field to ‘1’.
5. Set the ConControl. At this moment, an auto refresh counter should be off.
6. Set the MemControl. At this moment, all power down modes should be off.
7. Set the MemConfig0 register. If there are two external memory chips, set the MemConfig1 register.
8. Set the PrechConfig and PwrdnConfig registers.
9. Set the TimingAref, TimingRow, TimingData and TimingPower registers according to memory AC parameters.
10. If QoS scheme is required, set the QosControl0~15 and QosConfig0~15 registers.
11. Wait for the PhyStatus0.ctrl_locked bit-fields to change to ‘1’. Check whether PHY DLL is locked.
12. PHY DLL compensates the changes of delay amount caused by Process, Voltage and Temperature (PVT) variation during memory operation. Therefore, PHY DLL should not be off for reliable operation. It can be off except runs at low frequency. If off mode is used, set the PhyControl0.ctrl_force bit-field to correct value according to the PhyStatus0.ctrl_lock_value[9:2] bit-field to fix delay amount. Clear the PhyControl0.ctrl_dll_on bit-field to turn off PHY DLL.
13. Confirm whether stable clock is issued minimum 200us after power on
14. Issue a NOP command using the DirectCmd register to assert and to hold CKE to a logic high level.
15. Wait for minimum 400ns.
16. Issue a PALL command using the DirectCmd register.
17. Issue an EMRS2 command using the DirectCmd register to program the operating parameters.
18. Issue an EMRS3 command using the DirectCmd register to program the operating parameters.
19. Issue an EMRS command using the DirectCmd register to enable the memory DLLs.
20. Issue a MRS command using the DirectCmd register to reset the memory DLL.
21. Issue a PALL command using the DirectCmd register.
22. Issue two Auto Refresh commands using the DirectCmd register.
23. Issue a MRS command using the DirectCmd register to program the operating parameters without resetting the memory DLL.
24. Wait for minimum 200 clock cycles.
25. Issue an EMRS command using the DirectCmd register to program the operating parameters. If OCD calibration is not used, issue an EMRS command to set OCD Calibration Default. After that, issue an EMRS command to exit OCD Calibration Mode and to program the operating parameters.
26. If there are two external memory chips, perform steps 14~25 for chip1 memory device.
27. Set the ConControl to turn on an auto refresh counter. 28. If power down modes is required, set the MemControl registers.
4. 代码书写
210的内存初始化,将它放在一个新的s文件中。修改start.s中的依赖文件。在新的内存初始化文件中,按照上面的步骤,依次查找寄存器进行书写。
#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