S5PV210之SDRAM初始化

本文使用的开发板是九鼎创展的X210 iNand版本。

 

一、查阅原理图中SDRAM相关部分

 

S5PV210之SDRAM初始化_第1张图片
S5PV210之SDRAM初始化_第2张图片

 

从以上原理图中可以得出以下信息:

(1)开发板上使用的SDRAM编码是K4T1G164QQ

(2)开发板上包括4片内存芯片,每片内存的数据总线都是16位的

(3)横向的两颗内存芯片是并联的(并联时地址总线的接法一样,但数据总线要加起来),这样连接相当于在逻辑上可以把这两颗内存芯片看成是一个32位的内存芯片

(4)每个内存端口都由3类总线构成:地址总线(Xm1_ADDR0~Xm1_ADDR13、Xm2_ADDR0~Xm2_ADDR13)+ 控制总线 + 数据总线(Xm1_DATA0~Xm1_DATA31、Xm2_DATA0~Xm2_DATA31)

 

二、查阅SDRAM数据手册

 

S5PV210之SDRAM初始化_第3张图片

由上图可得出K4T1G164QQ的含义如下:

   K:三星内存

   4:DRAM

   T:DDR2 SDRAM

1G:1Gb(128MB)

 16:单芯片16位宽

   4:8 Banks

 

S5PV210之SDRAM初始化_第4张图片

 

由上图可得出以下信息:

(1)S5PV210的内存端口信号中有BA0~BA2,接在内存芯片的BA0~BA2上,这些引脚用来选择Bank

(2)每个Bank内部有128Mb,通过Row Address(14位)+ Column Address(10位)的方式来综合寻址

(3)一共能寻址的范围是:2的24次方,也就是16MB(128Mb)的内存

 

三、查阅数据手册中内存映射相关部分

 

S5PV210之SDRAM初始化_第5张图片

 

从上图可得出以下信息:

(1)S5PV210共有两个内存端口,分别是DRAM0和DRAM1

(2)DRAM0的内存地址范围是0x20000000~0x3FFFFFFF(512MB)

(3)DRAM1的内存地址范围是0x40000000~0x7FFFFFFF(1024MB)

 

由此,得出结论:

(1)S5PV210最多支持1.5GB的内存,如果给它更多的内存,CPU就无法识别

(2)S5PV210最多支持1.5GB的内存,但实际开发板上不一定有这么多。例如X210开发板就只有512MB的内存(DRAM0端口分布256MB,DRAM1端口分布256MB)

(3)X210开发板上内存的合法地址是0x20000000~0x2FFFFFFF(256MB)+ 0x40000000~0x4FFFFFFF(256MB)

 

综合以上信息,进一步得出结论:

(1)X210开发板共使用了4片内存,每片1Gb(128MB),共512MB

(2)DRAM0对应的引脚是Xm1_xxxx

(3)DRAM1对应的引脚是Xm2_xxxx

(4)从数据总线的位数可知,X210开发板用的是32位的内存

 

四、查阅数据手册中DDR2初始化相关部分

 

S5PV210之SDRAM初始化_第6张图片
S5PV210之SDRAM初始化_第7张图片

 

由上图可知:初始化DDR2共需27个步骤。

 

综合前文所述,初始化DRAM时分为2部分:第一部分初始化DRAM0,第二部分初始化DRAM1。

 

编码实现部分只实现DRAM0的初始化,DRAM1的初始化步骤相同。

 

五、代码实现

 

1、led.c

 

#define GPJ0CON	 0xE0200240
#define GPJ0DAT	 0xE0200244

#define rGPJ0CON *((volatile unsigned int *)GPJ0CON)
#define rGPJ0DAT *((volatile unsigned int *)GPJ0DAT)

void delay(void);

void led_blink(void) {
	rGPJ0CON = 0x11111111;
	
	while(1) {
		// led亮
		rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));
		// 延时
		delay();
		// led灭
		rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));
		// 延时
		delay();
	}
}

void delay(void) {
	volatile unsigned int i = 900000;		
	while (i--);							
}

 

2、link.lds

 

SECTIONS
{
	. = 0x20000000;
	
	.text : {
		start.o
		sdram_init.o
		* (.text)
	}
    		
	.data : {
		* (.data)
	}
	
	bss_start = .; 
	.bss : {
		* (.bss)
	}
	
	bss_end  = .;	
}

 

3、Makefie

 

led.bin: start.o led.o sdram_init.o
	arm-linux-ld -Tlink.lds -o led.elf $^
	arm-linux-objcopy -O binary led.elf led.bin
	arm-linux-objdump -D led.elf > led_elf.dis
	gcc mkv210_image.c -o mkx210
	./mkx210 led.bin 210.bin
	
%.o : %.S
	arm-linux-gcc -o $@ $< -c -nostdlib

%.o : %.c
	arm-linux-gcc -o $@ $< -c -nostdlib

clean:
	rm *.o *.elf *.bin *.dis mkx210 -f

 

4、start.S

 

#define SVC_STACK	0xD0037D80

.global _start					
_start:
	ldr sp, =SVC_STACK

	// 初始化DDR
	bl sdram_asm_init
	
	// 重定位
	adr r0, _start  				
	ldr r1, =_start 	
	ldr r2, =bss_start	
	cmp r0, r1			
	beq clean_bss		

copy_loop:
	ldr r3, [r0], #4    
	str r3, [r1], #4	
	cmp r1, r2			
	bne copy_loop

clean_bss:
	ldr r0, =bss_start					
	ldr r1, =bss_end
	cmp r0, r1				
	beq run_on_dram			
	mov r2, #0
clear_loop:
	str r2, [r0], #4		
	cmp r0, r1				
	bne clear_loop

run_on_dram:	
	ldr pc, =led_blink				

	b .

 

5、sdram_init.S

 

#define DMC0_MEMCONTROL		0x00202400 	// MemControl	BL=4, 1Chip, DDR2 Type, dynamic self refresh, force precharge, dynamic power down off

#define DMC0_MEMCONFIG_0	0x20F01323	// MemConfig0	256MB config, 8 banks, Mapping Method[12:15] 0:linear, 1:linterleaved, 2:Mixed
#define DMC0_MEMCONFIG_1	0x30F00312	// MemConfig1	默认值

#define DMC0_TIMINGA_REF	0x00000618	// TimingAref	7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)
#define DMC0_TIMING_ROW		0x28233287	// TimingRow	for @200MHz
#define DMC0_TIMING_DATA	0x23240304	// TimingData	CL=3
#define	DMC0_TIMING_PWR		0x09C80232	// TimingPower

.global sdram_asm_init
sdram_asm_init:	
	ldr	r0, =0xf1e00000
	ldr	r1, =0x0
	str	r1, [r0, #0x0]

	/* DMC0 Drive Strength (Setting 2X) */
	
	ldr	r0, =ELFIN_GPIO_BASE

	ldr	r1, =0x0000AAAA
	str	r1, [r0, #MP1_0DRV_SR_OFFSET]		

	ldr	r1, =0x0000AAAA
	str	r1, [r0, #MP1_1DRV_SR_OFFSET]

	ldr	r1, =0x0000AAAA
	str	r1, [r0, #MP1_2DRV_SR_OFFSET]

	ldr	r1, =0x0000AAAA
	str	r1, [r0, #MP1_3DRV_SR_OFFSET]

	ldr	r1, =0x0000AAAA
	str	r1, [r0, #MP1_4DRV_SR_OFFSET]

	ldr	r1, =0x0000AAAA
	str	r1, [r0, #MP1_5DRV_SR_OFFSET]

	ldr	r1, =0x0000AAAA
	str	r1, [r0, #MP1_6DRV_SR_OFFSET]

	ldr	r1, =0x0000AAAA
	str	r1, [r0, #MP1_7DRV_SR_OFFSET]

	ldr	r1, =0x00002AAA
	str	r1, [r0, #MP1_8DRV_SR_OFFSET]
	
	/* DMC0 initialization at single Type */
	ldr	r0, =APB_DMC_0_BASE

	ldr	r1, =0x00101000	      @PhyControl0 DLL parameter setting, manual 0x00101000
	str	r1, [r0, #DMC_PHYCONTROL0]

	ldr	r1, =0x00000086	      @PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case
	str	r1, [r0, #DMC_PHYCONTROL1]

	ldr	r1, =0x00101002				@PhyControl0 DLL on
	str	r1, [r0, #DMC_PHYCONTROL0]

	ldr	r1, =0x00101003				@PhyControl0 DLL start
	str	r1, [r0, #DMC_PHYCONTROL0]

find_lock_val:
	ldr	r1, [r0, #DMC_PHYSTATUS]	@Load Phystatus register value
	and	r2, r1, #0x7
	cmp	r2, #0x7					@Loop until DLL is locked
	bne	find_lock_val
	
	and	r1, #0x3fc0 
	mov	r2, r1, LSL #18
	orr	r2, r2, #0x100000
	orr	r2 ,r2, #0x1000	
		
	orr	r1, r2, #0x3				@Force Value locking
	str	r1, [r0, #DMC_PHYCONTROL0]
	
#if 0	/* Memory margin test 10.01.05 */
	orr	r1, r2, #0x1				@DLL off
	str	r1, [r0, #DMC_PHYCONTROL0]
#endif
	/* setting DDR2 */
	ldr	r1, =0x0FFF2010				@ConControl auto refresh off
	str	r1, [r0, #DMC_CONCONTROL]

	ldr	r1, =DMC0_MEMCONTROL		@MemControl BL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
	str	r1, [r0, #DMC_MEMCONTROL]
	
	ldr	r1, =DMC0_MEMCONFIG_0		@MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
	str	r1, [r0, #DMC_MEMCONFIG0]

	ldr	r1, =DMC0_MEMCONFIG_1		@MemConfig1
	str	r1, [r0, #DMC_MEMCONFIG1]

	ldr	r1, =0xFF000000				@PrechConfig
	str	r1, [r0, #DMC_PRECHCONFIG]
	
	ldr	r1, =DMC0_TIMINGA_REF		@TimingAref	7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)
	str	r1, [r0, #DMC_TIMINGAREF]
	
	ldr	r1, =DMC0_TIMING_ROW		@TimingRow	for @200MHz
	str	r1, [r0, #DMC_TIMINGROW]

	ldr	r1, =DMC0_TIMING_DATA		@TimingData	CL=3
	str	r1, [r0, #DMC_TIMINGDATA]
	
	ldr	r1, =DMC0_TIMING_PWR		@TimingPower
	str	r1, [r0, #DMC_TIMINGPOWER]

	ldr	r1, =0x07000000				@DirectCmd	chip0 Deselect
	str	r1, [r0, #DMC_DIRECTCMD]
	
	ldr	r1, =0x01000000				@DirectCmd	chip0 PALL
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x00020000				@DirectCmd	chip0 EMRS2
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x00030000				@DirectCmd	chip0 EMRS3
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x00010400				@DirectCmd	chip0 EMRS1 (MEM DLL on, DQS# disable)
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x00000542				@DirectCmd	chip0 MRS (MEM DLL reset) CL=4, BL=4
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x01000000				@DirectCmd	chip0 PALL
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x05000000				@DirectCmd	chip0 REFA
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x05000000				@DirectCmd	chip0 REFA
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x00000442				@DirectCmd	chip0 MRS (MEM DLL unreset)
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x00010780				@DirectCmd	chip0 EMRS1 (OCD default)
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x00010400				@DirectCmd	chip0 EMRS1 (OCD exit)
	str	r1, [r0, #DMC_DIRECTCMD]
	
	ldr	r1, =0x07100000				@DirectCmd	chip1 Deselect
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x01100000				@DirectCmd	chip1 PALL
	str	r1, [r0, #DMC_DIRECTCMD]
	
	ldr	r1, =0x00120000				@DirectCmd	chip1 EMRS2
	str	r1, [r0, #DMC_DIRECTCMD]
	
	ldr	r1, =0x00130000				@DirectCmd	chip1 EMRS3
	str	r1, [r0, #DMC_DIRECTCMD]
	
	ldr	r1, =0x00110400				@DirectCmd	chip1 EMRS1 (MEM DLL on, DQS# disable)
	str	r1, [r0, #DMC_DIRECTCMD]
	
	ldr	r1, =0x00100542				@DirectCmd	chip1 MRS (MEM DLL reset) CL=4, BL=4
	str	r1, [r0, #DMC_DIRECTCMD]
	
	ldr	r1, =0x01100000				@DirectCmd	chip1 PALL
	str	r1, [r0, #DMC_DIRECTCMD]
	
	ldr	r1, =0x05100000				@DirectCmd	chip1 REFA
	str	r1, [r0, #DMC_DIRECTCMD]
	
	ldr	r1, =0x05100000				@DirectCmd	chip1 REFA
	str	r1, [r0, #DMC_DIRECTCMD]
	
	ldr	r1, =0x00100442				@DirectCmd	chip1 MRS (MEM DLL unreset)
	str	r1, [r0, #DMC_DIRECTCMD]
	
	ldr	r1, =0x00110780				@DirectCmd	chip1 EMRS1 (OCD default)
	str	r1, [r0, #DMC_DIRECTCMD]
		
	ldr	r1, =0x00110400				@DirectCmd	chip1 EMRS1 (OCD exit)
	str	r1, [r0, #DMC_DIRECTCMD]
		
	ldr	r1, =0x0FF02030				@ConControl	auto refresh on
	str	r1, [r0, #DMC_CONCONTROL]
		
	ldr	r1, =0xFFFF00FF				@PwrdnConfig
	str	r1, [r0, #DMC_PWRDNCONFIG]
		
	ldr	r1, =0x00202400				@MemControl	BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
	str	r1, [r0, #DMC_MEMCONTROL]

	mov pc, lr

 

你可能感兴趣的:(c,嵌入式,sdram)