经过几天的调试DDR终于驱动起来的,但还不知道稳不稳定!
开发板:OK6410
Mobile DDR型号: EDD10163BBH-5BLS-F
开发环境RVDS2.2
启动模式:SD卡启动(为了不受UBOOT的影响所以用了SD卡启动,关于SD卡启动可以参考上上篇博客)
新手写的代码,不规范!
init.s
AREA code,CODE,READONLY
PRESERVE8
CODE32
IMPORT main
IMPORT init_clock
IMPORT init_mddr
EXPORT _start
_start
;将外设基地址告诉CPU
ldr r0, =0x70000000
orr r0, r0, #0x13
mcr p15,0,r0,c15,c2,4
;关看门狗
ldr r0, =0x7E004000
mov r1, #0
str r1, [r0]
;初始化时钟
bl init_clock
;初始化DDR
bl init_mddr
adr r0,_start ;获取程序入口点当前运行地址
ldr r1,=_start ;获取程序入口点的链接地址
ldr r2,=0x50000800 ;不知道RVDS2.2的程序的大小怎么获取,但程序不会超过2K就干脆复制2K的内容过去了
cmp r0,r1 ;比较运行地址是否和链接地址相同
beq on_ddr ;如果不同则将程序复制到DDR,相同则不复制
ldr r4,=0x7f008824 ;用于测试
mov r5,#0x03
copy_loop
str r5,[r4] ;当程序到这里的时候亮2个LED,说明开始拷贝了
ldr r3,[r0],#4 ;将运行地址的程序拷贝到链接地址去
str r3,[r1],#4
cmp r1,r2 ;当r1增长到和r2相等了说明2K复制完成
bne copy_loop
on_ddr
ldr r1,=0x7f008824 ;测试
mov r0,#0x07
str r0,[r1] ;程序即将跳转到main时亮一个LED
ldr sp,=0x50001000 ;设置栈指针
ldr pc,=main ;跳转
clock.s
AREA clock,CODE,READONLY
PRESERVE8
CODE32
EXPORT init_clock
APLL_LOCK EQU 0x7e00f000
MPLL_LOCK EQU 0x7e00f004
EPLL_LOCK EQU 0x7e00f008
APLL_CON EQU 0x7e00f00c
MPLL_CON EQU 0x7e00f010
EPLL_CON0 EQU 0x7e00f014
EPLL_CON1 EQU 0x7e00f018
CLK_SRC EQU 0x7e00f01c
CLK_DIV0 EQU 0x7e00f020
CLK_OTHER EQU 0x7e00f900
MDIV EQU 266
PDIV EQU 3
APLL_SDIV EQU 1
MPLL_SDIV EQU 1
APLL_CON_VAL EQU ((1<<31)|(MDIV<<16)|(PDIV<<8)|APLL_SDIV)
MPLL_CON_VAL EQU ((1<<31)|(MDIV<<16)|(PDIV<<8)|MPLL_SDIV)
init_clock
ldr r0,=APLL_LOCK
ldr r1,=0xffff
str r1,[r0]
ldr r0,=MPLL_LOCK
ldr r1,=0xffff
str r1,[r0]
ldr r0,=EPLL_LOCK
ldr r1,=0xffff
str r1,[r0]
ldr r0,=CLK_OTHER ;设置为异步模式(Asynchronous mode)
ldr r1,[r0] ;用MPLL作为HCLK和PCLK的Source是异步(ASYNC)模式,用APLL是同步(SYNC)模式
bic r1,#0xc0
str r1,[r0]
ldr r0,=CLK_OTHER
loop
ldr r1,[r0]
and r1,#0xf00
cmp r1,#0x0
bne loop ;等待进入异步模式
ldr r0,=APLL_CON ;设置APLL_CON 532MHZ
ldr r1,=APLL_CON_VAL
str r1,[r0]
ldr r0,=MPLL_CON ;设置MPLL_CON 532MHZ
ldr r1,=MPLL_CON_VAL
str r1,[r0]
ldr r0,=CLK_SRC ;设置时钟源
ldr r1,=(1<<1)|(1<<0)
str r1,[r0]
ldr r0,=CLK_DIV0 ;设置分频系数
ldr r1,=(3<<12)|(1<<8)|(1<<9)
str r1,[r0]
ldr r1,=0x7f008824 ;测试
mov r0,#0x01
str r0,[r1] ;亮3个LED
mov pc,lr ;返回
ddr.s
AREA clock,CODE,READONLY
PRESERVE8
CODE32
EXPORT init_mddr
P1MEMCFG2 EQU 0x7e00104c
MEM_SYS_CFG EQU 0x7e00f120
P1MEMSTAT EQU 0x7e001000
P1MEMCCMD EQU 0x7e001004
DIRECTCMD EQU 0x7e001008
P1MEMCFG EQU 0x7e00100c
P1REFRESH EQU 0x7e001010
P1CASLAT EQU 0x7e001014
P1T_DQSS EQU 0x7e001018
P1T_MRD EQU 0x7e00101c
P1T_RAS EQU 0x7e001020
P1T_RC EQU 0x7e001024
P1T_RCD EQU 0x7e001028
P1T_RFC EQU 0x7e00102c
P1T_RP EQU 0x7e001030
P1T_RRD EQU 0x7e001034
P1T_WR EQU 0x7e001038
P1T_WTR EQU 0x7e00103c
P1T_XP EQU 0x7e001040
P1T_XSR EQU 0x7e001044
P1T_ESR EQU 0x7e001048
P1_chip_cfg EQU 0x7e001200
init_mddr
ldr r0,=P1MEMCCMD ;参考6410手册 page 192 DDR初始化流程
mov r1,#0x04
str r1,[r0]
;设置DDR时间参数,时间基本都可以在DDR手册上找到,可能个别参数的名字不一样
ldr r0,=P1REFRESH
ldr r1,=0x40d
str r1,[r0]
ldr r0,=P1CASLAT
mov r1,#0x06 ;3<<1
str r1,[r0]
ldr r0,=P1T_DQSS
mov r1,#0x1
str r1,[r0]
ldr r0,=P1T_MRD
mov r1,#0x02
str r1,[r0]
ldr r0,=P1T_RAS
mov r1,#0x06
str r1,[r0]
ldr r0,=P1T_RC
mov r1,#0x08
str r1,[r0]
ldr r0,=P1T_RCD
mov r1,#0x03
str r1,[r0]
ldr r0,=P1T_RFC
ldr r1,=0x10B
str r1,[r0]
ldr r0,=P1T_RP
mov r1,#0x03
str r1,[r0]
ldr r0,=P1T_RRD
mov r1,#0x02
str r1,[r0]
ldr r0,=P1T_WR
mov r1,#0x03
str r1,[r0]
ldr r0,=P1T_WTR
mov r1,#0x02
str r1,[r0]
ldr r0,=P1T_XP ;在DDR手册上的参数为 tPDEX
mov r1,#0x01
str r1,[r0]
ldr r0,=P1T_XSR ;在DDR手册上的参数为 tSREX
mov r1,#0x10
str r1,[r0]
ldr r0,=P1T_ESR ;没找到,跟上个设置为一样的
mov r1,#0x10
str r1,[r0] ;时间参数设置完成
ldr r0,=P1MEMCFG ;设置 Row、Column位数、AP位(在DDR手册 page 13有讲 或搜索AP)memory burst 突发传输长度(需配合MRS设置)
ldr r1,=2|(3<<3)|(2<<15)
str r1,[r0]
ldr r0,=P1MEMCFG2 ;前4位不知道为什么这样设置
ldr r1,=5|(1<<6)|(3<<8)|(1<<11)
str r1,[r0]
; ldr r0,=P1_chip_cfg ;不知道为什么这样设置
; mov r1,#16
; str r1,[r0]
ldr r0,=DIRECTCMD ;发送NOP 6410手册page 192 “MOBILE DDR SDRAM INITIALIZATION SEQUENCE”
mov r1,#0xc0000
str r1,[r0]
ldr r0,=DIRECTCMD ;precharge
mov r1,#0x0
str r1,[r0]
ldr r0,=DIRECTCMD ;auto refresh
mov r1,#0x40000
str r1,[r0]
ldr r0,=DIRECTCMD ;auto refresh
mov r1,#0x40000
str r1,[r0]
ldr r0,=DIRECTCMD ;EMRS command b010 MRS/EMRS bank b10 EMRS DDR手册 ” Extended Mode Register “
mov r1,#0xa0000
str r1,[r0]
ldr r0,=DIRECTCMD ;MRS command b010 MRS/EMRS bank b00 MRS DDR手册 “Mode Register”
ldr r1,=0x80032
str r1,[r0]
ldr r0,=MEM_SYS_CFG ;由于是32位数据线所以要将X1mDATA[31:16]作为内存的高半字节使用(如果不是看别人的程序还真不知道要设置这个位)
mov r1,#0
str r1,[r0]
ldr r0,=P1MEMCCMD ;内存控制器进入ready状态
mov r1,#0
str r1,[r0]
ldr r0,=P1MEMSTAT
wait_ddr ;等待进入
ldr r1,[r0]
and r1,r1,#0x03
cmp r1,#0x01
bne wait_ddr
mov pc,lr ;返回
led.c
#define GPMCON (*(volatile unsigned long *)0x7F008820)
#define GPMDAT (*(volatile unsigned long *)0x7F008824)
void delay(volatile int count)
{
int i = 10000;
while(count--)
{
for(i=10000;i--;);
}
}
int main()
{
int i = 0;
GPMCON &= ~(0xffff);
GPMCON |= 0x1111;
GPMDAT = 0x55;
while (1)
{
GPMDAT &= ~0xf;
GPMDAT |= i;
i++;
delay(2000);
if (i == 16)
i = 0;
}
return 0;
}