/****************DDR的设置**************/
#include "common.h"
#define MEMCCMD 0x7e001004
#define P1REFRESH 0x7e001010
#define P1CASLAT 0x7e001014
#define MEM_SYS_CFG 0x7e00f120
#define P1MEMCFG 0x7e00100c
#define P1T_DQSS 0x7e001018
#define P1T_MRD 0x7e00101c
#define P1T_RAS 0x7e001020
#define P1T_RC 0x7e001024
#define P1T_RCD 0x7e001028
#define P1T_RFC 0x7e00102c
#define P1T_RP 0x7e001030
#define P1T_RRD 0x7e001034
#define P1T_WR 0x7e001038
#define P1T_WTR 0x7e00103c
#define P1T_XP 0x7e001040
#define P1T_XSR 0x7e001044
#define P1T_ESR 0x7e001048
#define P1MEMCFG2 0X7e00104c
#define P1_chip_0_cfg 0x7e001200
#define P1MEMSTAT 0x7e001000
#define P1MEMCCMD 0x7e001004
#define P1DIRECTCMD 0x7e001008
#define HCLK 133000000
#define nstoclk(ns) (ns/( 1000000000/HCLK)+1)
/*******************操作说明********************/
/***************设置动态内存控制器*****************/
int sdram_init( void ) //c语言可以写位置无关码,不能使用全局变量和静态变量
{
// tell dramc to configure
set_val( MEMCCMD, 0x4 ); //0x4=100;
//set_val定义
//将vi设置成unsigned int* 指针类型,前面加*表示指针操作
// set refresh period
set_val( P1REFRESH, nstoclk(7800) ); // ns->clock
/************刷新周期(DDR芯片手册)************/
//"+1"是四舍五入
// set timing para
set_val( P1CASLAT, ( 3 << 1 ) );
//延迟2或者3
set_val( P1T_DQSS, 0x1 ); // 0.75 - 1.25
set_val( P1T_MRD, 0x2 );
set_val( P1T_RAS, nstoclk(45) );
/***************RAS激活时间(DDR芯片手册)*************/
set_val( P1T_RC, nstoclk(68) );
u32 trcd = nstoclk( 23 );
set_val( P1T_RCD, trcd | (( trcd - 3 ) << 3 ) );
u32 trfc = nstoclk( 80 );
set_val( P1T_RFC, trfc | ( ( trfc-3 ) << 5 ) );
u32 trp = nstoclk( 23 );
set_val( P1T_RP, trp | ( ( trp - 3 ) << 3 ) );
set_val( P1T_RRD, nstoclk(15) );
set_val( P1T_WR, nstoclk(15) );
set_val( P1T_WTR, 0x7 );
set_val( P1T_XP, 0x2 );
set_val( P1T_XSR, nstoclk(120) );
set_val( P1T_ESR, nstoclk(120) );
// set mem cfg
set_nbit( P1MEMCFG, 0, 3, 0x2 ); /* 10 column address *///列地址长度为10位
/* set_nbit: 把从第bit位开始的一共len位消零,然后把这几位设为val */
/* set_nbit: 把从第bit位开始的一共len位消零,然后把这几位设为val */
set_nbit( P1MEMCFG, 3, 3, 0x2 ); /* 13 row address */
/***********行,列,bank,设置完后***********/
set_zero( P1MEMCFG, 6 ); /* A10/AP */
set_nbit( P1MEMCFG, 15, 3, 0x2 ); /* Burst 4 *///突发传输长度
/*设置位宽*/
set_nbit( P1MEMCFG2, 0, 4, 0x5 );
set_2bit( P1MEMCFG2, 6, 0x1 ); /* 32 bit */
set_nbit( P1MEMCFG2, 8, 3, 0x3 ); /* Mobile DDR SDRAM */
set_2bit( P1MEMCFG2, 11, 0x1 );
set_one( P1_chip_0_cfg, 16 ); /* Bank-Row-Column organization */
// memory init
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 );
// set dramc to "go" status
set_val( P1MEMCCMD, 0x000 );
// wait ready
while( !(( read_val( P1MEMSTAT ) & 0x3 ) == 0x1));
}
/*****************start.s****************/
.globl _start
_start:
/* 硬件相关的设置 */
/* Peri port setup */
ldr r0, =0x70000000
orr r0, r0, #0x13
mcr p15,0,r0,c15,c2,4
/* 关看门狗 */
/* 往WTCON(0x7E004000)写0 */
ldr r0, =0x7E004000
mov r1, #0
str r1, [r0]
bl clock_init
/* 为调用C函数准备环境 */
ldr sp, =8*1024
bl sdram_init //初始化DDR
/* 重定位代码 */
/* 把程序的代码段、数据段复制到它的链接地址去 */
adr r0, _start /* 获得_start指令当前所在的地址 : 0*/
ldr r1, =_start /* _start的链接地址 0x50000000 */
ldr r2, =bss_start /* bss段的起始链接地址 */
cmp r0,r1
beq clean_bss
copy_loop: //从片内内存复制到DDR里
ldr r3, [r0], #4
str r3, [r1], #4
cmp r1, r2
bne copy_loop
/* 把BSS段对应的内存清零 */
clean_bss:
ldr r0, =bss_start
ldr r1, =bss_end
mov r3, #0
cmp r0, r1
beq on_ddr
clean_loop:
str r3, [r0], #4
cmp r0, r1
bne clean_loop
on_ddr:
/* 调用C函数 */
ldr pc, =main /* pc等于main的链接地址 */
//这一步程序才跳到DDR里运行(之前还在片内内存中运行)
SECTIONS
{
. = 0x50000000; //0x50000000是DRAM的首地址
.text :
{
start.o
* (.text)
}
. = ALIGN(4);
.rodata :
{
* (.rodata)
}
. = ALIGN(4);
.data :
{
* (.data)
}
. = ALIGN(4);
bss_start = . ; /* 0x50000450 */
.bss :
{
* (.bss) /* i */
* (.common)
}
bss_end = . ; /* 0x50000450 */
}