(1)、CPU操作外设的基本原理图
由图可知,CPU要想访问一个外设,是要通过存储管理器来实现的。本篇中,主要是通过操作SDRAM来实现存储管理器的学习。
(2)、配置原理和步骤
访问一个芯片需要的配置信息:
1、 片选信号
2、 地址线
3、 数据线,即使数据宽度
4、 时钟频率
5、 芯片相关的东西:对SDRAM来说
a) 行地址有多少位
b) 列地址有多少位
c) BANK有多少位
操作一个SDRAM的步骤就是:
a、 首先通过片选信号选中SDRAM
b、 然后确定在哪一个BNAK里面存储
c、 然后发出行地址,在发出列地址,确定在SDRAM的数据位置
(3)、硬件相关信息
SDRAM原理图
SDRAM芯片手册
2440的存储控制器手册
通过查看原理图和数据手册可知SDRAM的配置数据如下:
a、 数据位宽32位,因为用到了2片SDRAM,一片是16位。
b、 行13位、列9位,由图SDRAM芯片手册可知。
c、 刷新周期 64ms/8192
d、 BANK有4位,由图2440的存储控制器手册可知,BANK地址是A[25:24],。
查看2440手册可知,SDRAM的硬件连接分配如下图
SDRAM的地址是从ADDR2~ADDR14,而没有ADDR0和ADDR1,因为我们的内存访问是以32位访问的,每次读写都是4个字节,这就导致了地址ADDR0和ADDR1代表的地址0、1、2和3是无法被单个读取的,每次都是把地址0、1、2和3的数据以一个32位的数据读出,所以忽略地址线ADDR0和ADDR1,地址线为ADDR2~ADDR14。
2440有8个bank,可以接8个类似SDRAM的外设。而我们的SDRAM接在了BANK6上面,起始地址是0x30000000,我们的SDRAM是64MB,所以访问空间是0x30000000~0x33FFFFFF。
(4)、程序代码
1 .equ MEM_CTL_BASE, 0x48000000 @因为存储控制器的起始地址是0x48000000 2 .equ SDRAM_BASE, 0x30000000 @如上SDRAM的起始访问地址是0x30000000 3 .text 4 .global _start 5 _start: 6 bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启 7 bl memsetup @ 设置存储控制器 8 bl copy_steppingstone_to_sdram @ 复制代码到SDRAM中 9 ldr pc, =on_sdram @ 跳到SDRAM中继续执行 10 on_sdram: 11 ldr sp, =0x34000000 @ 设置堆栈,因为程序被拷贝到SDRAM里面运行,栈空间设置为SDRAM的前4k内容。 12 bl main 13 halt_loop: 14 b halt_loop 15 16 disable_watch_dog: 17 @ 往WATCHDOG寄存器写0即可 18 mov r1, #0x53000000 19 mov r2, #0x0 20 str r2, [r1] 21 mov pc, lr @ 返回 22 23 copy_steppingstone_to_sdram: 24 @ 将Steppingstone的4K数据全部复制到SDRAM中去 25 @ Steppingstone起始地址为0x00000000,SDRAM中起始地址为0x30000000 26 27 mov r1, #0 28 ldr r2, =SDRAM_BASE 29 mov r3, #4*1024 30 1: 31 ldr r4, [r1],#4 @ 从Steppingstone读取4字节的数据,并让源地址加4 32 str r4, [r2],#4 @ 将此4字节的数据复制到SDRAM中,并让目地地址加4 33 cmp r1, r3 @ 判断是否完成:源地址等于Steppingstone的未地址? 34 bne 1b @ 若没有复制完,继续 35 mov pc, lr @ 返回 36 37 memsetup: 38 @ 设置存储控制器以便使用SDRAM等外设 39 40 mov r1, #MEM_CTL_BASE @ 存储控制器的13个寄存器的开始地址 41 adrl r2, mem_cfg_val @ 这13个值的起始存储地址 42 add r3, r1, #52 @ 13*4 = 54 43 1: 44 ldr r4, [r2], #4 @ 读取设置值,并让r2加4 45 str r4, [r1], #4 @ 将此值写入寄存器,并让r1加4 46 cmp r1, r3 @ 判断是否设置完所有13个寄存器 47 bne 1b @ 若没有写成,继续 48 mov pc, lr @ 返回 49 50 51 .align 4 52 mem_cfg_val: 53 @ 存储控制器13个寄存器的设置值 54 .long 0x22011110 @ BWSCON 55 .long 0x00000700 @ BANKCON0 56 .long 0x00000700 @ BANKCON1 57 .long 0x00000700 @ BANKCON2 58 .long 0x00000700 @ BANKCON3 59 .long 0x00000700 @ BANKCON4 60 .long 0x00000700 @ BANKCON5 61 .long 0x00018005 @ BANKCON6 62 .long 0x00018005 @ BANKCON7 63 .long 0x008C07A3 @ REFRESH 64 .long 0x000000B1 @ BANKSIZE 65 .long 0x00000030 @ MRSRB6 66 .long 0x00000030 @ MRSRB7
程序和之前主要的区别是加入了复制代码到SDRAM的程序。
因为程序最终是在SDRAM里面执行,所以在Makefile里面我们把代码起始段地址设置为了0x30000000.
1 arm-linux-ld -Ttext 0x30000000 head.o leds.o -o sdram_elf
程序具体的执行流程如下:
首先程序从NANDFlash启动,并把前4K的内容拷贝包片内RAM中去,然后程序执行,首先关闭看门狗,设置SDRAM相关寄存器,初始化SDRAM。
SDRAM初始化完成以后,开始执行copy_steppingstone_to_sdram程序,这个程序是把我们的程序拷贝到SDRAM里面去执行,拷贝完成后程序的起始地址变成0x3000000。并设置4k的栈空间。