在上一章中,将代码重定位到了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’存储器命令

具体代码如下:

 //Tiny6410Addr.h
#ifndef _Tiny6410Addr_H
#define _Tiny6410Addr_H
//GPK
#define GPKIO_BASE (0x7F008800)
#define rGPKCON0 (*((volatile unsigned long *)(GPKIO_BASE+0x00)))
#define rGPKDAT (*((volatile unsigned long *)(GPKIO_BASE+0x08))) //CLOCK
#define APLL_LOCK (*((volatile unsigned long *)0x7E00F000))
#define MPLL_LOCK (*((volatile unsigned long *)0x7E00F004))
#define EPLL_LOCK (*((volatile unsigned long *)0x7E00F008))
#define OTHERS (*((volatile unsigned long *)0x7e00f900))
#define CLK_DIV0 (*((volatile unsigned long *)0x7E00F020))
#define APLL_CON (*((volatile unsigned long *)0x7E00F00C))
#define MPLL_CON (*((volatile unsigned long *)0x7E00F010))
#define CLK_SRC (*((volatile unsigned long *)0x7E00F01C)) //GPA /uart
#define ULCON0 (*((volatile unsigned long *)0x7F005000))
#define UCON0 (*((volatile unsigned long *)0x7F005004))
#define UFCON0 (*((volatile unsigned long *)0x7F005008))
#define UMCON0 (*((volatile unsigned long *)0x7F00500C))
#define UTRSTAT0 (*((volatile unsigned long *)0x7F005010))
#define UFSTAT0 (*((volatile unsigned long *)0x7F005018))
#define UTXH0 (*((volatile unsigned char *)0x7F005020))
#define URXH0 (*((volatile unsigned char *)0x7F005024))
#define UBRDIV0 (*((volatile unsigned short *)0x7F005028))
#define UDIVSLOT0 (*((volatile unsigned short *)0x7F00502C))
#define GPACON (*((volatile unsigned long *)0x7F008000)) //SDRAM
#define P1MEMCCMD (*((volatile unsigned long *)0x7e001004))
#define P1REFRESH (*((volatile unsigned long *)0x7e001010))
#define P1CASLAT (*((volatile unsigned long *)0x7e001014)) #define MEM_SYS_CFG (*((volatile unsigned long *)0x7e00f120))
#define P1MEMCFG (*((volatile unsigned long *)0x7e00100c))
#define P1T_DQSS (*((volatile unsigned long *)0x7e001018))
#define P1T_MRD (*((volatile unsigned long *)0x7e00101c))
#define P1T_RAS (*((volatile unsigned long *)0x7e001020))
#define P1T_RC (*((volatile unsigned long *)0x7e001024))
#define P1T_RCD (*((volatile unsigned long *)0x7e001028))
#define P1T_RFC (*((volatile unsigned long *)0x7e00102c))
#define P1T_RP (*((volatile unsigned long *)0x7e001030))
#define P1T_RRD (*((volatile unsigned long *)0x7e001034))
#define P1T_WR (*((volatile unsigned long *)0x7e001038))
#define P1T_WTR (*((volatile unsigned long *)0x7e00103c))
#define P1T_XP (*((volatile unsigned long *)0x7e001040))
#define P1T_XSR (*((volatile unsigned long *)0x7e001044))
#define P1T_ESR (*((volatile unsigned long *)0x7e001048))
#define P1MEMCFG2 (*((volatile unsigned long *)0X7e00104c))
#define P1_chip_0_cfg (*((volatile unsigned long *)0x7e001200)) #define P1MEMSTAT (*((volatile unsigned long *)0x7e001000)) #define P1DIRECTCMD (*((volatile unsigned long *)0x7e001008)) #endif //start.S
// 启动代码
.global _start _start: // 把外设的基地址告诉CPU
ldr r0, =0x70000000
orr r0, r0, #0x13
mcr p15,,r0,c15,c2, // 关看门狗
ldr r0, =0x7E004000
mov r1, #
str r1, [r0] // 设置栈
ldr sp, =* // 开启icaches
#ifdef CONFIG_SYS_ICACHE_OFF
bic r0, r0, #0x00001000 @ clear bit (I) I-cache
#else
orr r0, r0, #0x00001000 @ set bit (I) I-cache
#endif
mcr p15, , r0, c1, c0, // 设置时钟
bl clock_init // 初始化sdram
bl sdram_init // 重定位
adr r0, _start
ldr r1, =_start
ldr r2, =bss_start
cmp r0, r1
beq clean_bss
copy_loop:
ldr r3, [r0], #
str r3, [r1], #
cmp r1, r2
bne copy_loop // 清BSS段
clean_bss:
ldr r0, =bss_start
ldr r1, =bss_end
mov r3, #
cmp r0, r1
beq on_ddr
clean_loop:
str r3, [r0], #
cmp r0, r1
bne clean_loop // 调用main函数
on_ddr:
ldr pc, =main
halt:
b halt
//clock.c
#include "Tiny6410Addr.h"
// 功能:c语言初始化时钟 #define ARM_RATIO 0 // ARMCLK = DOUTAPLL / (ARM_RATIO + 1) = 532/(0+1) = 532 MHz
#define MPLL_RATIO 0 // DOUTMPLL = MOUTMPLL / (MPLL_RATIO + 1) = 532/(0+1) = 532 MHz
#define HCLKX2_RATIO 1 // HCLKX2 = HCLKX2IN / (HCLKX2_RATIO + 1) = 532/(1+1) = 266 MHz
#define HCLK_RATIO 1 // HCLK = HCLKX2 / (HCLK_RATIO + 1) = 266/(1+1) = 133 MHz
#define PCLK_RATIO 3 // PCLK = HCLKX2 / (PCLK_RATIO + 1) = 266/(3+1) = 66.5 MHz #define APLL_CON_VAL ((1<<31) | (266 << 16) | (3 << 8) | (1)) #define MPLL_CON_VAL ((1<<31) | (266 << 16) | (3 << 8) | (1)) void clock_init(void)
{
/* 1. 设置各PLL的LOCK_TIME,使用默认值 */
APLL_LOCK = 0xffff; // APLL_LOCK,供cpu使用
MPLL_LOCK = 0xffff; // MPLL_LOCK,供AHB(存储/中断/lcd等控制器)/APB(看门狗,定时器,SD等)总线上的设备使用
EPLL_LOCK = 0xffff; // EPLL_LOCK,供UART,IIS,IIC使用 /* 2. 设置为异步模式(Asynchronous mode) */
OTHERS &= ~0xc0; //《linux installation for u-boot》3.7中:用MPLL作为HCLK和PCLK的Source是异步(ASYNC)模式,用APLL是同步(SYNC)模式
while ((OTHERS & 0xf00) != ); /* 3. 设置分频系数 */
CLK_DIV0 = (ARM_RATIO) | (MPLL_RATIO << ) | (HCLK_RATIO << ) | (HCLKX2_RATIO << ) | (PCLK_RATIO << ); /* 4. 设置PLL,放大时钟 */
APLL_CON = APLL_CON_VAL;
MPLL_CON = MPLL_CON_VAL; /* 5. 选择PLL的输出作为时钟源 */
CLK_SRC = 0x03;
} //sdram.c
#include "Tiny6410Addr.h" #define set_zero( addr, bit ) ( addr &= ( ~ ( 1 << (bit) ) ) )
#define set_one( addr, bit ) ( addr |= ( 1 << ( bit ) ) ) #define set_bit( addr, bit, val ) ( addr = (addr &=(~(1<<(bit))) ) | ( (val)<<(bit) ) ) #define set_2bit( addr, bit, val ) ( addr = (addr &(~(3<<(bit))) ) | ( (val)<<(bit) ) ) #define set_nbit( addr, bit, len, val ) \
( (addr) = (((addr)&(~(( ((<<(len))-) )<<(bit)))) | ( (val)<<(bit) ) )) #define get_bit( addr, bit ) ( ((addr ) & ( 1 << (bit) )) > 0 ) #define get_val( addr, val ) ( (val) = addr )
#define read_val( addr ) addr
#define set_val( addr, val ) ( addr = (val) )
#define or_val( addr, val ) ( addr |= (val) ) #define HCLK 133000000 #define nstoclk(ns) ( ns/(1000000000/HCLK)+1 )
/////////////////////////////// typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32; // function declare int delay( int ); /* 根据6410手册P192页相关步骤和sdram手册来初始化dram控制器(dramc) */
int sdram_init( void )
{
/* 1. 使dramc进入"config"状态 */
set_val(P1MEMCCMD, 0x4); /* 2. 设置timing parameter, chip configuration,id configuration registers */
/* 2.1 刷新周期 */
set_val(P1REFRESH, nstoclk()); //刷新周期:(7.8us)/((1/HCLK)s)=(7.8*10^3)/(1/133*10^6)
/* 2.2 时间参数,下列设置全都是取了最小值 */
set_val( P1CASLAT, ( << ) ); //CAS Latency:指的是内存存取数据所需的延迟时间,简单的说,就是内存接到CPU的指令后的反应速度。一般的参数值是2和3两种。K4X1G163PQ的芯片手册上CAS Latency=3
set_val( P1T_DQSS, 0x1 ); //下列设置均在sdram手册中可查询到
set_val( P1T_MRD, 0x2 );
set_val( P1T_RAS, nstoclk() );
set_val( P1T_RC, nstoclk() );
u32 trcd = nstoclk( );
set_val( P1T_RCD, trcd | (( trcd - ) << ) );
u32 trfc = nstoclk( );
set_val( P1T_RFC, trfc | ( ( trfc- ) << ) );
u32 trp = nstoclk( );
set_val( P1T_RP, trp | ( ( trp - ) << ) );
set_val( P1T_RRD, nstoclk() );
set_val( P1T_WR, nstoclk() ); set_val( P1T_WTR, 0x1 );
set_val( P1T_XP, 0x1 );
set_val( P1T_XSR, nstoclk() );
set_val( P1T_ESR, nstoclk() ); /* 2.3 chip configuration */
set_nbit( P1MEMCFG, , , 0x2 ); // column address(10):A0~A9
set_nbit( P1MEMCFG, , , 0x3 ); // row address(14):A0~A13
set_zero( P1MEMCFG, ); // A10/AP
set_nbit( P1MEMCFG, , , 0x2 ); // Burst Length (2, 4, 8, 16)
set_nbit( P1MEMCFG2, , , 0x5 );
set_2bit( P1MEMCFG2, , 0x1 ); // 32 bit
set_nbit( P1MEMCFG2, , , 0x3 ); // Mobile DDR SDRAM
set_2bit( P1MEMCFG2, , 0x1 );
set_one( P1_chip_0_cfg, ); // Bank-Row-Column organization /* 3. 初始化sdram */
set_val( P1DIRECTCMD, 0xc0000 ); // NOP
set_val( P1DIRECTCMD, 0x000 ); // precharge
set_val( P1DIRECTCMD, 0x40000 ); // auto refresh
set_val( P1DIRECTCMD, 0x40000 ); // auto refresh
set_val( P1DIRECTCMD, 0xa0000 ); // EMRS
set_val( P1DIRECTCMD, 0x80032 ); // MRS set_val( MEM_SYS_CFG, 0x0 ); /* 4. 使dramc进入"ready"状态 */
set_val( P1MEMCCMD, 0x000 );
while( !(( read_val( P1MEMSTAT ) & 0x3 ) == 0x1));// 等待dramc进入"ready"状态
}
//main.c #include "Tiny6410Addr.h"
#define GPK4_OUT (1<<4*4)
#define GPK5_OUT (1<<4*5)
#define GPK6_OUT (1<<4*6)
#define GPK7_OUT (1<<4*7)
//延时函数
void delay()
{
volatile int i = 0x10000;
while (i--);
} int main()
{
unsigned int i = 0x10;
//将GPK4-7设置为输出
rGPKCON0 = GPK4_OUT | GPK5_OUT |GPK6_OUT |GPK7_OUT;
//跑马灯式
while ()
{
rGPKDAT = 0x00;
delay();
rGPKDAT = 0xF0; } return ;
} //ddr.lds
SECTIONS
{
. = 0x50000000;
.text :
{
start.o
* (.text)
} . = ALIGN();
.rodata :
{
* (.rodata)
} . = ALIGN();
.data :
{
* (.data)
} . = ALIGN(); bss_start = . ; .bss :
{
* (.bss)
* (.common)
} bss_end = . ;
}

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. tiny4412 裸机程序 六、重定位代码到IRAM+0x8000【转】

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

  5. s3c2440裸机-代码重定位(1.重定位的引入,为什么要代码重定位)

    1.重定位的引入(为什么要代码重定位) 我们知道s3c2440的cpu从0地址开始取指令执行,当从nor启动时,0地址对应nor,nor可以像内存一样读,但不能像内存一样写.我们能够从nor上取指令执 ...

  6. s3c6410_uboot中的代码重定位(nand->sdram)

    本文仅探讨s3c6410从nand flash启动u-boot时的代码重定位过程 参考: 1)<USER'S MANUAL-S3C6410X>第二章 MEMORY MAP 第八章 NAND ...

  7. u-boot移植(四)---修改前工作:代码流程分析3---代码重定位

    一.重定位 1.以前版本的重定位 2.新版本 我们的程序不只涉及一个变量和函数,我们若想访问程序里面的地址,则必须使用SDRAM处的新地址,即我们的程序里面的变量和函数必须修改地址.我们要修改地址,则 ...

  8. s3c2440裸机-代码重定位、清bss的改进和位置无关码

    1.代码重定位的改进 用ldr.str代替ldrb, strb加快代码重定位的速度. 前面重定位时,我们使用的是ldrb命令从的Nor Flash读取1字节数据,再用strb命令将1字节数据写到SDR ...

  9. s3c2440裸机-代码重定位(2.编程实现代码重定位)

    代码重定位(2.编程实现代码重定位) 1.引入链接脚本 我们上一节讲述了为什么要重定位代码,那么怎么去重定位代码呢? 上一节我们发现"arm-linux-ld -Ttext 0 -Tdata ...

随机推荐

  1. swfupload多文件上传[附源码]

    swfupload多文件上传[附源码] 文件上传这东西说到底有时候很痛,原来的asp.net服务器控件提供了很简单的上传,但是有回传,还没有进度条提示.这次我们演示利用swfupload多文件上传,项 ...

  2. Linux网络编程(五)

    /*Linux网络编程(五)——多路IO复用之select() 网络编程中,使用IO复用的典型场合: 1.当客户处理多个描述字时(交互式输入以及网络接口),必须使用IO复用. 2.一个客户同时处理多个 ...

  3. Oracle误删恢复

    query deleted datarows: select * from 表名 as of timestamp to_timestamp('删除时间点','yyyy-mm-dd hh24:mi:ss ...

  4. 序列化json对象,通过ajax传入asp.net mvc后台

    序列化json对象,通过ajax传入asp.net mvc后台 序列化json对象,通过ajax传入asp.net mvc后台   今天遇到一个问题,准备把组织好的json对象通过jquery.aja ...

  5. Ogre源码编译教程

    最近突然发现Ogre引擎更新到2.1版本了,既然依旧是代码开源,本着学习的精神就下载下来弄弄.但是官网提供的SDK版本只有1.9的,考虑到学习的便利性,因此最好从Source版本开始弄,这样的话以后想 ...

  6. WCFRESTFul服务搭建及实现增删改查

    WCFRESTFul服务搭建及实现增删改查 RESTful Wcf是一种基于Http协议的服务架构风格,  RESTful 的服务通常是架构层面上的考虑. 因为它天生就具有很好的跨平台跨语言的集成能力 ...

  7. boost解析XML方法教程

    boost库在解析XML时具有良好的性能,可操作性也很强下地址有个简单的说明 http://blog.csdn.net/luopeiyuan1990/article/details/9445691 一 ...

  8. Liferay的架构:缓存(第一部分)

    这次,我将要涉及到一个非常重要的概念:缓存.在当今的web应用中,如果没有设计一个比较好的缓存系统,在web中就不可能有一个良好的性能.所以我将要 提到的缓存不仅仅能够更好地理解Liferay架构,而 ...

  9. [C++STDlib基础]关于单字符的操作——C++标准库头文件<cctype>

    网上实例 总结 /* _STD_BEGIN using _CSTD isalnum; using _CSTD isalpha; using _CSTD iscntrl; using _CSTD isd ...

  10. JVM参数设置、分析

    不管是YGC还是Full GC,GC过程中都会对导致程序运行中中断,正确的选择不同的GC策略,调整JVM.GC的参数,可以极大的减少由于GC工作,而导致的程序运行中断方面的问题,进而适当的提高Java ...