2、存儲管理器--SDRAM

2.1 硬件結構

2.1.1 硬件框圖

  CPU 經過存儲管理器來讀取 SDRAM 網卡 等外部設備,CPU無論外部設備是怎麼樣的,只是讀存儲管理器中的地址linux

  

  CPU從0x30000000地址讀取數據。編程

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

  存儲管理器會根據配置信息來訪問外部的設備。oop

  配置信息包括:spa

    • 外部設備的地址
    • 外部設備的數據,數據寬度是多少位(8位/16位/32位)
    • 時鐘信號頻率
    • 外部設備相關的特性,SDRAM包括行地址,列地址和bank

   SDRAM的存儲結構邏輯以下:設計

  

  SDRAM內部爲一個存儲陣列。讀寫原理爲,先指定一個行(ROW),再指定一個列(COLUMN),就能夠找到所須要的內容。指針

  一個存儲陣列稱爲一個BANK。code

2.SDRAM

2.1 硬件結構

  兩個16位的芯片組成32位位寬。blog

  

  

  

            

  具體參數能夠查看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、GPF二、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
相關文章
相關標籤/搜索