ARM SDRAM初始化

用两片16位SDRAM组成32位宽度的SDRAM

SDRAM接与bank6所以访问地址范围为0x30000000~0x3fffffff

eclipse裸机环境调试,源码就不上传了麻烦

SDRAM相关寄存器介绍:

1.BWSCON位宽和等待控制寄存器

      BWSCON:对应BANK0-BANK7,每BANK使用4位。这4位分别表示:
      a.STx:启动/禁止SDRAM的数据掩码引脚,对SDRAM,此位为0;对SRAM,此位为1
      b.WSx:是否使用存储器的WAIT信号,通常设为0
      c.DWx:使用两位来设置存储器的位宽:00-8位,01-16位,10-32位,11-保留。
      d.比较特殊的是BANK0对应的4位,它们由硬件跳线决定,只读。
      e.对于本开发板,使用两片容量为32Mbyte、位宽为16的SDRAM组成容量为64Mbyte、
        位宽为32的存储器,所以其BWSCON相应位为:0010。对于本开发板,BWSCON可设为
        0x22111110:其实我们只需要将BANK6对应的4位设为0010即可,其它的是什么值没
        什么影响,这个值是参考手册上给出的。

   2.BANKCON0-BANKCON5:使用默认值0x00000700
   3.BANKCON6-BANKCON7:设为0x00018005
      在8个BANK中,只有BANK6和BANK7可以使用SRAM或SDRAM,与BANKCON0-5有点不同:
      a.MT([16:15]):用于设置本BANK外接的是SRAM还是SDRAM:SRAM-0b00,SDRAM-0b11
      b.当MT=0b11时,还需要设置两个参数:
         Trcd([3:2]):RAS to CAS delay,设为推荐值0b01
         SCAN([1:0]):SDRAM的列地址位数,本开发板的SDRAM列地址位数为9,所以SCAN=0b01
   4.REFRESH(SDRAM refresh control register):
      其中R_CNT用于控制SDRAM的刷新周期,占用REFRESH寄存器的[10:0]位,它的取值可
      如下计算(SDRAM时钟频率就是HCLK):
      R_CNT = 2^11 + 1 – SDRAM时钟频率(MHz) * SDRAM刷新周期(uS)
      在未使用PLL时,SDRAM时钟频率等于晶振频率12MHz;SDRAM的刷新周期在SDRAM的数
      据手册上有标明,在本开发板使用的SDRAM HY57V561620CT-H的数据手册上,可看见
      这么一行“8192 refresh cycles / 64ms”:所以,刷新周期=64ms/8192 = 7.8125 uS。

      对于本实验,R_CNT = 2^11 + 1 – 12 * 7.8125 = 1955
      REFRESH=0x008e0000 + 1955 = 0x008e07a3
   5.BANKSIZE:0x000000b2
      位[7]=1:Enable burst operation
      位[5]=1:SDRAM power down mode enable
      位[4]=1:SCLK is active only during the access (recommended)
      位[2:1]=010 BANK6、BANK7对应的地址空间: 010-128M/128M, 001-64M/64M
   6.MRSRB6、MRSRB7:0x00000030
      能让我们修改的只有位[6:4](CL),SDRAM HY57V561620CT-H不支持CL=1的情况,所以
      位[6:4]取值为010(CL=2)或011(CL=3)

 

GUN汇编初始化

memsetup:
    @ 设置存储控制器以便使用SDRAM等外设

    mov r1,     #MEM_CTL_BASE       @ 存储控制器的13个寄存器的开始地址
    adrl    r2, mem_cfg_val         @ 这13个值的起始存储地址
    add r3,     r1, #52             @ 13*4 = 54
1:  
    ldr r4,     [r2], #4            @ 读取设置值,并让r2加4
    str r4,     [r1], #4            @ 将此值写入寄存器,并让r1加4
    cmp r1,     r3                  @ 判断是否设置完所有13个寄存器
    bne 1b                          @ 若没有写成,继续
    mov pc,     lr                  @ 返回


.align 4
mem_cfg_val:
    @ 存储控制器13个寄存器的设置值
    .long   0x22011110      @ BWSCON
    .long   0x00000700      @ BANKCON0
    .long   0x00000700      @ BANKCON1
    .long   0x00000700      @ BANKCON2
    .long   0x00000700      @ BANKCON3  
    .long   0x00000700      @ BANKCON4
    .long   0x00000700      @ BANKCON5
    .long   0x00018005      @ BANKCON6
    .long   0x00018005      @ BANKCON7
    .long   0x008C07A3      @ REFRESH
    .long   0x000000B1      @ BANKSIZE
    .long   0x00000030      @ MRSRB6
    .long   0x00000030      @ MRSRB7


试用C语言初始化(调用之前需要设置好堆栈sp)  ,了解位置无关码

/*
 * 设置存储控制器以使用SDRAM
 */
void memsetup(void)
{
    volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;

    /* 这个函数之所以这样赋值,而不是像前面的实验(比如mmu实验)那样将配置值
     * 写在数组中,是因为要生成”位置无关的代码”,使得这个函数可以在被复制到
     * SDRAM之前就可以在steppingstone中运行
     */
    /* 存储控制器13个寄存器的值 */
    p[0] = 0x22011110;     //BWSCON
    p[1] = 0x00000700;     //BANKCON0
    p[2] = 0x00000700;     //BANKCON1
    p[3] = 0x00000700;     //BANKCON2
    p[4] = 0x00000700;     //BANKCON3  
    p[5] = 0x00000700;     //BANKCON4
    p[6] = 0x00000700;     //BANKCON5
    p[7] = 0x00018005;     //BANKCON6
    p[8] = 0x00018005;     //BANKCON7
    
                                            /* REFRESH,
                                             * HCLK=12MHz:  0x008C07A3,
                                             * HCLK=100MHz: 0x008C04F4
                                             */ 
    p[9]  = 0x008C04F4;
    p[10] = 0x000000B1;     //BANKSIZE
    p[11] = 0x00000030;     //MRSRB6
    p[12] = 0x00000030;     //MRSRB7
}


初始化结束后就可以将前4K的内容搬运到SDRAM中运行

copy_steppingstone_to_sdram:
    @ 将Steppingstone的4K数据全部复制到SDRAM中去
    @ Steppingstone起始地址为0x00000000,SDRAM中起始地址为0x30000000
    
    mov r1, #0
    ldr r2, =SDRAM_BASE
    mov r3, #4*1024
1:  
    ldr r4, [r1],#4     @ 从Steppingstone读取4字节的数据,并让源地址加4
    str r4, [r2],#4     @ 将此4字节的数据复制到SDRAM中,并让目地地址加4
    cmp r1, r3          @ 判断是否完成:源地址等于Steppingstone的未地址?
    bne 1b              @ 若没有复制完,继续
    mov pc,     lr      @ 返回


 

void copy_steppingstone_to_sdram(void)
{
    unsigned int *pdwSrc  = (unsigned int *)0;
    unsigned int *pdwDest = (unsigned int *)0x30000000;
    
    while (pdwSrc < (unsigned int *)4096)
    {
        *pdwDest = *pdwSrc;
        pdwDest++;
        pdwSrc++;
    }
}


 

 

 

你可能感兴趣的:(ARM,GUN)