Exynos4412裸机之DDR-SDRAM中重定位

发布者:春水碧于天最新更新时间:2018-10-14 来源: eefocus关键字:Exynos4412  裸机  DDR-SDRAM  重定位 手机看文章 扫描二维码
随时随地手机看文章

上一此实验我们讲解了如何对代码进行重定位,但是将代码重定位到只有256K的IRAM中作用不大。正确的做法是将代码重定位到容量更大的主存中,即DRAM中。

Exynos4412中有两个独立的DRAM控制器,分别叫DMC0和DMC1。DMC0和DMC1分别支持最大1.5GB的DRAM,它们都支持DDR2/DDR3和LPDDR2等,512 Mb, 1 Gb, 2 Gb, 4 Gb and 8 Gbit的内存设备,支持16/32bit的位宽。DRAM0 对应的地址是0x4000_0000~0xAFFF_FFF共1.5GB,DRAM1 对应的地址是0xA000_000~0x0000_0000共1.5GB。

DRAM控制器地址映射

DRAM控制器地址映射

Tiny4412的1GB的DRAM是由4片大小为128MX16的DDR3芯片组合而成,下面看一下Tiny4412的原理图:

Tiny4412 DDR电路图

Tiny4412 DDR电路图

Tiny4412 DDR电路图

Tiny4412 DDR电路图

从上两图可以看出,这四片DDR 芯片被分成了两两一组,组成32位数据,四片都是挂接到DMC0处。

如何才能使用DRAM?对应Tiny4412而言,由于用到了DMC0,所有我们需要初始化DMC0和DDR3 DRAM芯片。

声明一下:

从这一节开始我们的程序结构发生了一些变化,前几个实验我们只生成一个文件,从这个实验开始我们生成两个文件,BL2.bin和main.bin,其中BL2.bin文件的链接地址是0x02023400;(使用的是位置无关码,程序可以在任意可用的内存中运行),main.bin 文件的链接地址是0x43E00000(使用的并不是位置无关码,所有程序必须位于该地址处才能正常运行)。需要在SD卡上烧写三部分程序,分别是:

1.BL1(由三星提供):实现一些初始化

2.BL2(我们自己编写源码,用mkbl2工具生成):板级初始化,并完成代码重定位到DDR SDRAM,完成跳转

3.主代码:实现我们想要的功能

三部分代码在SD卡的位置如下:

程序在SD卡的位置分布

程序在SD卡的位置分布

从图中可以看出,BL1.bin烧写到SD卡扇区1,BL2.bin烧写到sd卡的扇区17,main.bin烧写到sd卡的扇区49处。

整个程序的运行过程大致如下:系统上电后,首先将sd卡扇区1处的bl1拷贝到IRAM的0x02020000地址处,然后运行该部分代码,该部分代码首先又会加载BL2.bin,BL2.bin会进行时钟和DRAM初始化,然后把位于sd卡中扇区49处的main.bin拷贝到DRAM的0x43E00000地址处,最后跳转到该地址处继续运行。

 

一、程序说明

DDR的初始化顺序在前一篇文章Tiny4412裸机程序之DDR3初始化流程我们已经经过,下面就根据前面提及的步骤一一来进行设置。

注:看到这么多设置步骤,实在太繁琐了,我们参考u-boot for Tiny4412中的代码,搞明白它设置了哪些东西:

================================================================

//(C) Copyright 2011 Samsung Electronics Co. Ltd

//

//See file CREDITS for list of people who contributed to this

//project.

//

//This program is free software; you can redistribute it and/or modify

//it under the terms of the GNU General Public License version 2 as

//published by the Free Software Foundation.

 

#include "config.h"

#include "asm/arch/cpu.h"

 

#define MCLK_400

.globl mem_ctrl_asm_init

mem_ctrl_asm_init:

 

// Async bridge configuration at CPU_core:

// 1: half_sync

// 0: full_sync */

ldr r0, =0x10010350

mov r1, #1

str r1, [r0]

// 这几行代码不知道什么意思,以及这样做的原因

 

///////////////////////////////////////////////////////////////////

//--------------------------------DREX0---------------------------

///////////////////////////////////////////////////////////////////

 

ldr r0, =APB_DMC_0_BASE

 

ldr r1, =0xe0000086

str r1, [r0, #DMC_PHYCONTROL1]

//2. If on die termination is required, enable PhyControl1.term_write_en,

//PhyControl1.term_read_en.

 

ldr r1, =0xE3854C03

str r1, [r0, #DMC_PHYZQCONTROL]

//3. If ZQ calibration is required, disable PhyZQControl.

// ctrl_zq_mode_noterm and enable PhyZQCon-trol.

// ctrl_zq_start so that the PHY automatically calibrates

// the I/Os to match the driving and termination impedance

// by referencing resistor value of an external resistor

// and updates the matched value during auto re-fresh cycles.

 

mov r2, #0x100000

1: subs r2, r2, #1

bne 1b

ldr r1, =0x7110100A

str r1, [r0, #DMC_PHYCONTROL0]

//4. 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 activate the PHY DLL.

 

ldr r1, =0xe0000086

str r1, [r0, #DMC_PHYCONTROL1]

//5. DQS Cleaning: set the PhyControl1.ctrl_shiftc and PhyControl1.

// ctrl_offsetc bit-fields to the proper value according to clock frequency,

// board delay and memory tDQSCK parameter.

 

ldr r1, =0x7110100B

str r1, [r0, #DMC_PHYCONTROL0]

// 6. Set the PhyControl0.ctrl_start bit-field to "1".

 

ldr r1, =0x00000000

str r1, [r0, #DMC_PHYCONTROL2]

// DQS offset

// 实验了一下可以省略,默认值就是全零

 

ldr r1, =0x0FFF301A

str r1, [r0, #DMC_CONCONTROL]

// 7. Set the ConControl. At this moment,an auto refresh counter should be off.

 

ldr r1, =0x00312640

str r1, [r0, #DMC_MEMCONTROL]

// 8. Set the MemControl. At this moment,

// all power down modes and periodic ZQ(pzq_en) should be off.

 

ldr r1, =0x40e01323

str r1, [r0, #DMC_MEMCONFIG0]

ldr r1, =0x60e01323

str r1, [r0, #DMC_MEMCONFIG1]

// 9. Set the MemConfig0 register. If there are two external memory chips,

// also set the MemConfig1 register.

 

ldr r1, =(0x80000000 | CONFIG_IV_SIZE)

str r1, [r0, #DMC_IVCONTROL]

// Memory Channel Interleaving

// 实验了一下可以省略,用默认值就可以

 

ldr r1, =0xff000000

str r1, [r0, #DMC_PRECHCONFIG]

// 10. Set the PrechConfig and PwrdnConfig registers.

 

ldr r1, =0x000000BB

str r1, [r0, #DMC_TIMINGAREF] @TimingAref

ldr r1, =0x4046654f

str r1, [r0, #DMC_TIMINGROW] @TimingRow

ldr r1, =0x46400506

str r1, [r0, #DMC_TIMINGDATA] @TimingData

ldr r1, =0x52000a3c

str r1, [r0, #DMC_TIMINGPOWER] @TimingPower

// 11. Set the TimingAref, TimingRow, TimingData and

// TimingPower registers according to memory AC parame-ters.

 

// chip 0 

ldr r1, =0x07000000

str r1, [r0, #DMC_DIRECTCMD]

// 19. Issue a NOP command using the DirectCmd register to assert 

//and to hold CKE to a logic high level.

 

mov r2, #0x100000

2: subs r2, r2, #1

bne 2b

// 20. Wait for tXPR(max(5nCK,tRFC(min)+10ns)) or set tXP to tXPR value before step 

// 17. If the system set tXP to tXPR, then the system must set tXP to proper value 

//     before normal memory operation.

 

ldr r1, =0x00020000

str r1, [r0, #DMC_DIRECTCMD]

ldr r1, =0x00030000

str r1, [r0, #DMC_DIRECTCMD]

ldr r1, =0x00010002

str r1, [r0, #DMC_DIRECTCMD]

ldr r1, =0x00000328

str r1, [r0, #DMC_DIRECTCMD]

// 没搞明白这里发的什么指令

 

mov r2, #0x100000

3: subs r2, r2, #1

bne 3b

 

ldr r1, =0x0a000000

str r1, [r0, #DMC_DIRECTCMD]

// 26. Issues a ZQINIT commands using the DirectCmd register.*/

 

mov r2, #0x100000

4: subs r2, r2, #1

bne 4b

// 27. If there are two external memory chips, perform steps 19 ~ 26 

//     procedures for chip1 memory device.

#if 1

// chip 1 

ldr r1, =0x07100000

str r1, [r0, #DMC_DIRECTCMD]

 

mov r2, #0x100000

5: subs r2, r2, #1

bne 5b

 

ldr r1, =0x00120000

str r1, [r0, #DMC_DIRECTCMD]

ldr r1, =0x00130000

str r1, [r0, #DMC_DIRECTCMD]

ldr r1, =0x00110002

str r1, [r0, #DMC_DIRECTCMD]

ldr r1, =0x00100328

str r1, [r0, #DMC_DIRECTCMD]

 

mov r2, #0x100000

6: subs r2, r2, #1

bne 6b

 

ldr r1, =0x0a100000

str r1, [r0, #DMC_DIRECTCMD]

 

mov r2, #0x100000

7: subs r2, r2, #1

bne 7b

#endif

 

ldr r1, =0xe000008e

str r1, [r0, #DMC_PHYCONTROL1]

ldr r1, =0xe0000086

str r1, [r0, #DMC_PHYCONTROL1]

 

mov r2, #0x100000

8: subs r2, r2, #1

bne 8b

///////////////////////////////////////////////////////////////////

//---------------------------DREX1--------------------------------/

///////////////////////////////////////////////////////////////////

 

ldr r0, =APB_DMC_1_BASE

 

ldr r1, =0xe0000086

str r1, [r0, #DMC_PHYCONTROL1]

 

ldr r1, =0xE3854C03

str r1, [r0, #DMC_PHYZQCONTROL]

 

mov r2, #0x100000

1: subs r2, r2, #1

bne 1b

 

ldr r1, =0xe000008e

str r1, [r0, #DMC_PHYCONTROL1]

ldr r1, =0xe0000086

str r1, [r0, #DMC_PHYCONTROL1]

 

ldr r1, =0x71101008

str r1, [r0, #DMC_PHYCONTROL0]

ldr r1, =0x7110100A

str r1, [r0, #DMC_PHYCONTROL0]

 

ldr r1, =0xe0000086

str r1, [r0, #DMC_PHYCONTROL1]

ldr r1, =0x7110100B

str r1, [r0, #DMC_PHYCONTROL0]

 

ldr r1, =0x00000000

str r1, [r0, #DMC_PHYCONTROL2]

 

ldr r1, =0x0FFF301A

str r1, [r0, #DMC_CONCONTROL]

ldr r1, =0x00312640

str r1, [r0, #DMC_MEMCONTROL]

 

ldr r1, =0x40e01323 @Interleaved?

str r1, [r0, #DMC_MEMCONFIG0]

ldr r1, =0x60e01323

str r1, [r0, #DMC_MEMCONFIG1]

 

ldr r1, =(0x80000000 | CONFIG_IV_SIZE)

 

str r1, [r0, #DMC_IVCONTROL]

 

ldr r1, =0xff000000

str r1, [r0, #DMC_PRECHCONFIG]

 

ldr r1, =0x000000BB

str r1, [r0, #DMC_TIMINGAREF] @TimingAref

 

ldr r1, =0x4046654f

str r1, [r0, #DMC_TIMINGROW] @TimingRow

ldr r1, =0x46400506

str r1, [r0, #DMC_TIMINGDATA] @TimingData

ldr r1, =0x52000a3c

str r1, [r0, #DMC_TIMINGPOWER] @TimingPower

 

// chip 0 

ldr r1, =0x07000000

str r1, [r0, #DMC_DIRECTCMD]

 

mov r2, #0x100000

2: subs r2, r2, #1

bne 2b

 

ldr r1, =0x00020000

str r1, [r0, #DMC_DIRECTCMD]

ldr r1, =0x00030000

str r1, [r0, #DMC_DIRECTCMD]

ldr r1, =0x00010002

str r1, [r0, #DMC_DIRECTCMD]

ldr r1, =0x00000328

str r1, [r0, #DMC_DIRECTCMD]

 

mov r2, #0x100000

3: subs r2, r2, #1

bne 3b

 

ldr r1, =0x0a000000

str r1, [r0, #DMC_DIRECTCMD]

 

mov r2, #0x100000

4: subs r2, r2, #1

bne 4b

 

#if 1

// chip 1 

ldr r1, =0x07100000

str r1, [r0, #DMC_DIRECTCMD]

 

mov r2, #0x100000

5: subs r2, r2, #1

bne 5b

 

ldr r1, =0x00120000

str r1, [r0, #DMC_DIRECTCMD]

ldr r1, =0x00130000

str r1, [r0, #DMC_DIRECTCMD]

ldr r1, =0x00110002

str r1, [r0, #DMC_DIRECTCMD]

ldr r1, =0x00100328

str r1, [r0, #DMC_DIRECTCMD]

 

mov r2, #0x100000

6: subs r2, r2, #1

bne 6b

 

ldr r1, =0x0a100000

str r1, [r0, #DMC_DIRECTCMD]

 

mov r2, #0x100000

7: subs r2, r2, #1

bne 7b

#endif

 

ldr r1, =0xe000008e

str r1, [r0, #DMC_PHYCONTROL1]

ldr r1, =0xe0000086

str r1, [r0, #DMC_PHYCONTROL1]

 

mov r2, #0x100000

8: subs r2, r2, #1

bne 8b

///////////////////////////////////////////////////////////////////

//-----------------------Finalize---------------------------------/

///////////////////////////////////////////////////////////////////

 

ldr r0, =APB_DMC_0_BASE

ldr r1, =0x0FFF303A

str r1, [r0, #DMC_CONCONTROL]

// 28. Set the ConControl to turn on an auto refresh counter.

 

ldr r0, =APB_DMC_1_BASE

ldr r1, =0x0FFF303A

str r1, [r0, #DMC_CONCONTROL]

// 28. Set the ConControl to turn on an auto refresh counter.

 

mov pc, lr

================================================================

二、编译、烧写、运行

1.编译

通过FTP或者其他工具将文件上传到服务器上去,输入make命令进行编译将得到make_bl2.bin和main.bin文件。

2.烧写

将SD卡插入电脑,并让VmWare里的Ubuntu识别出来,然后执行如下命令:

1

sudo ./sd_fusing.sh /dev/sdb ../9_reload_ddr/BL2/make_bl2.bin ../9_reload_ddr/MAIN/main.bin

程序烧写

程序烧写

二、运行现象

将SD卡插入Tiny4412开发板,连接串口工具,上电,你会看到和上一节的运行效果一样(因为我们没有修改LED的显示效果,只是修改了程序的运行地址,这个对外是看不出区别的)。

串口可以看到如下显示信息;

运行效果

运行效果

从图的信息室打印的地址0x43E00000处的内容(main.bin文件的链接地址)

我们将上述打印的信息和main.bin文件进行对比,发现完全一样,说明代码已经拷贝到了正确的链接地址。

文件对比

文件对比


关键字:Exynos4412  裸机  DDR-SDRAM  重定位 引用地址:Exynos4412裸机之DDR-SDRAM中重定位

上一篇:Exynos4412裸机程序之UART收发数据
下一篇:Exynos4412裸机程序之DDR3初始化流程

推荐阅读最新更新时间:2024-03-16 16:16

S3C2440—2.裸机开发步骤及工具使用
一.裸机开发步骤简介 1.在X86架构的Windows系统中 1.建立工程 2.编辑源代码 3.编译(VC6.0) 4.运行 2.在X86架构的Ubuntu系统中 1.编辑源代码(vim) 2.编译(gcc) 3.运行 3.ARM裸机开发 1.编辑源代码(Windows:Source insight或者Notepad++) 2.编译(涉及到交叉编译:arm-linux-gcc) arm-linux-gcc是基于Linux系统的arm编译器,功能强大、稳定、支持qrm芯片多。 3.烧写 4.运行 注意: 使用ads(停止更新)、MDK编译器,是win系统的编译器,功能很弱,只适合个
[单片机]
S3C2440—2.<font color='red'>裸机</font>开发步骤及工具使用
做ARM裸机C与程序时的注意事项
在设置好芯片类型,弄好芯片寄存器的宏定义后,接下来的编程就是走C的标准程序设计了。想法正确,但是ARM程序设计与以前大家学的8051是有差别的。 以前在KeilC51里面,在建立完工程之后,Keil会提示是否加入startup.a51的文件,这个文件用来初始化51芯片的各个硬件资源。如果不加,往往程序会运行出错。 对于ARM裸机,也一样,只不过RVDS编译器不会给你提供初始化的文件,都要自己写。一般工程文件为汇编和C的混合。因为现在的学习还不够深入,所以目前也只清楚一些简单的程序设计框架。 例如,一般在工程文件中加一个init.s的汇编文件。里面仅有一句用于跳转的汇编语句。假如你的C语言的入口函数为main,那么这句语句就是
[单片机]
做ARM<font color='red'>裸机</font>C与程序时的注意事项
基于mini2440的按键中断控制LED(裸机代码)
#define GLOBAL_CLK //相当于定义了FCLK,HCLK,PCLK,UCLK #include def.h #include option.h #include mmu.h #include 2440addr.h #define LED1_on rGPBDAT = ((0xf 5)^(1 5)) //GPB5=0 #define LED2_on rGPBDAT = ((0xf 5)^(1 6)) //GPB6=0 #define LED3_on rGPBDAT = ((0xf 5)^(1 7)) //GPB7=0 #define LED4_on rGPBDAT = ((0xf 5)^(1 8))
[单片机]
S3C2440裸机------NandFlash编程_时序及初始化
1.NandFlash初始化 Nandflash初始化主要包括时序图的设置和Nandflash控制器的使能,我们首先看一下S3C2440芯片手册里面的时序图。 上图中的HCLK我们已经设置成了100M。那么时钟周期是1/100M=10ns 然后下图是NandFlash芯片手册里面的时序图。 我们将S2C2440里面NandFlash控制器的时序图和NandFlash时序图结合起来看。 左图中的TACLS表示当我们的CLE/ALE发出之后,再过多长时间再发出WE信号,就是右图中的tcls-twp,而我们从右下图可以看到,tcls的最小值是12,twp的最小值也是12,就表明tcls-twp可以为零,也就表明CLE
[单片机]
S3C2440<font color='red'>裸机</font>------NandFlash编程_时序及初始化
第019课 I2C协议详解及裸机程序分析
第001节_I2C协议与EEPROM I2C协议 I2C在硬件上的接法如下(图19-1)所示,主控芯片引出两条线SCL,SDA线,在一条I2C总线上可以接很多I2C设备,我们还会放一个上拉电阻(放一个上拉电阻的原因以后我们再说)。 我们怎么传输数据,我们需要发数据从主设备发送到从设备上去,也需要把数据从从设备传送到主设备上去,数据涉及到双向传输。 举个例子: 体育老师:可以把球发给学生,也可以把球从学生中接过来。 1.发球:a.老师说:注意了(start) b.老师对A学生说我要球发给你(地址)。 :: c.老师就把球发出去了(传输)。 :: d.A收到球之后,应该告诉老师一声(回应)。 :: e.老师说下
[单片机]
第019课 I2C协议详解及<font color='red'>裸机</font>程序分析
s3c2440裸机-LCD编程(二、LCD控制器)
1.LCD控制器框图 从上图看出,S3C2440 LCD控制器用于传输视频数据并且生成必要的控制信号,如VFRAME,VLINE,VCLK,VM等。除了控制信号,S3C2440还有视频数据端口,即VD 。通过设置REGBANK(寄存器组),LCDCDMA会自动(无需CPU参与)把内存上FrameBuffer里的数据,通过VIDPRCS发送到引脚VD 数据总线上,再配合VIDEOMUX引脚的控制信号,正确的显示出来。 REGBANK:具有17个可编程寄存器组和256x16调色板存储器,用于配置LCD控制器。 TIMEGEN:产生控制信号,例如 VSYNC、HSYNC、VCLK等信号 LCDCDMA:可以自动从FrameBuff中
[单片机]
s3c2440<font color='red'>裸机</font>-LCD编程(二、LCD控制器)
传统彩电商IT领域定位 云端是决战场所
  青岛海信电器股份有限公司总经理刘洪新也没想到,仅仅半年时间,智能电视就从概念变成了身边的现实,而且是全球热点。记得去年9月份海信电器第一次提出“智能电视”概念之际,记者问他什么时候上Android系统的电视,他嗫嚅着说,“时机不成熟”,“不确定”。   也还记得,在今年初美国CES大展上,英特尔、Google、D-link、微软、苹果等IT厂商冲破电视的围墙,夹着很炫的产品趾高气昂站在电视厂商前面,等着看后者的反应,仿佛在说,“我们来了,你们怎么办?”   先前错愕的电视厂商转身整合了IT资源,拿着装有Android系统或windows系统的智能电视,跑到IT厂商面前,高声说,“看,这并不难。”更出人意料的是,电视厂商
[家用电子]
S3C2440裸机之用查询方式按键控制LED
前言 本文基于JZ2440开发板 一、思维导图 二、代码 1.key_led.c 代码如下(示例): /************************************************************************ * * 文件名:key_led.c * * 功能: 用EINT0(GPF0)按键控制D12(GPF6), 用EINT2(GPF2)按键控制D11(GPF5), 用EINT11(GPG3)按键控制D10(GPF4) * * 创建人:LiZhenhao * * 时间:2021年10月9日16:49:52 * * 版本号:1.0 * * 修改记录:无 * ********
[单片机]
S3C2440<font color='red'>裸机</font>之用查询方式按键控制LED
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved