zoukankan      html  css  js  c++  java
  • 二、存储管理器--SDRAM

    2.1 硬件结构

    2.1.1 硬件框图

      CPU 通过存储管理器来读取 SDRAM 网卡 等外部设备,CPU不管外部设备是怎么样的,只是读存储管理器中的地址

      

      CPU从0x30000000地址读取数据。

    1 mov R1, #0x30000000
    2 ldr    R0, [R1]

      存储管理器会根据配置信息来访问外部的设备。

      配置信息包括:

      • 外部设备的地址
      • 外部设备的数据,数据宽度是多少位(8位/16位/32位)
      • 时钟信号频率
      • 外部设备相关的特性,SDRAM包括行地址,列地址和bank

       SDRAM的存储结构逻辑如下:

      

      SDRAM内部为一个存储阵列。读写原理为,先指定一个行(ROW),再指定一个列(COLUMN),就可以找到所需要的内容。

      一个存储阵列称为一个BANK。

    2.SDRAM

    2.1 硬件结构

      两个16位的芯片组成32位位宽。

      

      

      

                

      具体参数可以查看SDRAM的芯片手册。

      SDRAM 需要知道的信息:

    • 列地址和行地址的数目:由芯片手册可以知道,行地址为13位,列地址为9位
    • 刷新周期:刷新周期为  64/8192
    • bank 地址
    • 位宽:由原理图可以知道,位宽为32  

       

      由芯片手册可以知道,行地址为13位,列地址为9位

      

      刷新周期为  64/8192

      2440 芯片手册上面写了位宽与PIN脚之间的关系,如下图:

      

      若是8位位宽,只接A0 A1.......,若是16位位宽,则为A1 A2........,若是32位位宽,则为A2 A3........;这些引脚接到SDRAM上都是从 SDRAM的A0开始,32位,即LADDR2接到A0上开始

    2.2 编程

      要想使用SDRAM,需要进行以下几步:

      1)配置存储管理器

      2)将SDRAM 的信息写入到寄存器中

      对于存储管理器,涉及到13个寄存器,具体看芯片手册

    • 程序设计思路:
      • 程序烧写进NAND Flash 中后,NAND Flash 中的前4K会拷贝到CPU的SRAM中去,SRAM的起始地址为0x00000000,程序从这里开始执行,SDRAM中的4K内容称为steppingstone
      • 然后在SRAM中执行的时候,会将SRAM中的程序拷贝进SDRAM中去,然后继续在SDRAM中执行
      • 若是程序较大,则前4K执行完后,会将NAND Flash 的中的所有代码一次性拷贝进SDRAM中执行,此章不涉及

      链接地址:运行时,程序应该位于哪里  

       代码 head.S

     1 @******************************************************************************
     2 @ File:head.S
     3 @ 功能:SDRAM 进行初始化
     4 @******************************************************************************       
     5 
     6 @ .equ 命令用于把常量值设置为可以在文本段中使用的符号
     7 @ 经过设置之后,数据符号值是不能在 程序中改动的。
     8 @  .equ 命令可以出现在数据段中任何位置,但是出于好的代码习惯,最好是在定义其他数据之前或之后集中定义所有数据符号
     9 .equ        MEM_CTL_BASE,       0x48000000          @ 设置内存控制器的基地址,寄存器的起始地址
    10 .equ        SDRAM_BASE,         0x30000000          @ 设置SDRAM的基地址,按接在2440的哪个片选上看
    11 
    12 .text
    13 .global _start
    14 _start:
    15     bl      disable_watch_dog               @ 关闭WATCHDOG,否则CPU会不断重启
    16     bl      memsetup                        @ 设置存储控制器
    17     bl      copy_steppingstone_to_sdram     @ 复制代码到SDRAM中
    18     ldr     pc, =on_sdram                   @ 跳到SDRAM中继续执行
    19 
    20 on_sdram:
    21     ldr     sp, =0x34000000                 @ 设置堆栈,SDRAM 总共64M,栈指针指向SDRAM的最上端
    22     bl      main
    23 
    24 halt_loop:
    25     b       halt_loop
    26 
    27 @ 关闭看门狗
    28 disable_watch_dog:
    29     ldr     r0, =0x53000000                 @ WATCHDOG寄存器地址
    30     mov     r1, #0x0                     
    31     str     r1, [r0]                        @ 写入0,禁止WATCHDOG,否则CPU会不断重启
    32     mov     pc, lr                          @ 返回
    33 
    34 @ 设置存储控制器,以便使用SDRAM等外设
    35 memsetup:
    36     mov     r1, #MEM_CTL_BASE               @ 存储控制器的13个寄存器的开始地址
    37     adrl    r2, mem_cfg_val                 @ 这13个值的起始存储地址
    38     add     r3, r1, #52                     @ 13*4 = 54
    39 1:  
    40     ldr     r4, [r2], #4                    @ 读取设置值,并让r2加4
    41     str     r4, [r1], #4                    @ 将此值写入寄存器,并让r1加4
    42     cmp     r1, r3                          @ 判断是否设置完所有13个寄存器
    43     bne     1b                              @ 若没有写成,继续
    44     mov     pc, lr                          @ 返回
    45 
    46 
    47 copy_steppingstone_to_sdram:
    48     @ 将Steppingstone的4K数据全部复制到SDRAM中去
    49     @ Steppingstone起始地址为0x00000000,SDRAM中起始地址为0x30000000
    50             
    51     mov     r1, #0                          @ 片内内存的起始地址为 0
    52     ldr     r2, =SDRAM_BASE                 @ SDRAM 中的基地址
    53     mov     r3, #4*1024                     @ 拷贝的大小为 4K
    54 1:  
    55     ldr     r4, [r1],#4                     @ 从Steppingstone读取4字节的数据,并让源地址加4
    56     str     r4, [r2],#4                     @ 将此4字节的数据复制到SDRAM中,并让目地地址加4
    57     cmp     r1, r3                          @ 判断是否完成:源地址等于Steppingstone的末地址?
    58     bne     1b                              @ 若没有复制完,继续
    59     mov     pc,     lr                      @ 返回
    60 
    61 
    62 .align 4
    63 mem_cfg_val:
    64     @ 存储控制器13个寄存器的设置值
    65     .long   0x22011110      @ BWSCON
    66     .long   0x00000700      @ BANKCON0
    67     .long   0x00000700      @ BANKCON1
    68     .long   0x00000700      @ BANKCON2
    69     .long   0x00000700      @ BANKCON3  
    70     .long   0x00000700      @ BANKCON4
    71     .long   0x00000700      @ BANKCON5
    72     .long   0x00018005      @ BANKCON6
    73     .long   0x00018005      @ BANKCON7
    74     .long   0x008C07A3      @ REFRESH
    75     .long   0x000000B1      @ BANKSIZE
    76     .long   0x00000030      @ MRSRB6
    77     .long   0x00000030      @ MRSRB7

      sdram.c

     1 /* GPF */
     2 #define GPFCON      (*(volatile unsigned long *)0x56000050)
     3 #define GPFDAT      (*(volatile unsigned long *)0x56000054)
     4 /* GPG */
     5 #define GPGCON      (*(volatile unsigned long *)0x56000060)
     6 #define GPGDAT      (*(volatile unsigned long *)0x56000064)
     7 
     8 /* GPF */
     9 #define GPF4_out    (1<<(4*2))
    10 #define GPF5_out    (1<<(5*2))
    11 #define GPF6_out    (1<<(6*2))
    12 
    13 #define GPF4_msk    (3<<(4*2))
    14 #define GPF5_msk    (3<<(5*2))
    15 #define GPF6_msk    (3<<(6*2))
    16 
    17 /*
    18  * S2,S3,S4对应GPF0、GPF2、GPG3
    19  */
    20 #define GPF0_in     (0<<(0*2))
    21 #define GPF2_in     (0<<(2*2))
    22 #define GPG3_in     (0<<(3*2))
    23 
    24 #define GPF0_msk    (3<<(0*2))
    25 #define GPF2_msk    (3<<(2*2))
    26 #define GPG3_msk    (3<<(3*2))
    27 
    28 int main()
    29 {   
    30     unsigned long dwDat;
    31 
    32     // LED1,LED2,LED4对应的3根引脚设为输出
    33     GPFCON &= ~(GPF4_msk | GPF5_msk | GPF6_msk);
    34     GPFCON |= GPF4_out | GPF5_out | GPF6_out;
    35 
    36     // S2,S3对应的2根引脚设为输入
    37     GPFCON &= ~(GPF0_msk | GPF2_msk);
    38     GPFCON |= GPF0_in | GPF2_in;
    39 
    40     // S4对应的引脚设为输入
    41     GPGCON &= ~GPG3_msk;
    42     GPGCON |= GPG3_in;
    43 
    44     while(1)
    45     {
    46         //若Kn为0(表示按下),则令LEDn为0(表示点亮)
    47         dwDat = GPFDAT;             // 读取GPF管脚电平状态
    48 
    49         if (dwDat & (1<<0))        // S2没有按下
    50             GPFDAT |= (1<<4);       // LED1熄灭
    51         else
    52             GPFDAT &= ~(1<<4);      // LED1点亮
    53 
    54         if (dwDat & (1<<2))         // S3没有按下
    55             GPFDAT |= (1<<5);       // LED2熄灭
    56         else
    57             GPFDAT &= ~(1<<5);      // LED2点亮
    58 
    59         dwDat = GPGDAT;             // 读取GPG管脚电平状态
    60 
    61         if (dwDat & (1<<3))         // S4没有按下
    62             GPFDAT |= (1<<6);       // LED3熄灭
    63         else
    64             GPFDAT &= ~(1<<6);      // LED3点亮
    65     }
    66     return 0;
    67 }

      Makefile

    1 led_on.bin : head.S  sdram.c
    2     arm-linux-gcc -g -c -o head.o head.S
    3     arm-linux-gcc -g -c -o sdram.o sdram.c
    4     arm-linux-ld -Ttext 0x30000000 -g head.o sdram.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

      

  • 相关阅读:
    Java读取resource文件/路径的几种方式
    log4j:WARN Please initialize the log4j system properly解决办法
    SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
    log4j.properties配置详解与实例-全部测试通过[转]
    testNG中dataprovider使用的两种方式
    远程仓库获取最新代码合并到本地分支
    git 冲突解决办法
    【转】JsonPath教程
    selenium及webdriver的原理【转】
    [转]Redis 数据结构简介
  • 原文地址:https://www.cnblogs.com/kele-dad/p/6879959.html
Copyright © 2011-2022 走看看