• JZ2440 裸机驱动 第6章 存储控制器


    本章目标:
        了解S3C2410/S3C2440地址空间的布局
        掌握如何通过总线形式访问扩展的外设,比如内存、NOR Flash、网卡等
    ····································································································
        总线的使用方法是嵌入式低层开发的基础,了解它之后,再根据外设的具体特性,就可以驱动外设了。
    6.1 使用存储控制器访问外设的原理
    6.1.1 S3C2410/S3C2440的地址空间
        S3C2410/S3C2440的“存储控制器”提供了访问外部设备所需要的信息,它有如下特性:
    ① 支持小字节序、大字节序(通过软件选择);
    ② 每个BANK的地址空间为128MB,总共1GB(8 BANKs);
    ③ 可编程控制的总线位宽(8/16/32-bit),不过BANK0只能选择两种位宽(16/32-bit);
    ④ 总共8个BANK,BANK0~BANK5可以支持外接ROM、SRAM等,BANK6~BANK7除了可以支持
        ROM、SRAM外,还支持SDRAM等;
    ⑤ BANK0~BANK6共7个BANK的起始地址是固定的;
    ⑥ BANK7的起始地址可编程选择;
    ⑦ BANK6、BANK7的地址空间大小是可编程控制的;
    ⑧ 每个的访问周期均可编程控制;
    ⑨ 可以通过外部的“wait”信号延长总线的访问周期;
    ⑩ 在外接SDRAM时,支持自刷新(self-refresh)和省电模式(power down mode)。
        S3C2410/S3C2440对外引出的27根地址线ADDR0~ADDR26的访问范围只有128MB,CPU对外
    还引出了8根片选信号nGCS0~nGCS7,对应于BANK0~BANK7,当访问BANKx的地址空间时,
    nGCSx引脚输出低电平用来选中外接的设备。这8个BANK的地址空间如下图6.1所示:
     
         S3C2410/S3C2440作为32位的CPU,可以使用的地址范围理论上达到4GB。除去上述用于连接外设
    的1GB地址空间外,还有一部分是CPU内部寄存器的地址,剩下的地址空间没有使用。
        S3C2410/S3C2440的寄存器地址范围都处于0x480 0000~0x5ff ffff,各功能部件的寄存器大体相同,
    如下表所示:
    6.1.2 存储控制器与外设的关系
        本书所用开发板使用了存储控制器的BANK0~BANK6,分别外接了如下设备:
    NOR Flash、IDE接口、10M网卡CS8900A、100M网卡DM9000、扩展串口芯片16C2550、
    SDRAM,连线方式如下图6.2所示。
        外设的访问地址 = 地址线确定的地址 + BANK的起始地址
    比如:扩展串口。
        (1)它使用nGCS5,起始地址为0x2800 0000。
        (2)nCSA=ADDR24||nGCS5,nCSB=!ADDR24||nGCS5。当ADDR24和nGCS5均为低电平
    时选中扩展串口A;当ADDR24为高电平、nGCS5为低电平时,选中扩展串口B。
        (3)CPU的ADDR0~ADDR2连接到扩展串口的A0~A2,所以访问空间为8字节。
        综上所述,扩展串口A的访问空间为:0x2800 0000~0x2800 0007;扩展串口B的
    访问空间为:0x2900 0000~0x2900 0007(bit24为1)。
    图4.2:
        BANK0~BANK5的连接方式都是类似的,BANK6连接SDRAM时复杂一点,CPU提供了一
    组用于SDRAM的信号。
    ① SDRAM时钟有效信号SCKE;
    ② SDRAM时钟信号SCLK0/SCLK1;
    ③ 数据掩码信号DQM0/DQM1/DQM2/DQM3;
    ④ SDRAM片选信号nSCS0(它与nGCS6是同一引脚的两个功能);
    ⑤ SDRAM行地址选通脉冲信号nSRAS;
    ⑥ SDRAM列地址选通脉冲信号nSCAS;
    ⑦ 写允许信号nWE(它不是专用于SDRAM的)。
        SDRAM的内部是一个存储阵列,如同表格一样,将数据填进去。
        SDRAM的寻址基本原理:先指定一个行,在指定一个列,就可以准确地找到所需要的单元格。
    这个单元格被称为存储单元。这个表格(存储阵列)就是逻辑Bank(简称L-Bank),SDRAM一般含有
    4个L-BANK。
        SDRAM的逻辑结构如图6.3所示。
        可以想象,对SDRAM的访问可以分为如下4个步骤
        (1)CPU发出的片选信号nSCS0有效,它选中SDRAM芯片;
        (2)SDRAM中有4个L-Bank,需要两根地址信号来选中其中一个,从图6.2可知使用ADDR24、
    ADDR25作为L-Bank的选择信号;
        (3)对被选中的芯片进行统一行、列(存储单元)寻址;
        根据SDRAM芯片的列地址线数目设置CPU的相关寄存器后,CPU就会从32位地址中自动分出
    L-Bank选择信号、行地址信号、列地址信号,然后先后发出行地址信号、列地址信号。L-Bank选
    择信号在发出行地址信号的同时发出,并维持到列地址信号结束。
        在图6.2中,行地址、列地址公用地址线ADDR2~ADDR14(BANK6位宽为32,ADDR0/1没有使
    用),使用nSRAS、nSCAS两个信号来区分它们。比如本开发板中,使用两根地址线ADDR24、
    ADDR25作为L-Bank的选择信号;SDRAM芯片K4S561632的行地址数为13,列地址数为9,所以
    当nSRAS信号有效时,ADDR2~ADDR14上发出的是行地址信号,它对应32位地址空间的bit[23:11];
    当nSCAS信号有效时,ADDR2~ADDR10上发出的是列地址信号,它对应32位地址空间的bit[10:2]。
    由于图6.2中BANK6以32位的宽度连接SDRAM,ADDR0、ADDR1恒为0,不参与译码。
        (4)找到存储单元后,被选中的芯片就要进行统一的数据传输了。
        开发板中使用两片16位的SDRAM芯片并联组成32位的位宽,与CPU的32根数据线(DATA0~DATA31)相连。
        BANK6的起始地址为0x3000 0000,所以SDRAM的访问地址为0x3000 0000~0x33ff ffff,共64MB。
        对图6.2中连接的外设,它们的访问地址(物理地址)如表6.2所示。

     6.1.3 存储控制器的寄存器使用方法
        存储控制器共有13个寄存器,BANK0~BANK5只需要设置BWSCON和BANKCONx(x为0~5)两个
    寄存器:BANK6和BANK7外接SDRAM时,除BWSCON和BANKCONx(x为6、7)外,还要设置REFRESH、
    BANKSIZE、MRSRB6、MRSRB7等4个寄存器。下面分类说明:
        1.位宽和等待控制寄存器BWSCON
        每4位控制一个BANK,最高4位对应BANK7、接下来4位对应BANK6,以此类推。
        (1)STx:启动/禁止SDRAM的数据掩码引脚,对于SDRAM, 此位为0;对于SRAM,此位为1;
        (2)WSx:是否使用存储器的WAIT信号,通常设为0;
        (3)DWx:使用两位来设置相应BANK的位宽:
        0b00:8位,0b01:16位,0b10:32位,0b11:保留;
           BANK0比较特殊,只支持16和32位两种位宽,它没有ST0和WS0,DW0([2:1])只读——由硬件跳线决定:
        0b01:16位,0b10:32位;
            对于本开发板,没有使用BANK7,根据表6.1可以确定BWSCON的值为:0x2201 1110。
        2.BANK控制寄存器BANKCONx(x为0~5)
        这几个寄存器用来控制BANK0~BANK5外接设备的访问时序,使用默认的0x0700即可满足
    本开发板所接各外设的要求。
        3.BANK控制寄存器BANKCONx(x为6~7)
        在8个BANK中,只有BANK6和BANK7可以外接SRAM或SDRAM,所以BANKCON6~
    BANKCON7与BANKCON0~BANKCON5有点不同。
        (1)MT([16:15]):用于设置本BANK外接的是ROM/SRAM还是SDRAM。
        当MT = 0b00:时,接SRAM,此寄存器与BANKCON0~BANKOCN5类似;
        当MT = 0b11:时,接SDRAM,此寄存器其他值如下设置。
        (2)Trcd([3:2]):RAS to CAS delay,设为推荐值0b01。
        (3)SCAN([1:0]):SDRAM的列地址位数,对于本开发板使用的SDRAM K4S561632,
    列地址位数为9,所以SCAN = 0b01。如果使用其他型号的SDRAM,需要查看数据手册来
    决定SCAN的取值。0b00:8位;0b01:9位;0b10:10位。
        综上所述,本开发板中BANKCON6、7均设为0x0001 8005。
        4.刷新控制寄存器REFRESH:设为0x008c 0000 + R_CNT
        (1)REFEN([23]):0 = 禁止SDRAM的刷新功能,1 = 开启SDRAM的刷新功能。
        (2)TREFMD([22]):SDRAM的刷新模式,0 = CBR/Auto Refresh,1 = Self Refresh(一般在系统休眠时使用)。
        (3)Trp([21:20]):设为0即可。
        (4)Tsrc([19:18]):设为默认值0b11即可。
        (5)Refresh Counter([10:0]):即上述的R_CNT,
                R_CNT = 2^11 + 1 - SDRAM时钟频率(MHz) * SDRAM刷新周期(us);
            其中SDRAM时钟频率就是HCLK,SDRAM的刷新周期在SDRAM数据手册上有标明,
    在本开发板所使用的SDRAM 数据手册上,可以看见“ 64ms refresh period(8K Cycle)”。所以,
    刷新周期 = 64ms/8192 = 7.8125us。
        在未使用PLl时,SDRAM时钟频率等于晶振频率12MHz。
        现在可以计算:R_CNT = 2^11 + 1 - 12*7.8125 = 1955。
        所以,在未使用PLL时,REFRESH = 0x008c 0000 + 195 = 0x008C 07A3。
        5.BANKSIZE寄存器BANKSIZE
        (1)BURST_EN([7])。
                0 = ARM核禁止突发传输,1 = ARM核支持突发传输。
        (2)SCKE_EN([5])。
                0 = 不使用SCKE信号令SDRAM进入省电模式,1 = 使用SCKEN信号令SDRAM进入省电模式。
        (3)SCLK_EN([4])。
                0 = 时刻发出SCLK信号,1 = 仅在访问SDRAM期间发出SCLK信号(推荐)。
        (4)BK76MAP([2:0]):设置BANK6/7的大小。
                BANK6/7对应的地址空间与BANK0~5不同:
                BANK0~5的地址空间大小都是固定的128MB,地址范围是(x * 128M)到(x+1)*128M -1,x表示0~5。
                BANK6/7的大小是可变的,以保持这两个空间的地址连续,即BANK7的起始地址会随着
    它们的大小变化。
                BK76MAP的取值意义如下:
                0b010 = 128MB/128MB,0b001 = 64MB/64MB,0b000 = 32M/M,
                0b111 = 16M/16M,0b110 = 8M/8M,0b101 = 4M/4M,0b100 = 2M/2M
                本开发板BANK6外接64MB的SDRAM,令[2:0] = 0b001,表示BANK6/7的容量都是64MB,
    虽然BANK7没使用。
        综上所述,开发板的BANKSIZE寄存器的值可算得0xB1。
        6.SDRAM模式设置寄存器MRSRBx(x为6~7)
        能修改的只有位CL([6:4]),这是SDRAM时序的一个时间参数:
        [work] 0b000 = 1 clock,0b010 = 2 clocks,0b011 = 3 clocks
        SDRAM K4S561632不支持CL = 1的情况,所以此位取值0b010(CL = 2)或0b011(CL = 3)。
    本开发板取最保守值0b011,所以MRSRB6/7的值为0x30。
    6.2 存储控制器操作实例:使用SDRAM
    6.2.1 代码详解及程序的复制、跳转过程
        从NAND Flash启动CPU时,CPU会通过内部的硬件将NAND Flash开始的4KB数据复
    到称为“Steppingstone”的4KB的内部RAM中(起始地址为0),然后跳到地址0开始执行。
        本实例先使用汇编语言设置好存储控制器,使外接的SDRAM可用;然后把程序从
    Steppingstone复制到SDRAM处;最后跳到SDRAM中执行。
        源代码在/work/hardware/sdram目录中,包含两个文件head.S和leds.c。其中leds.c和第5
    章中的leds的代码完全一样,也是让3个led从0~7轮流计数。
        重点在head.S,它的作用是设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM
    继续执行。head.S的代码如下:
     1 @****************************************
     2 @ File:head.S
     3 @ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
     4 @****************************************
     5 
     6 .equ    MEM_CTL_BASE,    0x48000000
     7 .equ    SDRAM_BASE,      0x30000000
     8     
     9 .text
    10 .global _start
    11 _start:
    12     bl disable_watch_dog             @关闭WATCHDOG
    13     bl memsetup                      @设置存储控制器
    14     bl copy_steppingston_to_sdram    @复制代码到SDRAM中
    15     ldr pc, =on_sdram                @跳到SDRAM中继续执行
    16 on_sdram:
    17     ldr sp, =0x34000000              @设置栈
    18     bl main
    19 halt_loop:
    20     b halt_loop
    21     
    22 disable_watch_dog:
    23     @往WATCHDOG寄存器写0即可
    24     mov r1, #0x53000000
    25     mov r2, #0x0
    26     str r2, [r1]
    27     mov pc, lr         @返回
    28     
    29 copy_steppingstone_to_sdram:
    30     @将Steppingstone的4KB数据全部复制到SDRAM中去
    31     @Steppingstone起始地址为0x0000 0000,SDRAM中起始地址为0x3000 0000
    32         
    33     mov r1, #0
    34     ldr r2, =SDRAM_BASE
    35     mov r3, #4*1024
    36 1:
    37     ldr r4, [r1], #4    @从Steppingstone(0x0000 0000)读取4字节的数据,并让源地址加4
    38     str r4, [r2], #4    @将此4字节数据复制到SDRAM中,并让目的地址加4
    39     cmp r1, r3          @判断是否完成:源地址是否等于Steppingstone的末地址?
    40     bne 1b              @若没有复制完,继续
    41     mov pc, lr          @返回
    42     
    43 memsetup:
    44     @设置存储控制器以便使用SDRAM等外设
    45     
    46     mov    r1, #MEM_CTL_BASE    @存储控制器的13个寄存器的开始地址
    47     adr1   r2, mem_cfg_val      @这13个值的起始存储地址
    48     add    r3, r1, #52          @13*4 = 52
    49 1:
    50     ldr r4, [r2], #4            @读取“待设置值”,并让r2加4
    51     str r4, [r1], #4            @将此值写入寄存器,并让r1加4
    52     cmp r1, r3                  @判断是否设置完所有13个寄存器
    53     bne 1b                      @若没有写完,继续
    54     mov pc, lr                  @返回
    55 
    56 
    57 .align 4
    58 mem_cfg_val:
    59     @存储控制器13个寄存器的设置值
    60     .long 0x22011110    @BWSCON
    61     .long 0x00000700    @BANKCON0
    62     .long 0x00000700    @BANKCON1
    63     .long 0x00000700    @BANKCON2
    64     .long 0x00000700    @BANKCON3
    65     .long 0x00000700    @BANKCON4
    66     .long 0x00000700    @BANKCON5
    67     .long 0x00018005    @BANKCON6
    68     .long 0x00018005    @BANKCON7
    69     .long 0x008c07a3    @REFRESH
    70     .long 0x000000b1    @BANKSIZE
    71     .long 0x00000030    @MRSRB6
    72     .long 0x00000030    @MRSRB7
    head.S
        程序是如何通过第15行的“ ldr pc, =on_sdram”指令来完成的
        程序标号“on_sdram”这个地址值在连接程序时被确定为0x3000 0010(这个是SDRAM的
    地址),执行“ldr pc, =on_sdram”后,程序一下子就跳到SDRAM中去了。
        “on_sdram”这个地址值为什么等于0x3000 0010?
        Makefile中连接程序的命令为“arm-linux-ld -Ttext 0x30000000 head.o sdram.o -o
     sdram_elf”,意思就是代码段的起始地址为0x3000 0000,即程序的第一条指令(第12行)的
    连接地址为0x3000 0000,第二条指令(第13行)的连接地址为0x3000 0004,...,第5条指
    令(第17行)的连接地址为0x3000 0010,其程序标号“on_sdram”的值就是0x3000 0010。
        虽然第12~14行指令的连接地址都在SDRAM中,但是由于他们都是位置无关的相对
    跳转指令,所以可以在Steppingstone里执行。
        Makefile如下(注意第4行,“-Ttext 0x30000000”指定了代码段的起始地址):
    1 sdram.bin : head.S leds.c
    2     arm-linux-gcc -c -o head.o head.S
    3     arm-linux-gcc -c -o leds.o leds.c
    4     arm-linux-ld -Ttext 0x30000000 head.o leds.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 clean:
    8     rm -f sdram.dis sdram.bin sdram_elf *.o
    Makefile
        为了更形象地了解本程序,下面用图6.4来演示程序的复制、跳转过程。
    6.2.2 实例测试
        在sdram目录中执行make指令生成可执行文件sdram.bin后,下载到板子上运行。可以
    发现与leds程序相比,LED闪烁得更慢,原因是外部SDRAM的性能比内部SRAM差一些。
        把程序从性能更好的内部SRAM移到外部SDRAM中去,是否多此一举呢?内部SRAM
    只有4KB大小,如果程序大于4KB,那么就不能指望完全利用内部SRAM来运行了,得想
    办法把存储在NAND Flash中的代码复制到SDRAM中去。对于NAND Flash中的前4KB,
    芯片自动把它复制到内部SRAM中,可以很轻松地再把它复制到SDRAM中(实验代码中的
    函数copy_steppingston_to_sdram就有此功能),要复制4KB后面的代码需要使用NAND Flash
    控制器来读取NAND Flash,这就是第8章的内容。
    附:代码:
    链接: https://pan.baidu.com/s/1kV24a9L 密码: tfab
  • 相关阅读:
    pl/sql developer中如何导出oracle数据库结构? 参考文章一
    ORACLE知识点整理之一
    WebService之第一天
    Eclipse中,open declaration;open implementation;open super implementation的区别
    Maven 手动添加 JAR 包到本地仓库
    clipse maven 项目 出现红色叹号 解决方法
    eclipse快捷键设置
    Hibernate3--快速入门--第一天
    C++ 虚函数表解析
    c++ primer复习(二)
  • 原文地址:https://www.cnblogs.com/sz189981/p/7709888.html
Copyright © 2020-2023  润新知