Tiny4412裸机程序之代码在DDR SDRAM中运行

转载:http://www.techbulo.com/1509.html

Tiny4412裸机程序之代码在DDR SDRAM中运行

2014年11月13日  ⁄ 裸机程序 ⁄ 共 8647字 ⁄ 字号      ⁄ 评论 17 条 ⁄ 阅读 2,762 次

上一此实验我们讲解了如何对代码进行重定位,但是将代码重定位到只有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中的代码,搞明白它设置了哪些东西:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
/*
* (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文件进行对比,发现完全一样,说明代码已经拷贝到了正确的链接地址。

文件对比

文件对比

 

完整的程序下载地址(解压密码:WWW.techbulo.Com):

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值