(7)初始化DRAM并重定位代码到DRAM中

11 篇文章 0 订阅

一、DRAM初始化步骤
第一步、设置 DRAM Driver Strength( 内存访问信号的强度)
第二步、初始化 PHY DLL
第三步、初始化 DMC0
第四步、初始化 DDR2 DRAM

二、相关代码
1、dram_init.S

#include "s5pv210.h"

// MemControl	BL=4, 1Chip, DDR2 Type, dynamic self refresh, force precharge, dynamic power down off
#define DMC0_MEMCONTROL			0x00202400
// MemConfig0	256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
#define DMC0_MEMCONFIG_0		0x20F00313	
// MemConfig1
#define DMC0_MEMCONFIG_1		0x00F00313	

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

.globl dram_init
dram_init:
	// 1. 设置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]

	// 2. 初始化PHY DLL
	ldr	r0, =APB_DMC_0_BASE
	//step 3: PhyControl0 DLL parameter setting, manual 0x00101000
	ldr	r1, =0x00101000					
	str	r1, [r0, #DMC_PHYCONTROL0]
	//PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case
	ldr	r1, =0x00000086					
	str	r1, [r0, #DMC_PHYCONTROL1]
	
	//step 2: PhyControl0 DLL on
	ldr	r1, =0x00101002					
	str	r1, [r0, #DMC_PHYCONTROL0]
	//step 4: PhyControl0 DLL start
	ldr	r1, =0x00101003					
	str	r1, [r0, #DMC_PHYCONTROL0]

find_lock_val:
	//Loop until DLL is locked
	ldr	r1, [r0, #DMC_PHYSTATUS]			
	and	r2, r1, #0x7
	cmp	r2, #0x7					
	bne	find_lock_val

	//Force Value locking
	and	r1, #0x3fc0
	mov	r2, r1, LSL #18
	orr	r2, r2, #0x100000
	orr	r2 ,r2, #0x1000
	orr	r1, r2, #0x3					
	str	r1, [r0, #DMC_PHYCONTROL0]

	// 3. 初始化DMC0
	//step 5: ConControl auto refresh off
	ldr	r1, =0x0FFF2010					
	str	r1, [r0, #DMC_CONCONTROL]
	//step 6: MemControl BL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
	ldr	r1, =DMC0_MEMCONTROL				
	str	r1, [r0, #DMC_MEMCONTROL]
	//step 7: MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
	ldr	r1, =DMC0_MEMCONFIG_0				
	str	r1, [r0, #DMC_MEMCONFIG0]
	//MemConfig1
	ldr	r1, =DMC0_MEMCONFIG_1				
	str	r1, [r0, #DMC_MEMCONFIG1]
	//step 8:PrechConfig
	ldr	r1, =0xFF000000					
	str	r1, [r0, #DMC_PRECHCONFIG]
	//step 9:TimingAref	7.8us//133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)
	ldr	r1, =DMC0_TIMINGA_REF				
	str	r1, [r0, #DMC_TIMINGAREF]
	//TimingRow	for //200MHz
	ldr	r1, =DMC0_TIMING_ROW				
	str	r1, [r0, #DMC_TIMINGROW]
	//TimingData	CL=4
	ldr	r1, =DMC0_TIMING_DATA				
	str	r1, [r0, #DMC_TIMINGDATA]
	//TimingPower
	ldr	r1, =DMC0_TIMING_PWR				
	str	r1, [r0, #DMC_TIMINGPOWER]

	// 4. 初始化DDR2 DRAM
	//DirectCmd	chip0 Deselect
	ldr	r1, =0x07000000					
	str	r1, [r0, #DMC_DIRECTCMD]
	//step 16:DirectCmd	chip0 PALL
	ldr	r1, =0x01000000					
	str	r1, [r0, #DMC_DIRECTCMD]
	//step 17:DirectCmd	chip0 EMRS2
	ldr	r1, =0x00020000					
	str	r1, [r0, #DMC_DIRECTCMD]
	//step 18:DirectCmd	chip0 EMRS3
	ldr	r1, =0x00030000					
	str	r1, [r0, #DMC_DIRECTCMD]
	//step 19:DirectCmd	chip0 EMRS1 (MEM DLL on, DQS# disable)
	ldr	r1, =0x00010400					
	str	r1, [r0, #DMC_DIRECTCMD]
	//step 20:DirectCmd	chip0 MRS (MEM DLL reset) CL=4, BL=4
	ldr	r1, =0x00000542					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip0 PALL
	ldr	r1, =0x01000000					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip0 REFA
	ldr	r1, =0x05000000					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip0 REFA
	ldr	r1, =0x05000000					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip0 MRS (MEM DLL unreset)
	ldr	r1, =0x00000442					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip0 EMRS1 (OCD default)
	ldr	r1, =0x00010780					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip0 EMRS1 (OCD exit)
	ldr	r1, =0x00010400					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip1 Deselect
	ldr	r1, =0x07100000					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip1 PALL
	ldr	r1, =0x01100000					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip1 EMRS2
	ldr	r1, =0x00120000					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip1 EMRS3
	ldr	r1, =0x00130000					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip1 EMRS1 (MEM DLL on, DQS# disable)
	ldr	r1, =0x00110400					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip1 MRS (MEM DLL reset) CL=4, BL=4
	ldr	r1, =0x00100542					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip1 PALL
	ldr	r1, =0x01100000					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip1 REFA
	ldr	r1, =0x05100000					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip1 REFA
	ldr	r1, =0x05100000					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip1 MRS (MEM DLL unreset)
	ldr	r1, =0x00100442					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip1 EMRS1 (OCD default)
	ldr	r1, =0x00110780					
	str	r1, [r0, #DMC_DIRECTCMD]
	//DirectCmd	chip1 EMRS1 (OCD exit)
	ldr	r1, =0x00110400					
	str	r1, [r0, #DMC_DIRECTCMD]
	//ConControl	auto refresh on
	ldr	r1, =0x0FF02030					
	str	r1, [r0, #DMC_CONCONTROL]
	//PwrdnConfig
	ldr	r1, =0xFFFF00FF					
	str	r1, [r0, #DMC_PWRDNCONFIG]
	//MemControl	BL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
	ldr	r1, =0x00202400					
	str	r1, [r0, #DMC_MEMCONTROL]

	mov	pc, lr

该代码来自友善之臂官方用户手册。
2、s5pv210.h
这里面都是一些和寄存器有关的宏定义,内容太多就不贴出来了。
3、start.s

/*
 *		代码:初始化DRAM并且重定位代码到DRAM0x30000000
 *		日期:2020.7.12
 *		作者:glass love
 *
 */
 
//要开icache就将 CONFIG_SYS_ICACHE_OFF写为1,关则写为0
#define CONFIG_SYS_ICACHE            1
 
.globl _start
_start:

/**********************关看门狗*******************************/
//通过查阅数据手册知道控制看门狗开关的寄存器是:
//Watchdog Timer Control Register (WTCON, R/W, Address =0xE2700000 ) 
//WTCON寄存器的bit[0]位是启用或禁用复位信号的看门狗定时器输出位
//1为启用,0为禁止
//因此只需要往WTCON中写入0x0即可
	ldr r0, =0x00000000
	ldr r1, =0xE2700000
	str r0, [r1]
	
/**********************开icache*********************************/
//打开icache可以提高运行速度
	//读出协处理器cp15的c1的值到r0中
	mrc p15, 0, r0, c1, c0, 0
#if	CONFIG_SYS_ICACHE
	//将cp15协处理器的bit[12]置一(开icache)
	orr r0, r0, #0x00001000
#else
	//将cp15协处理器的bit[12]清零(关icache)
	bic r0, r0, #0x00001000
#endif
	//将r0中的值写入到cp15协处理器的c1中
	mcr p15, 0, r0, c1, c0, 0
	
/***********************设置栈****************************/
//IROM 里的固定代码设置的 sp 就等于 0xD003_7D80,
//所以我们设置栈一般就指向0xD003_7D80,以调用c函数

	ldr sp, =0xD0037D80
	
	
/**********************初始化DRAM**************************/
	bl dram_init
	
/*************************重定位***************************/
//adr短加载,加载_start的地址,即_start的当前地址
	adr r0, _start
//ldr长加载,加载_start的链接地址
	ldr r1, =_start
//加载bss_start的链接地址
	ldr r2, =bss_start
//比较r0和r1是否相同
	cmp r0, r1
	beq clear_bss
	
//复制代码到链接地址
copy_loop:
	ldr r3, [r0], #4      //源代码
	str r3, [r1], #4      //目标代码
	cmp r1, r2			  //只用复制到bss_start处就可以了
	bne copy_loop
	
//清bss段
clear_bss:
	ldr r0, =bss_start
	ldr r1, =bss_end
	cmp r0, r1
	beq run_dram
	ldr r2, =0x0
clear_loop:
	str r2, [r0], #4
	cmp r0, r1
	bne clear_loop
	
//跳转到链接地址中的led函数处
run_dram:
	ldr pc, =led_blink

//汇编死循环	
	b .

4、dram.lds

SECTIONS
{
	. = 0x30000000;          /*指定链接地址为DRAM0的0x30000000地址*/
	
	.text : {
		start.o              /*表示start.o排在代码段的最开始*/
		* (.text)			 /*(.text)表示后面的顺序随意*/
	}
    		
	.data : {
		* (.data)
	}
	
	bss_start = .;          /*将bss段的起始地址赋给bss_start,以方便外部使用该地址*/
	.bss : {
		* (.bss)
	}
	
	bss_end  = .;	       /*bss_end同上*/
}

5、Makefile

led_link_dram.bin: start.o led.o dram_init.o
	arm-linux-ld -Tdram.lds -o led_link_dram.elf $^                 
	arm-linux-objcopy -O binary led_link_dram.elf led_link_dram.bin			  
	arm-linux-objdump -D led_link_dram.elf > led_link_dram_elf.dis   		  
	gcc mkv210_image.c -o mk210              		  
	./mk210 led_link_dram.bin 210.bin 						  
	
%.o : %.S
	arm-linux-gcc -o $@ $< -c -nostdlib

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

clear:
	rm *.o *.elf *.bin *.dis mk210 -f

其余几个代码较上一节均为变化。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值