zoukankan      html  css  js  c++  java
  • 实验三——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
    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(pSrc<(unsigned int*)4096)
    48     {
    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,
    54             };
    55 
    56     for(;i<13;i++)
    57         p[i]=mem_jcq[i];
    58 }
    59 
    60 《三》。
    61 
    62  #define       MEM_CTL_BASE               0x48000000
    63 #define       MEM_CTL_END                0x48000034
    64 unsigned long  const    mem_cfg_val[]={         // 声明数组存放内存控制器设置数据
    65 
    66            0x22000000,                //BWSCON
    67            0x00000700,                //BANKCON0
    68            0x00000700,                //BANKCON1
    69            0x00000700,                //BANKCON2
    70            0x00000700,                //BANKCON3 
    71            0x00000700,                //BANKCON4
    72            0x00000700,                //BANKCON5
    73            0x00018005,                //BANKCON6
    74            0x00018005,                //BANKCON7
    75            0x008e07a3,                 //REFRESH(HCLK = 12MHz,该值为0x008e07a3                                                //HCLK = 100MHz 0x008e04f5)
    76            0x000000b1,                //BANKSIZE
    77            0x00000030,                //MRSRB6
    78            0x00000030,                //MRSRB7
    79 };

    上面是三种写法,唯有第一种可行。why?

    比较一,二,三以及查阅资料可知,其根本原因是位置无关码

    注意,在复制代码到sdram之前,链接地址是0x30000000,也就是sdram的起始地址,此时若想正确执行,必须是使用跳转指令。

    二和三中都是以数组的形式存储,自然不会是位置无关,因而行不通。

    那么,怎么编写位置无关码呢?

    先总结基本为两点

    一。在汇编中,使用B/BL指令

    二。在c中,避免使用static来限定范围;连续寄存器组尽量分别赋值。

    附,另一个可行的办法:

     1 void memsetup(void)
     2 {
     3     volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;
     4 
     5     /* 这个函数之所以这样赋值,而不是像前面的实验(比如mmu实验)那样将配置值
     6      * 写在数组中,是因为要生成”位置无关的代码”,使得这个函数可以在被复制到
     7      * SDRAM之前就可以在steppingstone中运行
     8      */
     9     /* 存储控制器13个寄存器的值 */
    10     p[0] = 0x22011110;     //BWSCON
    11     p[1] = 0x00000700;     //BANKCON0
    12     p[2] = 0x00000700;     //BANKCON1
    13     p[3] = 0x00000700;     //BANKCON2
    14     p[4] = 0x00000700;     //BANKCON3  
    15     p[5] = 0x00000700;     //BANKCON4
    16     p[6] = 0x00000700;     //BANKCON5
    17     p[7] = 0x00018005;     //BANKCON6
    18     p[8] = 0x00018005;     //BANKCON7
    19     p[9]  = 0x008C07A3;   //REFRESH
    20     p[10] = 0x000000B1;     //BANKSIZE
    21     p[11] = 0x00000030;     //MRSRB6
    22     p[12] = 0x00000030;     //MRSRB7
    23 }
  • 相关阅读:
    linux网络编程系列TCP及常用接口分析
    Linux网络编程系列TCP状态分析
    常见的HTTP 1.1状态代码及含义
    修改android SDK 模拟器(avd) 内存大小
    Android应用研发核心竞争力
    网路编程——阻塞式&&非阻塞式
    URI、URL和URN之间的区别与联系
    初识android——四大组件
    无依赖的combobox组件(autocomplete组件)
    为什么JS没有catchMyException或类似的方法
  • 原文地址:https://www.cnblogs.com/hulig7/p/4083511.html
Copyright © 2011-2022 走看看