实验三——SDRAM

发布时间:
来源: 电子工程世界

一。运行环境


  开发板: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

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,

文章来源于: 电子工程世界 原文链接

本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。