DDR学习笔记

DDR

15条地址线32k 

128M*2(20)=2(27)



DDR学习笔记_第1张图片

查看6410芯片手册;

5.4.3 DDR/MOBILE DDR SDRAM INITIALIZATION SEQUENCE 

• Program mem_cmd in direct_cmd to 2b10, which makes DRAM Controller issue NOP’ memory command. 

• Program mem_cmd in direct_cmd to 2b00, which makes DRAM Controller issue Prechargeall’ memory 

command. 

• Program mem_cmd in direct_cmd to 2b11, which makes DRAM Controller issue Autorefresh’ memory 

command. 

• Program mem_cmd in direct_cmd to 2b11, which makes DRAM Controller issue Autorefresh’ memory 

command. 

• Program mem_cmd to 2b10’ in direct_cmd, which makes DRAM Controller issue MRS’ memory command 

− Bank address for EMRS must be set. 

• Program mem_cmd to 2b10’ 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

你可能感兴趣的:(DDR学习笔记)