在上一章中,将代码重定位到了SRAM中,但是这样的做法作用不大。正确的做法的是将代码重定位到更大的主存中,即DRAM。Tiny6410的DRAM控制寄存器最多只能支持两个同一类型的芯片。每个芯片最多可分配256MB的地址空间,所有的芯片在相同的端口共享所有的引脚,除了时钟启动信号和片选信号。

通过原理图

DRAM的地址为0x50000000

通过原理图可知SDRAM的使用的是K4X1G163PE-L(F)E/GC6。通过查看该芯片的数据手册可知道,如何启动SDRAM控制寄存器。

SDRAM  初始化顺序
  上电复位时,软件必须初始化 DRAM 控制器,SDRAM 的每一项都连接到 DRAM 控制器?仅以 SDRAM 的数据表为启动程序
1 1 . M DRAM  控制器初始化顺序
(1)以 ‘3’b100’ 执行 memc_cmd,使得 DRAM 控制器输入‘配置’状态
(2)写存储器时间参数,芯片配置和 ID 配置寄存器
(3)等待 200μs 来使 SDRAM 电源和时钟稳定?当 CPU 开始工作时,电源和时钟已经被稳定下来
(4)执行存储器初始化顺序
(5)以 ‘3’b000’ 执行 memc_cmd,使得 DRAM 控制器输入‘准备’状态
(6)在 memc_stat 中检查存储器状态域,直到存储器状态变为 ‘2’b01’ ,即‘准备’

DDR/ 移动  M DDR SDRAM  初始化顺序
(1)在 direct_cmd,以‘ 2’b10 ’执行 mem_cmd,使得 DRAM 控制器产生‘NOP’存储器命令
(2)在 direct_cmd,以‘ 2’b00 ’执行 mem_cmd,使得 DRAM 控制器产生‘Prechargeall’存储器命令
(3)在 direct_cmd,以‘ 2’b11 ’执行 mem_cmd,使得 DRAM 控制器产生‘Autorefresh’存储器命令
(4)在 direct_cmd,以‘ 2’b10 ’执行 mem_cmd,使得 DRAM 控制器产生‘MRS’存储器命令
EMRS 块地址必须被设置
(5)在 direct_cmd,以‘ 2’b10 ’执行 mem_cmd,使得 DRAM 控制器产生‘MRS’存储器命令
MRS 块地址必须被设置
(6)在 direct_cmd,以‘ 2’b11 ’执行 mem_cmd,使得 DRAM 控制器产生‘Autorefresh’存储器命令
(7)在 direct_cmd,以‘ 2’b11 ’执行 mem_cmd,使得 DRAM 控制器产生‘Autorefresh’存储器命令
(8)在 direct_cmd,以‘ 2’b11 ’执行 mem_cmd,使得 DRAM 控制器产生‘Prechargeall’存储器命令

具体代码如下:

  1 //Tiny6410Addr.h
  2 #ifndef _Tiny6410Addr_H
  3 #define _Tiny6410Addr_H
  4 //GPK
  5 #define GPKIO_BASE (0x7F008800)
  6 #define rGPKCON0 (*((volatile unsigned long *)(GPKIO_BASE+0x00)))
  7 #define rGPKDAT  (*((volatile unsigned long *)(GPKIO_BASE+0x08)))
  8
  9 //CLOCK
 10 #define APLL_LOCK (*((volatile unsigned long *)0x7E00F000))
 11 #define MPLL_LOCK (*((volatile unsigned long *)0x7E00F004))
 12 #define EPLL_LOCK (*((volatile unsigned long *)0x7E00F008))
 13 #define OTHERS    (*((volatile unsigned long *)0x7e00f900))
 14 #define CLK_DIV0  (*((volatile unsigned long *)0x7E00F020))
 15 #define APLL_CON  (*((volatile unsigned long *)0x7E00F00C))
 16 #define MPLL_CON  (*((volatile unsigned long *)0x7E00F010))
 17 #define CLK_SRC   (*((volatile unsigned long *)0x7E00F01C))
 18
 19
 20
 21 //GPA /uart
 22 #define ULCON0     (*((volatile unsigned long *)0x7F005000))
 23 #define UCON0      (*((volatile unsigned long *)0x7F005004))
 24 #define UFCON0     (*((volatile unsigned long *)0x7F005008))
 25 #define UMCON0     (*((volatile unsigned long *)0x7F00500C))
 26 #define UTRSTAT0   (*((volatile unsigned long *)0x7F005010))
 27 #define UFSTAT0    (*((volatile unsigned long *)0x7F005018))
 28 #define UTXH0      (*((volatile unsigned char *)0x7F005020))
 29 #define URXH0      (*((volatile unsigned char *)0x7F005024))
 30 #define UBRDIV0    (*((volatile unsigned short *)0x7F005028))
 31 #define UDIVSLOT0  (*((volatile unsigned short *)0x7F00502C))
 32 #define GPACON     (*((volatile unsigned long *)0x7F008000))
 33
 34
 35 //SDRAM
 36 #define P1MEMCCMD    (*((volatile unsigned long *)0x7e001004))
 37 #define P1REFRESH    (*((volatile unsigned long *)0x7e001010))
 38 #define P1CASLAT    (*((volatile unsigned long *)0x7e001014))
 39
 40 #define MEM_SYS_CFG    (*((volatile unsigned long *)0x7e00f120))
 41 #define P1MEMCFG    (*((volatile unsigned long *)0x7e00100c))
 42 #define P1T_DQSS    (*((volatile unsigned long *)0x7e001018))
 43 #define P1T_MRD        (*((volatile unsigned long *)0x7e00101c))
 44 #define P1T_RAS        (*((volatile unsigned long *)0x7e001020))
 45 #define P1T_RC        (*((volatile unsigned long *)0x7e001024))
 46 #define P1T_RCD        (*((volatile unsigned long *)0x7e001028))
 47 #define P1T_RFC        (*((volatile unsigned long *)0x7e00102c))
 48 #define P1T_RP        (*((volatile unsigned long *)0x7e001030))
 49 #define P1T_RRD        (*((volatile unsigned long *)0x7e001034))
 50 #define P1T_WR        (*((volatile unsigned long *)0x7e001038))
 51 #define P1T_WTR        (*((volatile unsigned long *)0x7e00103c))
 52 #define P1T_XP        (*((volatile unsigned long *)0x7e001040))
 53 #define P1T_XSR        (*((volatile unsigned long *)0x7e001044))
 54 #define P1T_ESR        (*((volatile unsigned long *)0x7e001048))
 55 #define P1MEMCFG2    (*((volatile unsigned long *)0X7e00104c))
 56 #define P1_chip_0_cfg    (*((volatile unsigned long *)0x7e001200))
 57
 58 #define P1MEMSTAT    (*((volatile unsigned long *)0x7e001000))
 59
 60 #define P1DIRECTCMD    (*((volatile unsigned long *)0x7e001008))
 61
 62 #endif
 63
 64 //start.S
 65 // 启动代码
 66 .global _start
 67
 68 _start:
 69
 70     // 把外设的基地址告诉CPU
 71     ldr r0, =0x70000000
 72     orr r0, r0, #0x13
 73     mcr p15,0,r0,c15,c2,4
 74
 75     // 关看门狗
 76     ldr r0, =0x7E004000
 77     mov r1, #0
 78     str r1, [r0]
 79
 80     // 设置栈
 81     ldr sp, =8*1024
 82
 83     // 开启icaches
 84 #ifdef  CONFIG_SYS_ICACHE_OFF
 85     bic r0, r0, #0x00001000                 @ clear bit 12 (I) I-cache
 86 #else
 87     orr r0, r0, #0x00001000                 @ set bit 12 (I) I-cache
 88 #endif
 89     mcr p15, 0, r0, c1, c0, 0
 90
 91     // 设置时钟
 92     bl clock_init
 93
 94     // 初始化sdram
 95     bl sdram_init
 96
 97     // 重定位
 98     adr r0, _start
 99     ldr r1, =_start
100     ldr r2, =bss_start
101     cmp r0, r1
102     beq clean_bss
103 copy_loop:
104     ldr r3, [r0], #4
105     str r3, [r1], #4
106     cmp r1, r2
107     bne copy_loop
108
109     // 清BSS段
110 clean_bss:
111     ldr r0, =bss_start
112     ldr r1, =bss_end
113     mov r3, #0
114     cmp r0, r1
115     beq on_ddr
116 clean_loop:
117     str r3, [r0], #4
118     cmp r0, r1
119     bne clean_loop
120
121
122     // 调用main函数
123 on_ddr:
124     ldr pc, =main
125 halt:
126     b halt
127 //clock.c
128 #include "Tiny6410Addr.h"
129 // 功能:c语言初始化时钟
130
131
132 #define ARM_RATIO    0                           // ARMCLK     = DOUTAPLL / (ARM_RATIO + 1)      = 532/(0+1) = 532  MHz
133 #define MPLL_RATIO   0                           // DOUTMPLL = MOUTMPLL / (MPLL_RATIO + 1)   = 532/(0+1) = 532  MHz
134 #define HCLKX2_RATIO 1                           // HCLKX2     = HCLKX2IN / (HCLKX2_RATIO + 1) = 532/(1+1) = 266  MHz
135 #define HCLK_RATIO   1                           // HCLK     = HCLKX2   / (HCLK_RATIO + 1)   = 266/(1+1) = 133  MHz
136 #define PCLK_RATIO   3                           // PCLK       = HCLKX2   / (PCLK_RATIO + 1)   = 266/(3+1) = 66.5 MHz
137
138
139
140 #define APLL_CON_VAL  ((1<<31) | (266 << 16) | (3 << 8) | (1))
141
142
143 #define MPLL_CON_VAL  ((1<<31) | (266 << 16) | (3 << 8) | (1))
144
145
146
147 void clock_init(void)
148 {
149     /* 1. 设置各PLL的LOCK_TIME,使用默认值 */
150     APLL_LOCK = 0xffff;                            // APLL_LOCK,供cpu使用
151     MPLL_LOCK = 0xffff;                            // MPLL_LOCK,供AHB(存储/中断/lcd等控制器)/APB(看门狗,定时器,SD等)总线上的设备使用
152     EPLL_LOCK = 0xffff;                            // EPLL_LOCK,供UART,IIS,IIC使用
153
154     /* 2. 设置为异步模式(Asynchronous mode) */
155     OTHERS &= ~0xc0;                            //《linux installation for u-boot》3.7中:用MPLL作为HCLK和PCLK的Source是异步(ASYNC)模式,用APLL是同步(SYNC)模式
156     while ((OTHERS & 0xf00) != 0);
157
158     /* 3. 设置分频系数 */
159     CLK_DIV0 = (ARM_RATIO) | (MPLL_RATIO << 4) | (HCLK_RATIO << 8) | (HCLKX2_RATIO << 9) | (PCLK_RATIO << 12);
160
161     /* 4. 设置PLL,放大时钟 */
162     APLL_CON = APLL_CON_VAL;
163     MPLL_CON = MPLL_CON_VAL;
164
165     /* 5. 选择PLL的输出作为时钟源 */
166     CLK_SRC = 0x03;
167 }
168
169 //sdram.c
170 #include "Tiny6410Addr.h"
171
172 #define set_zero( addr, bit ) ( addr &= ( ~ ( 1 << (bit) ) ) )
173 #define set_one( addr, bit ) ( addr |= ( 1 << ( bit ) ) )
174
175 #define set_bit( addr, bit, val ) ( addr = (addr &=(~(1<<(bit))) ) | ( (val)<<(bit) ) )
176
177 #define set_2bit( addr, bit, val ) ( addr = (addr &(~(3<<(bit))) ) | ( (val)<<(bit) ) )
178
179 #define set_nbit( addr, bit, len,  val ) \
180     ( (addr) = (((addr)&(~(( ((1<<(len))-1) )<<(bit))))  | ( (val)<<(bit) ) ))
181
182 #define get_bit( addr, bit ) ( ((addr ) & ( 1 << (bit) )) > 0  )
183
184 #define get_val( addr, val ) ( (val) = addr )
185 #define read_val( addr ) addr
186 #define set_val( addr, val ) ( addr = (val) )
187 #define or_val( addr, val ) ( addr |= (val) )
188
189
190 #define HCLK    133000000
191
192 #define nstoclk(ns)    ( ns/(1000000000/HCLK)+1 )
193 ///
194
195 typedef unsigned char u8;
196 typedef unsigned short u16;
197 typedef unsigned int u32;
198
199 // function declare
200
201 int delay( int );
202
203 /* 根据6410手册P192页相关步骤和sdram手册来初始化dram控制器(dramc) */
204 int sdram_init( void )
205 {
206     /* 1. 使dramc进入"config"状态 */
207     set_val(P1MEMCCMD, 0x4);
208
209     /* 2. 设置timing parameter, chip configuration,id configuration registers */
210     /* 2.1 刷新周期 */
211     set_val(P1REFRESH, nstoclk(7800));                    //刷新周期:(7.8us)/((1/HCLK)s)=(7.8*10^3)/(1/133*10^6)
212     /* 2.2 时间参数,下列设置全都是取了最小值 */
213     set_val( P1CASLAT, ( 3 << 1 ) );                      //CAS Latency:指的是内存存取数据所需的延迟时间,简单的说,就是内存接到CPU的指令后的反应速度。一般的参数值是2和3两种。K4X1G163PQ的芯片手册上CAS Latency=3
214     set_val( P1T_DQSS, 0x1 );                            //下列设置均在sdram手册中可查询到
215     set_val( P1T_MRD, 0x2 );
216     set_val( P1T_RAS, nstoclk(42) );
217     set_val( P1T_RC, nstoclk(60) );
218     u32 trcd = nstoclk( 18 );
219     set_val( P1T_RCD, trcd | (( trcd - 3 ) << 3 ) );
220     u32 trfc = nstoclk( 72 );
221     set_val( P1T_RFC, trfc | ( ( trfc-3 ) << 5 ) );
222     u32 trp = nstoclk( 18 );
223     set_val( P1T_RP, trp | ( ( trp - 3 ) << 3 ) );
224     set_val( P1T_RRD, nstoclk(12) );
225     set_val( P1T_WR, nstoclk(12) );
226
227     set_val( P1T_WTR, 0x1 );
228     set_val( P1T_XP, 0x1 );
229     set_val( P1T_XSR, nstoclk(120) );
230     set_val( P1T_ESR, nstoclk(120) );
231
232     /* 2.3 chip configuration */
233     set_nbit( P1MEMCFG, 0, 3, 0x2 );                      // column address(10):A0~A9
234     set_nbit( P1MEMCFG, 3, 3, 0x3 );                      // row address(14):A0~A13
235     set_zero( P1MEMCFG, 6 );                              // A10/AP
236     set_nbit( P1MEMCFG, 15, 3, 0x2 );                     //  Burst Length (2, 4, 8, 16)
237     set_nbit( P1MEMCFG2, 0, 4, 0x5 );
238     set_2bit( P1MEMCFG2, 6, 0x1 );                        // 32 bit
239     set_nbit( P1MEMCFG2, 8, 3, 0x3 );                    // Mobile DDR SDRAM
240     set_2bit( P1MEMCFG2, 11, 0x1 );
241     set_one( P1_chip_0_cfg, 16 );                        // Bank-Row-Column organization
242
243     /* 3. 初始化sdram */
244     set_val( P1DIRECTCMD, 0xc0000 );                     // NOP
245     set_val( P1DIRECTCMD, 0x000 );                        // precharge
246     set_val( P1DIRECTCMD, 0x40000 );                    // auto refresh
247     set_val( P1DIRECTCMD, 0x40000 );                    // auto refresh
248     set_val( P1DIRECTCMD, 0xa0000 );                     // EMRS
249     set_val( P1DIRECTCMD, 0x80032 );                     // MRS
250
251     set_val( MEM_SYS_CFG, 0x0 );
252
253     /* 4. 使dramc进入"ready"状态    */
254     set_val( P1MEMCCMD, 0x000 );
255     while( !(( read_val( P1MEMSTAT ) & 0x3 ) == 0x1));// 等待dramc进入"ready"状态
256 }
257 //main.c
258
259 #include "Tiny6410Addr.h"
260 #define GPK4_OUT  (1<<4*4)
261 #define GPK5_OUT  (1<<4*5)
262 #define GPK6_OUT  (1<<4*6)
263 #define GPK7_OUT  (1<<4*7)
264 //延时函数
265 void delay()
266 {
267    volatile int i = 0x10000;
268    while (i--);
269 }
270
271 int main()
272 {
273     unsigned int i = 0x10;
274     //将GPK4-7设置为输出
275     rGPKCON0 = GPK4_OUT | GPK5_OUT |GPK6_OUT |GPK7_OUT;
276     //跑马灯式
277     while (1)
278     {
279         rGPKDAT = 0x00;
280         delay();
281         rGPKDAT = 0xF0;
282
283     }
284
285     return 0;
286     }
287
288 //ddr.lds
289 SECTIONS
290 {
291     . = 0x50000000;
292     .text :
293     {
294         start.o
295         * (.text)
296     }
297
298     . = ALIGN(4);
299     .rodata :
300     {
301         * (.rodata)
302     }
303
304     . = ALIGN(4);
305     .data :
306     {
307     * (.data)
308     }
309
310     . = ALIGN(4);
311
312     bss_start = . ;
313
314     .bss :
315       {
316     * (.bss)
317     * (.common)
318       }
319
320     bss_end = . ;
321 }

View Code

转载于:https://www.cnblogs.com/chenshikun/p/5840200.html

Tiny6410之重定位代码到SDRAM相关推荐

  1. Tiny6410之重定位代码到SRAM+4096

    重定位代码 两个不同的地址概念: 对于程序而言,需要理解两个地址,一个是程序当前所处的地址,即程序运行时所处的当前地址.二是程序应该位于的运行地址,即编译程序时所指定的程序的链接地址.在Tiny641 ...

  2. uboot重定位代码分析(转)

    概述 重定位(relocate)代码将BootLoader自身由Flash复制到SDRAM,以便跳转到SDRAM执行.之所以需要进行重定位是因为在Flash中执行速度比较慢,而系统复位后总是从0x00 ...

  3. tiny4412 裸机程序 七、重定位代码到DRAM【转】

    本文转载自:http://blog.csdn.net/eshing/article/details/37116637 一.关于DRAM 上一章我们讲解了如何对代码进行重定位,但是将代码重定位到只有25 ...

  4. uboot为什么要重定位/代码拷贝?

    参考自:https://www.cnblogs.com/Cqlismy/p/12152400.html 必看.这个老哥写的uboot启动的博客非常棒,感谢. 还有https://blog.csdn.n ...

  5. tiny4412 裸机程序 六、重定位代码到IRAM+0x8000【转】

    本文转载自:http://blog.csdn.net/eshing/article/details/37115697 一.重定向 对于程序而言,我们需要理解两个概念,一是程序当前所处的地址,即程序在运 ...

  6. tiny4412 裸机程序 六、重定位代码到IRAM+0x8000

    一.重定向 对于程序而言,我们需要理解两个概念,一是程序当前所处的地址,即程序在运行时,所处的当前地址:二是程序的链接地址,即程序运行时应该位于的运行地址.编译程序时,可以指定程序的链接地址.对于Ti ...

  7. 重定位代码Repair

    此类指令都为6个字节 大致试验结果如下: 第一个字节跟操作类型相关,第二个字节跟寄存器相关,后面四个字节为地址 第二个字节高四位必须为8,9,A,B四个中的一个,低四位必为5和D中的一个,产生8种排列 ...

  8. 《5.SDRAM和重定位relocate》

    转自 https://edu.csdn.net/lecturer/505 朱老师物联网大讲堂 <5.SDRAM和重定位relocate> 第一部分.章节目录 1.5.1.汇编写启动代码之关 ...

  9. 第四天:关看门狗、设置栈、控制icache、重定位、链接脚本

    1.汇编写启动代码:关看门狗 什么是看门狗? 看门狗(watch dog timer看门狗定时器),比如:家门口有一只狗,这个狗定时会饿(譬如两小时一饿),狗饿了就会胡乱咬人,人进进出出要想保证安全必 ...

最新文章

  1. 3D视觉从入门到进阶学习路线
  2. LPC43xx双核笔记
  3. 亿级Web系统搭建――单机到分布式集群 转载
  4. RABBITMQ 管理指南(添加虚拟HOST)
  5. springboot 中根据数据库表生成所有表的model,mapper和xml文件
  6. 百度网盘7.3.1.10版本增加工作空间功能,可实现百度网盘与电脑文件夹同步
  7. flask sqlalchemy 单表查询
  8. python编辑器_自学python第一课之下载安装编辑器
  9. php易错,PHP学习1:几种常见数据类型及其易错点
  10. Sprin boot 加载位置顺序
  11. PCoIP卡由火炮升级为喀秋莎
  12. DHCP server 冒充及DOS攻击处理方案
  13. 重磅!清华大学网上课程面向全国免费开放!无需登录、注册!在家上清华!...
  14. 【iOS篇】在iPhone上安装描述文件
  15. 小程序上传图片前将图片剪切成固定尺寸
  16. java网页作业提交_基于JAVA网上作业提交批改系统的设计(SQL)(含录像)
  17. OpenCV基础入门【C++及python语言】
  18. Linux文件名包含小括号处理
  19. 诺贝尔物理学奖揭晓:LED灯将点亮整个21世纪
  20. python 批量打开网页并截图_Python自动截图html页面

热门文章

  1. Linux如何在线修改hostname
  2. Noip 2016 愤怒的小鸟 题解
  3. 某大型企业私有云建设思路解析
  4. 收集的安全网站【公司】
  5. CSS3 display:flex和display:box有什么区别?
  6. MSP430G2553需要注意的一些参数
  7. XenDesktop 5.6 PVS6.1测试中出现的一例错误:Management Interface:Remote request failed
  8. 我的20天项目经历--至今令我难忘的技术难题
  9. MongoDb 中 serverStatus was very slow 的原因分析
  10. DAO(Data Access Object ,数据访问对象)设计模式