S3C2440的裸奔--内存篇


大,为何要在规定的小空间里和本身过不去呢!开发板上也同样,以前一直在一个4K大的Stepping stone里打转转,
惋惜了那64MB的内存了。那么,今天就到拥有更广阔的天地里折腾一番吧。

    s3c2440对外引出了27根地址线ADDR0~ADDR26,最多能寻址2的27次方,也就是128MB,但实际上s3c2440可以
寻址1G的地址空间,这是由于它还有8根片选信号线nGCS0~nGCS7,每根信号线对应一个128MB地址空间,这个空间被称做
BANK,因此s3c2440共有8个BANK -- BANK0~BANK7,当访问某个BANK时,其对应的nGCS信号引脚电平拉低,这和单
片机上的扩展IO的操做类同。s3c2440是32位的芯片,理论上支持2的32次方,即4GB的地址空间,除去上面8个BANK用掉的
1GB地址空间外,特殊功能寄存器占用了0x48000000~0x5b00001c这段地址空间,其它的地址空间没有被使用。
    
    BANK0~BANK5能够链接ROM和SRAM类型的存储器,BANK6~BANK7能够链接ROM、SRAM、SDRAM类型的存储器,
最大支持256MB,mini2440将两片32MB,16bits位宽的SDRAM链接在了BANK6和BANK7上,并联构成64MB、32位宽的
内存。

    在处理SDRAM内部的数据时须要先指定行,再指定列,便可访问到须要的数据,由行和列构成的矩阵称为存储阵列,
你们通常会把它叫做"L-BANK",但SDRAM里面不会只有一个存储阵列,这是由于若是只作一个存储阵列会形成严重的寻址
冲突并大幅度下降内存效率。因此通常人们都将内存分为4个存储阵列(这也是SDRAM规范中的最高L-BANK数量),访问时
每次只能访问一个,具体访问那个L-BANK能够经过内存的两个外接引脚BA0和BA1来决定,mini2440将addr24链接BA0、
addr25链接BA1,经过地址线24和地址线25来选择存储单元的4个L-BANK。

    SDRAM只有13根地址线A0~A12,只能寻址8MB(2的13次方)的内存空间,因为每一个内存内部划分红四个L-BANK,因此
经过addr24和addr25的配合,就能够寻址一个内存芯片的所有空间。开发板上一共有两片并联的32MB的SDRAM,每发送一次
地址信号,两片芯片均可以同时接收到,以后其中一片返回低16bits的数据,另外一片返回高16bits的数据。下面是内存芯片和
cpu的引脚的链接表:linux

--------------------------------------------------------------------------------------------------------------------cpu引脚          内存芯片引脚    描述--------------------------------------------------------------------------------------------------------------------A2~A14       A0~A12       地址线--------------------------------------------------------------------------------------------------------------------D0~D31       DQ0~DQ31     数据线,其中一片的DQ0~DQ15链接D0~D15,另外一片的DQ0~DQ15链接D16~D31--------------------------------------------------------------------------------------------------------------------A24,A25      BA0,BA1      L-BANK选择信号--------------------------------------------------------------------------------------------------------------------DQM0~DQM3    LDQM,UDQM    高低字节数据掩码信号--------------------------------------------------------------------------------------------------------------------SCKE         SCKE         输入时钟有效信号--------------------------------------------------------------------------------------------------------------------SCLK         SCLK         输入时钟--------------------------------------------------------------------------------------------------------------------nSCS0        nSCS         片选信号(和nGCS6是同一个引脚,只是功能不一样)--------------------------------------------------------------------------------------------------------------------nSRAS        nSRAS        行地址选通讯号--------------------------------------------------------------------------------------------------------------------nSCAS        nSCAS        列地址选通讯号--------------------------------------------------------------------------------------------------------------------nWE          nWE          写入有效信号--------------------------------------------------------------------------------------------------------------------

 



存储控制器的寄存器部分这里略过。    

    下面是启动代码:
 ide

@*************************************************************************@ File:head.S@ 功能:关闭看门狗,初始化时钟,初始化内存,将Stepping stone的数据@复制到SDRAM,  而后跳到内存中继续运行main函数,循环点亮led灯。@*************************************************************************       @看门狗寄存器.equ        WTCON,       0x53000000     @看门狗控制寄存器.equ        WTDAT,       0x53000004     @看门狗数据寄存器.equ        WTCNT,       0x53000008     @看门狗计数寄存器@系统时钟寄存器.equ        LOCKTIME,    0x4c000000     @变频锁定时间寄存器.equ        MPLLCON,     0x4c000004     @MPLL寄存器.equ        CLKDIVN,     0x4c000014     @分频比寄存器@内存寄存器.equ        MEM_CTL_BASE,       0x48000000.equ        SDRAM_BASE,         0x30000000  @定义64MB内存开始的地址.equ        SDRAM_END,          0x34000000  @定义64MB内存结束的地址.text.global _start_start:        bl    disable_watch_dog               @ 关闭WATCHDOG,不然CPU会不断重启        bl    init_clock                      @初始化系统时钟        bl    memsetup                        @ 设置存储控制器        bl    copy2sdram                      @ 复制代码到SDRAM中        ldr   pc, =on_sdram                   @ 跳到SDRAM中继续执行on_sdram:            ldr   sp, =SDRAM_END                  @ 设置堆栈,堆栈由高地址向低地址生长            bl    mainhalt_loop:            b    halt_loopdisable_watch_dog:        mov   r1, #WTCON        mov   r2, #0x0                        @ 往WATCHDOG寄存器写0便可        str   r2, [r1]        mov   pc, lr                          @ 返回init_clock:            @ 设置锁频时间        ldr   r0, =LOCKTIME                   @取得LOCKTIME寄存器地址        ldr   r1, =0x00ffffff                 @设置锁定时间        str   r1, [r0]                        @将r1中的数据写入r0           @设置FCLK,HCLK,PCLK三者之间的比例,原本还须要设置CAMDIVN寄存器,        @但这里设置成1:4:8,因此CAMDIVN使用默认值就能够了!        ldr   r0, =CLKDIVN                    @取得CLKDIVN寄存器地址        mov   r1, #0x05                       @设定比例        str   r1, [r0]                @修改CPU总线模式        mrc   p15, 0, r1, c1, c0, 0        orr   r1, r1, #0xc0000000        mcr   p15, 0, r1, c1, c0, 0        @倍频到400MHz          ldr   r0, =MPLLCON                    @MPLL控制寄存器        ldr   r1, =0x0005c011        str   r1, [r0]        mov   pc, lr                          @ 返回copy2sdram:            @ 将Steppingstone的4K数据所有复制到SDRAM中去            @ Steppingstone起始地址为0x00000000,SDRAM中起始地址为0x30000000            mov   r1, #0            ldr   r2, =SDRAM_BASE            mov   r3, #4*1024copyloop:              ldr   r4, [r1],#4                     @ 从Steppingstone读取4字节的数据,并让源地址加4            str   r4, [r2],#4                     @ 将此4字节的数据复制到SDRAM中,并让目地地址加4            cmp   r1, r3                          @ 判断是否完成:源地址等于Steppingstone的未地址?            bne   copyloop                        @ 若没有复制完,继续            mov   pc, lr                          @ 返回memsetup:            @ 设置存储控制器以便使用SDRAM等外设           mov   r1, #MEM_CTL_BASE               @ 存储控制器的13个寄存器的开始地址           adrl  r2, mem_cfg_val                 @ 这13个值的起始存储地址           add   r3, r1, #52                     @ 13*4 = 54initmemloop:              ldr   r4, [r2], #4                    @ 读取设置值,并让r2加4           str   r4, [r1], #4                    @ 将此值写入寄存器,并让r1加4           cmp   r1, r3                          @ 判断是否设置完全部13个寄存器           bne   initmemloop                     @ 若没有写成,继续            mov   pc, lr                          @ 返回@4字节对齐.align 4  mem_cfg_val:    @ 存储控制器13个寄存器的设置值    .long   0x22000000      @ 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   0x008E04F5      @ REFRESH    .long   0x000000B1      @ BANKSIZE    .long   0x00000030      @ MRSRB6    .long   0x00000030      @ MRSRB7@******************************************************************************

 





C程序仍是使用上次那个leds.c程序,这里就再也不列出代码了!
而后是编译用的Makefile.函数

#******************************************************************************#Makefile#******************************************************************************sdram.bin : head.S  leds.c    arm-linux-gcc  -c -o head.o head.S    arm-linux-gcc -c -o leds.o leds.c    arm-linux-ld -Ttext 0x30000000 head.o leds.o -o sdram_elf    arm-linux-objcopy -O binary -S sdram_elf sdram.bin    arm-linux-objdump -D -m arm  sdram_elf > sdram.disclean:    rm -f   sdram.dis sdram.bin sdram_elf *.o#****************************************************************************** 

 



编译以后获得sdram.bin,下载到开发板上运行。能够看到led闪烁的速度比上次慢了不少,oop


这是由于外部的SDRAM的性能比内部的SRAM差不少。但内部的SRAM只有4k,若是程序大于4k,性能


就须要想办法将存储在NAND中的代码复制到SDRAM中去运行。spa


注意:上面的代码只是把SRAM中的代码复制到SDRAM中运行,并非将NAND Flash中的code

相关文章
相关标签/搜索