上一此实验我们讲解了如何对代码进行重定位,但是将代码重定位到只有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控制器地址映射
Tiny4412的1GB的DRAM是由4片大小为128MX16的DDR3芯片组合而成,下面看一下Tiny4412的原理图:
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卡的位置分布
从图中可以看出,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裸机程序之UART收发数据
下一篇:Exynos4412裸机程序之DDR3初始化流程
推荐阅读
史海拾趣
柯爱亚一直秉承“持续改进,满足客户要求,不断创新,超越客户期望”的品质方针。公司严格把控产品质量,从原材料采购到生产流程,再到产品检测,每一个环节都力求精益求精。这种对品质的坚持赢得了客户的信任,柯爱亚的产品逐渐在市场上树立了良好的口碑。
爱特姆在国内市场取得一定成绩后,开始积极拓展国际市场。通过与欧洲、美国等国家的知名企业建立合作关系,爱特姆的产品逐渐打入国际市场,并赢得了良好的口碑。同时,公司还积极参加国际电子展会,与全球同行交流学习,不断提升自身的国际竞争力。
艾为电子注重与产业链上下游企业的合作,通过协同创新和资源共享,实现共赢发展。例如,艾为与歌尔股份建立了长期合作伙伴关系,双方在声光电射手等领域展开了深度合作,共同推出了多款优秀产品。此外,艾为还与多家ODM厂商和智能硬件企业建立了紧密的合作关系,共同推动产业链的协同发展。
在技术创新和产品创新的基础上,Corex Intervest Inc公司开始积极拓展市场。公司通过参加国际电子展览、与各大电商平台合作等方式,不断提升品牌知名度和影响力。同时,公司还注重与客户的沟通与合作,根据客户需求定制产品方案,赢得了客户的广泛信任和好评。
在公司的快速发展中,BERNSTEIN公司逐渐将目光投向了国际市场。通过与国际知名企业的合作与交流,公司不断引进先进的技术和管理经验,提升了自身的竞争力。同时,BERNSTEIN公司的产品也逐渐在国际市场上赢得了广泛的认可和好评,为公司的发展注入了新的动力。
Elytone Electronics Co Ltd成立于XXXX年,最初是一家仅有几名员工的小型电子产品加工厂。公司创始人凭借对电子技术的热爱和对市场敏锐的洞察力,带领团队开始了艰苦的创业之路。在资源有限的情况下,他们不断研发新产品,优化生产工艺,逐步在行业内建立起了一定的知名度。
使用GetHostByAddr通过Ip地址获取主机名,但是经常不能获取成功,偶尔成功后获取的主机名是localhost。错误时,返回值是11001,并且通过抓包软件不能抓到任何的数据。希望高手指教。… 查看全部问答∨ |
|
把虚拟机的网卡设为192.168.126.***,tornado的config.h文件里设为#define DEFAULT_BOOT_LINE \\ "lnPci(0,0)LENOVO-1111111:c:\\\\vxworks h=172.16.100.163 e=172.16.100.111 u=target pw=target tn=target" ...… 查看全部问答∨ |
这是一个用51将HT6221红外编码解码 并将码通过串口发送给PC 用vb编写PC接收程序实现鼠标移动、待机、一键虚拟键盘、小键盘、鼠标左键单双击、鼠标右键单击的程序,没有多键触控,设置串口码率1200bps com4 无奇偶校验 屏幕分辨率1280*800,下面是51 ...… 查看全部问答∨ |
Andrew Armutat 产品市场部 吉时利仪器公司 2602型双通道系统源表[1] 测试应用与设备结构的配合 在面临这些挑战时,生产测试工程师必须彻底纵览ATE前景,寻找新的硬件结构和软件结构,从中找出满足其测试功能所需的最佳选择。当然,根据 ...… 查看全部问答∨ |
采用TI AM335X系列处理器,最高720MHz高速ARM Cortex-A8核心; 256MB DDR2 SDRAM(RAM最大扩展至512M,批量用户定制)使较多代码程序运行成为可能; 256MB NandFlash 2MB DataFlash(Flash最大扩展至64GB ...… 查看全部问答∨ |
ADuM1440/ADuM1441/ADuM1442/ADuM1445/ ADuM1446/ADuM1447是采用ADI公司iCoupler®技术的微功耗、4通道数字隔离器。 这些隔离器件结合了高速互补金属氧化物半导体(CMOS)与单片空芯变压器技 ...… 查看全部问答∨ |