DDR
15条地址线32k
128M*2(20)=2(27)
查看6410芯片手册;
5.4.3 DDR/MOBILE DDR SDRAM INITIALIZATION SEQUENCE
• Program mem_cmd in direct_cmd to ‘2’b10’, which makes DRAM Controller issue ‘NOP’ memory command.
• Program mem_cmd in direct_cmd to ‘2’b00’, which makes DRAM Controller issue ‘Prechargeall’ memory
command.
• Program mem_cmd in direct_cmd to ‘2’b11’, which makes DRAM Controller issue ‘Autorefresh’ memory
command.
• Program mem_cmd in direct_cmd to ‘2’b11’, which makes DRAM Controller issue ‘Autorefresh’ memory
command.
• Program mem_cmd to ‘2’b10’ in direct_cmd, which makes DRAM Controller issue ‘MRS’ memory command
− Bank address for EMRS must be set.
• Program mem_cmd to ‘2’b10’ in direct_cmd, which makes DRAM Controller issue ‘MRS’ memory command.
− Bank address for MRS must be set.
0x50000000 0x5FFFFFFF - - - - - DRAM Ctrl 1
示例代码如下:
sratr.S文件
.globl _start
_start:
/*硬件相关设置*/
ldr r0, =0x70000000
orr r0,r0,#0x13
mcr p15,0,r0,c15,c2,4
/*关看门狗*/
ldr r0,=0x7E00400
mov r1,#0
str r1,[r0]
/*初始化时钟*/
bl clock_init
/*为C函数准备环境*/
ldr sp,=8*1024
bl sdram_init
/*重定位代码*/
adr r0,_start /*取得_start指令当前所在位置*/
ldr r1,=_start /*_start 的链接地址*/
ldr r2,=bss_start /*bss段的起始地址*/
cmp r0,r1 /*比较两寄存器的值*/
beq clean_bss /*如果两个值相同,跳转到clean_bss*/
copy_loop:
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
/*调用C函数*/
on_ddr:
ldr pc,=main /*pc等于main的链接地址*/
clock.S文件
#define APLL_CLOCK 0x7e00f000
#define MPLL_CLOCK 0x7e00f004
#define EPLL_CLOCK 0x7e00f008
#define LOCK_TIME 0xffff
#define OTHERS 0x7e00f900
#define CLK_DIV0 0x7e00f020
#define CLK_SRC 0x7e00f01c
.text
.global clock_init
clock_init:
/*设置lock_time*/
ldr r0,=APLL_CLOCK
ldr r1,=LOCK_TIME
str r1,[r0] /*APLL_LOCK*/
str r1,[r0,#4] /*MPLL_LOCK*/
str r1,[r0,#8] /*EPLL_LOCK*/
/*当cpu时钟!=HCLK时,设置为异步模式*/
ldr r0,=OTHERS
ldr r1,[r0]
bic r1,#0xc0
str r1,[r0]
loop1:
ldr r0,=OTHERS
ldr r1,[r0]
and r1,#0xf00
cmp r1,#0
bne loop1
#define ARM_RATIO 0
#define HCLKX2_RATIO 1
#define HCLK_RATIO 1
#define PCLK_RATIO 3
#define MPLL_RATIO 0
ldr r0,=CLK_DIV0
ldr r1,=(ARM_RATIO)|(MPLL_RATIO<<4)|(HCLK_RATIO<<8)|(HCLKX2_RATIO<<9)|(PCLK_RATIO<<12)
str r1,[r0]
/*配置时钟 apll mpll epll*/
#define SDIV 1
#define PDIV 3
#define MDIV 266
#define PLL_ENABLE (1<<31)
#define APLL_VAL ((SDIV<<0)|(PDIV<<8)|(MDIV<<16)|(PLL_ENABLE))
#define MPLL_VAL APLL_VAL
#define EPLL0_VAL ((2<<0)|(1<<8)|(32<<16)|PLL_ENABLE)
#define EPLL1_VAL (0)
#define APLL_CON 0x7e00f00c
#define MPLL_CON 0x7e00f010
#define EPLL_CON0 0x7e00f014
#define EPLL_CON1 0x7e00f018
ldr r0,=APLL_CON
ldr r1,=APLL_VAL
str r1,[r0]
ldr r0, =MPLL_CON
ldr r1, =MPLL_VAL
str r1, [r0]
ldr r0, =EPLL_CON0
ldr r1, =EPLL0_VAL
str r1, [r0]
ldr r0, =EPLL_CON1
ldr r1, =EPLL1_VAL
str r1, [r0]
/*选择PLL的输出作为时钟源*/
ldr r0, =CLK_SRC
mov r1, #7
str r1, [r0]
mov pc, lr
Common.h文件
#ifndef __COMMON_H
#define __COMMON_H
#define vi *( volatile unsigned int * )
#define set_zero( addr, bit ) ( (vi addr) &= ( ~ ( 1 << (bit) ) ) )
#define set_one( addr, bit ) ( (vi addr) |= ( 1 << ( bit ) ) )
#define set_bit( addr, bit, val ) ( (vi addr) = (( vi addr)&=(~(1<<(bit))) ) | ( (val)<<(bit) ) )
#define set_2bit( addr, bit, val ) ( (vi addr) = (( vi addr)&(~(3<<(bit))) ) | ( (val)<<(bit) ) )
#define set_nbit( addr, bit, len, val ) \
( (vi addr) = ((( vi addr)&(~(( ((1<<(len))-1) )<<(bit)))) | ( (val)<<(bit) ) ))
#define get_bit( addr, bit ) ( (( vi addr ) & ( 1 << (bit) )) > 0 )
#define get_val( addr, val ) ( (val) = vi addr )
#define read_val( addr ) ( vi ( addr ) )
#define set_val( addr, val ) ( (vi addr) = (val) )
#define or_val( addr, val ) ( (vi addr) |= (val) )
/**********************************************/
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
// function declare
int delay( int );
#endif /* __COMMON_H */
Sdram.c文件
#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 )
{
// tell dramc to configure
set_val( MEMCCMD, 0x4 );
// 设置refresh period
set_val( P1REFRESH, nstoclk(7800) );
// 设置时序
set_val( P1CASLAT, ( 3 << 1 ) );
set_val( P1T_DQSS, 0x1 ); // 0.75 - 1.25
set_val( P1T_MRD, 0x2 );
set_val( P1T_RAS, nstoclk(45) );
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) );
// 设置mem cfg
set_nbit( P1MEMCFG, 0, 3, 0x2 ); /* 10 column address */
/* set_nbit: 把从第bit位开始的一共len位消零,然后把这几位设为val */
set_nbit( P1MEMCFG, 3, 3, 0x2 ); /* 13 row address */
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 );
// 设置内存控制器(dramc)状态为go
set_val( P1MEMCCMD, 0x000 );
// 准备就绪
while( !(( read_val( P1MEMSTAT ) & 0x3 ) == 0x1));
}
Led.c
void delay(){
volatile int i=0x10000000;
while (i--);
}
int main(){
int i=0;
volatile unsigned long *gpkcon=(volatile unsigned long *)0x7F008800;
volatile unsigned long *gpkdat=(volatile unsigned long *)0x7F008808;
*gpkcon=0x11110000;
while(1){
*gpkdat=i;
i++;
if(i==16)
i=0;
delay();
}
return 0;
}
Led.lds文件
SECTIONS
{
. = 0x50000000;
.text :
{
start.o
* (.text)
}
. = ALIGN(4);
.rodata :
{
* (.rodata)
}
. = ALIGN(4);
.data :
{
* (.data)
}
. = ALIGN(4);
bss_start = . ; /* 0x50000450 */
.bss :
{
* (.bss) /* i */
* (.common)
}
bss_end = . ; /* 0x50000450 */
}
Makefile文件
led.bin : start.o clock.o sdram.o led.o
arm-linux-ld -T led.lds -o led.elf $^
arm-linux-objcopy -O binary led.elf led.bin
arm-linux-objdump -D led.elf > led.dis
%.o : %.S
arm-linux-gcc -g -c -O2 -o $@ $^
%.o : %.c
arm-linux-gcc -g -c -O2 -o $@ $^
clean:
rm -f *.o *.bin *.elf *.dis