一。运行环境
开发板:jz2440
系统: ubuntu12.04
编译器:arm-linux-gcc
二、特殊寄存器
sdram的操作无需按照时序图来设置,只要设置好相关的13个寄存器,arm处理器里面的存储管理器会自动输出控制信号
1 .long 0x22011110 @ BWSCON
2 .long 0x00000700 @ BANKCON0
3 .long 0x00000700 @ BANKCON1
4 .long 0x00000700 @ BANKCON2
5 .long 0x00000700 @ BANKCON3
6 .long 0x00000700 @ BANKCON4
7 .long 0x00000700 @ BANKCON5
8 .long 0x00018005 @ BANKCON6
9 .long 0x00018005 @ BANKCON7
10 .long 0x008C07A3 @ REFRESH
11 .long 0x000000B1 @ BANKSIZE
12 .long 0x00000030 @ MRSRB6
13 .long 0x00000030 @ MRSRB7
先看BWSCON:
每四位控制一个BKNK
对于SDRAM,ST7设置为0,SRAN则设置为1
WSx通常设置为0
DBx设置为01b,这个一般按照实际情况来设置,还要参照具体开发板上面存储资源。
对于这六个寄存器,主要设置时序的,默认值就欧克
MT[16:15]设置SRAM OR SDRAM ,这里设置0B11
如果是sdram,那么Trcd 设为推荐值0b10
SCAN 设置为9-bit
对于刷新寄存器,注意低11位会根据CLK不同而不同,也就是说使用PLL与否,会有不同的值
由此可算出
Refreh_count =2^12+1-12*64/8092=1955
REFRESF=0x008c0000+1955
先看代码:这里主要有三个head.S ,led.c ,Makefile,其中led的代码同流水灯一样,直接拷贝过来。
此外外,代码参考韦东山先生的源码,经过烧写可验证没问题。
三。直接贴代码
先看Makefile:
1 sdram.bin:head.S led.c
2 arm-linux-gcc -Wall -O2 -c -g -o head.o head.S
3 arm-linux-gcc -Wall -O2 -c -g -o led.o led.c
4 arm-linux-ld -Ttext 0x30000000 head.o led.o -o sdram_elf
5 arm-linux-objcopy -O binary -S sdram_elf sdram.bin
6 arm-linux-objdump -D -m arm sdram_elf>sdram.dis
7
8 clean:
9 rm -f sdram.bin sdram_elf*.o sdram.dis
再看head.h
1 .equ MEM_BASE,0x48000000
2 .equ SDRAM_BASE,0x30000000
3
4 .text
5 .global _start
6 _start:
7
8 bl close_watchdog @关闭看门狗
9 bl mem_set @设置存储寄存器组
10 bl steppingstone_sdram @复制代码到sdram
11
12 ldr pc,=on_sdram
13 on_sdram:
14 ldr sp,=0x34000000
15 bl main
16 halt_loop:
17 b halt_loop
18
19
20
21 close_watchdog:
22 mov r1,#0x53000000
23 mov r2,#0x0
24 str r2,[r1]
25
26 mov pc,lr @返回
27
28 steppingstone_sdram: @起始地址0x00000000,目标地址0x30000000
29 mov r1,#0
30 ldr r2,=SDRAM_BASE
31 mov r3,#1024*4
32
33
34 copy_loop:
35 ldr r4,[r1],#4
36 str r4,[r2],#4
37
38 cmp r1,r3
39 bne copy_loop
40 mov pc,lr @返回
41
42 mem_set:
43 mov r1,#MEM_BASE
44
45 adrl r2,JCQ
46 add r3,r1,#52 @4*13
47
48 set_loop:
49 ldr r4,[r2],#4
50 str r4,[r1],#4
51 cmp r1,r3
52 bne set_loop
53
54 mov pc,lr
55
56
57 .align 4
58 JCQ:
59 .long 0x22011110 @BWSCON
60 .long 0x00000700 @bankcon0
61 .long 0x00000700 @bankcon1
62 .long 0x00000700 @bankcon2
63 .long 0x00000700 @bankcon3
64 .long 0x00000700 @bankcon4
65 .long 0x00000700 @bankcon5
66 .long 0x00018005 @bankcon6
67 .long 0x00018005 @bankcon7
68 .long 0x008c07a3 @refresh
69 .long 0x000000b1 @banksize
70 .long 0x00000030 @mrsrb6
71 .long 0x00000030 @mrsrb7
其实没什么改动,换些名字而已,但是自己敲的话,当然会有一些细节上面会出错,不注意的地方。
以上启动文件是以汇编编写的,下面贴出c语言版的。
head.S:
1 .extern main
2 .text
3 .global _start
4 _start:
5 b reset
6
7 reset:
8 ldr sp,=4096 @
9
10 bl close_watchdog @关闭看门狗
11 bl mem_set @设置存储寄存器组
12 bl steppingstone_sdram @复制代码到sdram
13
14
15
16 ldr pc,=on_sdram
17 on_sdram:
18 ldr sp,=0x34000000
19 ldr pc,=0x30000000
20 halt_loop:
21 b halt_loop
init.c:
1 /*************************************************************************
2 > File Name: init.c
3 > Author: hulig
4 > Mail:
5 > Created Time: 2014年11月08日 星期六 15时52分55秒
6 >function:init disable watchdog ,init mem .goto main and on
7 >result:ok
8 ************************************************************************/
9
10 #define WTCON (*(volatile unsigned long *)0x53000000)
11 #define MEM_BASE (*(volatile unsigned long *)0x48000000)
12
13 void close_watchdog()
14 {
15 WTCON =0; //往看门狗寄存器里写0 就可以啦
16 }
17
18 void mem_set() //与sdram设置有关的13个寄存器写入对应的值就ok
19 {
20 unsigned long const mem_jcq[]={
21 0x22011110,
22 0x00000700,
23 0x00000700,
24 0x00000700,
25 0x00000700,
26 0x00000700,
27 0x00000700,
28 0x00018005,
29 0x00018005,
30 0x008c07a3,
31 0x000000b1,
32 0x00000030,
33 0x00000030,
34 };
35
36 int i=0;
37 volatile unsigned long *p=(volatile unsigned long *)MEM_BASE;
38 for(;i<13;i++)
39 p[i]=mem_jcq[i];
40 }
41
42 void steppingstone_sdram(void)
43 {
44 unsigned int *pSrc=(unsigned int *)0; // 将steppingstone 0地址复制到sdram起始地址
45 unsigned int *pDes =(unsigned int *)0x30000000;//sdram起始地址
46
47 while(pSrc48 {
49 *pDes=*pSrc;
50 pDes++;
51 pSrc++;
52 }
53
54
55 }
上面c代码并不能达到预期的效果,其主要问题点是sdram的初始化,也就是给13个寄存器赋值的时候:
1 《一》。
2 #define BWSCON (*(volatile unsigned long * )0x48000000)
3 #define BANKCON0 (*(volatile unsigned long * )0x48000004)
4 #define BANKCON1 (*(volatile unsigned long * )0x48000008)
5 #define BANKCON2 (*(volatile unsigned long * )0x4800000c)
6 #define BANKCON3 (*(volatile unsigned long * )0x48000010)
7 #define BANKCON4 (*(volatile unsigned long * )0x48000014)
8 #define BANKCON5 (*(volatile unsigned long * )0x48000018)
9 #define BANKCON6 (*(volatile unsigned long * )0x4800001c)
10 #define BANKCON7 (*(volatile unsigned long * )0x48000020)
11 #define REFRESH (*(volatile unsigned long * )0x48000024)
12 #define BANKSIZE (*(volatile unsigned long * )0x48000028)
13 #define MRSRB6 (*(volatile unsigned long * )0x4800002c)
14 #define MRSRB7 (*(volatile unsigned long * )0x48000030)
15
16
17 void mem_set()
18 {
19 BWSCON= 0x22011110;
20 BANKCON0=0x00000700;
21 BANKCON1=0x00000700;
22 BANKCON2=0x00000700;
23 BANKCON3=0x00000700;
24 BANKCON4=0x00000700;
25 BANKCON5=0x00000700;
26 BANKCON6=0x00018005;
27 BANKCON7=0x00018005;
28 REFRESH=0x008c07a3;
29 BANKSIZE=0x000000b1;
30 MRSRB6 =0x00000030;
31 MRSRB7= 0x00000030;
32 }
33
34
35 《二》。
36 void mem_set() //与sdram设置有关的13个寄存器写入对应的值就ok
37 {
38 int i=0;
39 unsigned long *p=(unsigned long *)MEM_BASE;
40 unsigned long const mem_jcq[]={
41 0x22011110,
42 0x00000700,
43 0x00000700,
44 0x00000700,
45 0x00000700,
46 0x00000700,
47 0x00000700,
48 0x00018005,
49 0x00018005,
50 0x008c07a3,
51 0x000000b1,
52 0x00000030,
53 0x00000030,