31.6410内存的知识
6410的地址空间分布:
S3C6410处理器拥32位地址总线,其寻址空间为。其中高为保留外设区,低2GB区域又可划分为两部分:主存储区和外设区。
外设主要是寄存器所在的地址。
主存储区分为:Boot镜像区、内部存储区、静态存储区、保留区、动态存储区:
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开始的原因。
6410的存储控制器:
S3C6410X.pdf的第五章是DRAM CONTROLLER:
1.Program memc_cmd to ‘3‘b100 which makes DRAM Controller enter ‘config‘ state.
2.Write memory timing parameter, chip configuration, and id configuration registers.
3.Wait 200us to allow SDRAM power and clock to stabilize. However, when CPU starts working, power and clock would already be stabilized.
4.Execute memory initialization sequence.
5.Program memc_cmd to ‘3‘b000 which makes DRAM Controller enter ‘Ready‘ state.
6.Check memory status field in memc_stat until memory status becomes ‘2‘bo1 ,which means ‘Ready‘.
从上面的描述知道,6410的存储控制器的初始化是要有流程的:(2440不需要)所以看看uboot里是如何来初始化存储控制器的。验证一下uboot是不是按照上面的步骤来的:
打开uboot/cpu/s3c64xx/s3c6410里的cpu_init.S:这个汇编文件就是进行板子的内存和存储控制器初始化的。
在这汇编文件的开头几行不知道是做什么的暂时不管:
,
从注释看到,这是在设置总线的大小。
芯片文档:
在该寄存器里主要的是看:
注意:DATA[26:16]改为DATA[31:16]
从上面知道,如果该寄存器的[7]位设置为0,那么DATA[31:16]这16位就作为内存芯片数据引脚。如果是1,则这些位就会被SROMC使用了,这是设置为0.
0xd=0b00001101,所以[7]=0的,所以是作为数据引脚的。
接着是:
可以看到有对应的数据出现了0x04=0b100,数据写入的寄存器是MEMC_CMD,这跟手册里是一致的:1.Program memc_cmd to ‘3‘b100 which makes DRAM Controller enter ‘config‘ state.
按照上面的操作:
寄存器MEMC_CMD:
2.Write memory timing parameter, chip configuration, and id configuration registers.这是进行写内存的时间参数,芯片配置,配置寄存器等一系列寄存器的配置操作:就不看了:
ldr r1, =DMC_DDR_REFRESH_PRD
str r1, [r0, #INDEX_DMC_REFRESH_PRD]
ldr r1, =DMC_DDR_CAS_LATENCY
str r1, [r0, #INDEX_DMC_CAS_LATENCY]
ldr r1, =DMC_DDR_t_DQSS
str r1, [r0, #INDEX_DMC_T_DQSS]
ldr r1, =DMC_DDR_t_MRD
str r1, [r0, #INDEX_DMC_T_MRD]
ldr r1, =DMC_DDR_t_RAS
str r1, [r0, #INDEX_DMC_T_RAS]
ldr r1, =DMC_DDR_t_RC
str r1, [r0, #INDEX_DMC_T_RC]
ldr r1, =DMC_DDR_t_RCD
ldr r2, =DMC_DDR_schedule_RCD
orr r1, r1, r2
str r1, [r0, #INDEX_DMC_T_RCD]
ldr r1, =DMC_DDR_t_RFC
ldr r2, =DMC_DDR_schedule_RFC
orr r1, r1, r2
str r1, [r0, #INDEX_DMC_T_RFC]
ldr r1, =DMC_DDR_t_RP
ldr r2, =DMC_DDR_schedule_RP
orr r1, r1, r2
str r1, [r0, #INDEX_DMC_T_RP]
ldr r1, =DMC_DDR_t_RRD
str r1, [r0, #INDEX_DMC_T_RRD]
ldr r1, =DMC_DDR_t_WR
str r1, [r0, #INDEX_DMC_T_WR]
ldr r1, =DMC_DDR_t_WTR
str r1, [r0, #INDEX_DMC_T_WTR]
ldr r1, =DMC_DDR_t_XP
str r1, [r0, #INDEX_DMC_T_XP]
ldr r1, =DMC_DDR_t_XSR
str r1, [r0, #INDEX_DMC_T_XSR]
ldr r1, =DMC_DDR_t_ESR
str r1, [r0, #INDEX_DMC_T_ESR]
ldr r1, =DMC1_MEM_CFG
str r1, [r0, #INDEX_DMC_MEMORY_CFG]
ldr r1, =DMC1_MEM_CFG2
str r1, [r0, #INDEX_DMC_MEMORY_CFG2]
ldr r1, =DMC1_CHIP0_CFG
str r1, [r0, #INDEX_DMC_CHIP_0_CFG]
ldr r1, =DMC_DDR_32_CFG
str r1, [r0, #INDEX_DMC_USER_CONFIG]
3.Wait 200us to allow SDRAM power and clock to stabilize. However, when CPU starts working, power and clock would already be stabilized.
在第三步这里,是可以不做的。跳过。
4.Execute memory initialization sequence.
是内存初始化执行序列:
1.Program mem_cmd in direct_cmd to ‘2‘b11 which makes DRAM Controller issue ‘NOP‘ memory command.
2.Program mem_cmd in direct_cmd to ‘2‘b00 which makes DRAM Controller issue ‘Prechargeall‘ memorycommand.
3.Program mem_cmd in direct_cmd to ‘2‘b01 which makes DRAM Controller issue ‘Autorefresh‘ memorycommand.
4.Program mem_cmd in direct_cmd to ‘2‘b11 which makes DRAM Controller issue ‘Autorefresh‘ memorycommand.
5.Program mem_cmd to ‘2‘b10 in direct_cmd, which makes DRAM Controller issue ‘MRS‘ memory command- Bank address for EMRS must be set.
6.Program mem_cmd to ‘2‘b10 in direct_cmd, which makes DRAM Controller issue ‘MRS‘ memory command.- Bank address for MRS must be set.
1.在这内存初始化系列的第一条是往direct_cmd寄存器的mem_cmd位写入b11,使DRAM控制寄存器发出一个NOP命令。(上面mem_cmd是01是错的,下面的才是对的)。
所以在DIRECTCMD寄存器里写入的是:0b11000000000000000000=0x000C0000.看看uboot里的代码:
可以看到uboot里是按照芯片手册写的,写入的也是0x0c0000.
2.Program mem_cmd in direct_cmd to ‘2‘b00 which makes DRAM Controller issue ‘Precharge all‘ memorycommand.
写入的值是0b00,也是对应的:
3和4.Program mem_cmd in direct_cmd to ‘2‘b01 which makes DRAM Controller issue ‘Autorefresh‘ memorycommand.
AutoRefresh写入的是0b01000000000000000000=0x40000,可以看到也是正确的。
5.Program mem_cmd to ‘2‘b10 in direct_cmd, which makes DRAM Controller issue ‘MRS‘ memory command- Bank address for EMRS must be set.
0x0a0000=0b10100000000000000000可以看到是往direct_cmd写入了10.
6.Program mem_cmd to ‘2‘b10 in direct_cmd, which makes DRAM Controller issue ‘MRS‘ memory command.- Bank address for MRS must be set.
0x080032=0b10000000000000110010, 可以看到是往direct_cmd写入了10.操作也是正确的。
到这里,uboot内存初始化完成,接下来是存储控制器的初始化:
5.Program memc_cmd to ‘3‘b000 which makes DRAM Controller enter ‘Ready‘ state.
6.Check memory status field in memc_stat until memory status becomes ‘2‘bo1 ,which means ‘Ready‘.
mem.S:
.text
.global mem_init
mem_init:
ldr r0, =0x7e00f120
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
str r1, [r0]
ldr r1, =0x00000000
str r1, [r0]
ldr r1, =0x00040000
str r1, [r0]
ldr r1, =0x000a0000
str r1, [r0]
ldr r1, =0x00080032
str r1, [r0]
ldr r0, =0x7e001004
mov r1, #0x0
str r1, [r0]
check_dmc1_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