存储控制器SDRAM实验
2013-01-05 22:55
288 查看
今天继续学习韦东山老师的视频教程,这是有关存储控制器以及SDRAM实验的部分。
S3C2440对外引出27根地址线ADDR0-ADDR26,访问范围只有128MB,CPU对外还引出8根片选信号nGCS0-nGCS7,对应BANK0-BANK7,当访问BANKx的地址空间时,nGCSx引脚输出低电平来选中外接设备。
这样每个128MB空间,共8个片选,对应1GB的地址空间。S3C2440是32位CPU,可以使用的地址范围理论达到4GB,除去上面连接外设的1GB空间外,还有一部分是CPU内部寄存器的地址,剩下的地址空间没有使用。
先上源码,head.S文件内容
.equ MEM_CTL_BASE, 0x48000000此处是设置BWSCON寄存器,其地址为0x48000000.
.equ SDRAM_BASE, 0x30000000BANK6和BANK7外接SDRAM,其中BANK6的起始地址为0x30000000
on_sdram:
ldr sp, =0x34000000 @ 设置堆栈,0x34000000为SDRAM中bank7的start address
bl main
此处为什么要将sp设置到0x34000000?
关于_start部分,这里涉及到程序的启动过程,具体过程如下:
1)CPU上电后,硬件自动将NAND前4k的内容复制到SRAM,在手册中SRAM称为steppingstone,其地址为0x00000000.
2)这时,程序需要关闭看门狗,若不关闭系统将不断重启。之后初始化存储管理器
3)存储管理器初始化完成后,将代码从SRAM拷贝到SDRAM中,然后程序继续执行。在这里,由于程序大小只有不到4k,所以可以直接拷贝。若程序大于4k,则需要从NandFlash中拷贝余下内容。
以上三步逐步对应此四段代码
adrl r2, mem_cfg_val @ 13个值的起始存储地址
ADRL 指令将基于PC或基于寄存器的地址值读取到寄存器中。ADRL伪指令比ADR伪指令可以读取更大范围的地址。ADRL伪指令在汇编时被编译器替换成两条指令,即使一条指令可以完成该伪指令的功能。 语法格式 ADRL{cond} register,expr
bne 1b @ 若没有写成,继续
bne里的1b是向后跳转到局部标签1处执行,b表示backward
对应的还有bne 1f(向前跳到局部标签1处执行) 如:
1: ;A
cmp r0, #0
beq 1f ; r0==0那么向前跳转到B处执行
bne 1b ; 否则向后跳转到A处执行
1: ;B
1b,1f里的b和f表示backward和forward,1表示局部标签1
刚意识到这里出现了.align,经查,该指令为:对指令或者数据的地址进行对齐,关于该指令的详细介绍:http://blog.csdn.net/cs1275/article/details/8487468
存储控制器各寄存器值设定的说明:
1)位宽和等待控制寄存器BWSCON
BWSCON中每四位控制一个BANK,最高4位对应BANK7、接下来4位对应BANK6,依次类推。
STx:启动/禁止SDRAM的数据掩码引脚
WSx:是否使用存储器的WAIT信号
DWx:设置对应BANK的位宽,0b00对应8位,0b01对应16位,0b10对应32位,0b11表示保留
比较特殊的是BANK0,它没事ST0和WS0,DW0只读,由硬件跳线决定,0b01表示16位,0b10表示32位,BANK0只支持16、32两种位宽
所以可以确定BWSCON寄存器值为:0x22011110
2)BANK控制寄存器BANKCONx(x为0-5)
这些寄存器用来控制BANK0-BANK5外接设备的访问时序,使用默认0x0700即可
3)BANK控制寄存器BANKCONx(x为6-7)
MT[16:15]:设置BANK外接ROM/SRAM还是SDRAM,00=ROM/SRAM,01=保留,10=保留,11=SDRAM
MT=0b00时,与BANKCON0-BANKCON5类似
MT=0b11时,Trcd[3:2]:RAS to CAS delay,设为推荐值0b01
SCAN[1:0]:SDRAM的列地址数,本开发板使用的SDRAM列地址数为9,0b00=8位,0b01=9位,0b10=10位
所以本开发板,BANKCON6/7均设为0x00018005
4)刷新控制寄存器REFRESH
REFEN[23]: 0=禁止SDRAM的刷新功能,1=开启SDRAM的刷新功能
TREFMD[22]: SDRAM的刷新模式,0=CBR/Auto Refresh,1=SelfRefresh
Trp[21:20]: SDRAM RAS预充电时间 00=2 clocks,01=3clocks,10=4clocks,11=不支持
Tsrc[19:18]: SDRAM半行周期时间 00=4clocks,01=5clocks,10=6clocks,11=7clocks,SDRAM行周期时间Trc=Tsrc+Trp
Refresh Counter[10:0]: SDRAM刷新计数,刷新时间=(2^11+1-refresh_count)/HCLK,在未使用PLL时,HCLK=晶振频率12MHz,刷新周期为7.8125us
refresh_count=2^11+1-12*7.8125=1955
REFRESH=0x008C0000+1955=0x008C07A3
5)BANKSIZE寄存器
BURST_EN[7]: 0=ARM核禁止突发传输,1=ARM核支持突发传输
SCKE_EN[5]: 0=不使用SCKE信号令SDRAM进入省电模式,1=使用SCKE信号令SDRAM进入省电模式
SCLK_EN[4]: 0=时刻发出SCLK信号,1=仅在方位SDRAM期间发出SCLK信号
BK76MAP[2:0]: 设置BANK6/7的大小,0b010=128MB/128MB,0b001=64MB/64MB,0b000=32M/32M,0b111=16M/16M,0b110=8M/8M,0b101=4M/4M,0b100=2M/2M
本开发板外接64MB的SDRAM
则本开发板BANKSIZE设为0xB1
6)SDRAM模式设置寄存器MRSRBx(x为6-7)
CL[6:4]: 0b000=1clocks,0b010=2clocks,0b011=3clocks
本开发板取0b011,所以MRSRB6/7取值为0x30
leds.C文件
Makefile文件
S3C2440对外引出27根地址线ADDR0-ADDR26,访问范围只有128MB,CPU对外还引出8根片选信号nGCS0-nGCS7,对应BANK0-BANK7,当访问BANKx的地址空间时,nGCSx引脚输出低电平来选中外接设备。
这样每个128MB空间,共8个片选,对应1GB的地址空间。S3C2440是32位CPU,可以使用的地址范围理论达到4GB,除去上面连接外设的1GB空间外,还有一部分是CPU内部寄存器的地址,剩下的地址空间没有使用。
先上源码,head.S文件内容
@************************************************************************* @ File:head.S @ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行 @************************************************************************* .equ MEM_CTL_BASE, 0x48000000 .equ SDRAM_BASE, 0x30000000 .text .global _start _start: bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启 bl memsetup @ 设置存储控制器 bl copy_steppingstone_to_sdram @ 复制代码到SDRAM中 ldr pc, =on_sdram @ 跳到SDRAM中继续执行 on_sdram: ldr sp, =0x34000000 @ 设置堆栈,0x34000000为SDRAM中bank7的start address bl main halt_loop: b halt_loop disable_watch_dog: @ 往WATCHDOG寄存器写0即可 mov r1, #0x53000000 mov r2, #0x0 str r2, [r1] mov pc, lr @ 返回 copy_steppingstone_to_sdram: @ 将Steppingstone的4K数据全部复制到SDRAM中去 @ Steppingstone起始地址为0x00000000,SDRAM中起始地址为0x30000000 mov r1, #0 ldr r2, =SDRAM_BASE mov r3, #4*1024 1: ldr r4, [r1],#4 @ 从Steppingstone读取4字节的数据,并让源地址加4 str r4, [r2],#4 @ 将此4字节的数据复制到SDRAM中,并让目地地址加4 cmp r1, r3 @ 判断是否完成:源地址等于Steppingstone的未地址? bne 1b @ 若没有复制完,继续 mov pc, lr @ 返回 memsetup: @ 设置存储控制器以便使用SDRAM等外设 mov r1, #MEM_CTL_BASE @ 存储控制器的13个寄存器的开始地址,0x48000000为BWSCON的起始地址 adrl r2, mem_cfg_val @ 这13个值的起始存储地址 add r3, r1, #52 @ 13*4 = 54 1: ldr r4, [r2], #4 @ 读取设置值,并让r2加4 str r4, [r1], #4 @ 将此值写入寄存器,并让r1加4 cmp r1, r3 @ 判断是否设置完所有13个寄存器 bne 1b @ 若没有写成,继续 mov pc, lr @ 返回 .align 4 mem_cfg_val: @ 存储控制器13个寄存器的设置值 .long 0x22011110 @ 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 0x008C07A3 @ REFRESH//refresh_count=2^11+1-12*7.8125=1955 REFRESH=0x008C0000+1955=0x008C07A3 .long 0x000000B1 @ BANKSIZE .long 0x00000030 @ MRSRB6 .long 0x00000030 @ MRSRB7
.equ MEM_CTL_BASE, 0x48000000此处是设置BWSCON寄存器,其地址为0x48000000.
.equ SDRAM_BASE, 0x30000000BANK6和BANK7外接SDRAM,其中BANK6的起始地址为0x30000000
on_sdram:
ldr sp, =0x34000000 @ 设置堆栈,0x34000000为SDRAM中bank7的start address
bl main
此处为什么要将sp设置到0x34000000?
关于_start部分,这里涉及到程序的启动过程,具体过程如下:
1)CPU上电后,硬件自动将NAND前4k的内容复制到SRAM,在手册中SRAM称为steppingstone,其地址为0x00000000.
2)这时,程序需要关闭看门狗,若不关闭系统将不断重启。之后初始化存储管理器
3)存储管理器初始化完成后,将代码从SRAM拷贝到SDRAM中,然后程序继续执行。在这里,由于程序大小只有不到4k,所以可以直接拷贝。若程序大于4k,则需要从NandFlash中拷贝余下内容。
以上三步逐步对应此四段代码
bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启 bl memsetup @ 设置存储控制器 bl copy_steppingstone_to_sdram @ 复制代码到SDRAM中 ldr pc, =on_sdram @ 跳到SDRAM中继续执行
adrl r2, mem_cfg_val @ 13个值的起始存储地址
ADRL 指令将基于PC或基于寄存器的地址值读取到寄存器中。ADRL伪指令比ADR伪指令可以读取更大范围的地址。ADRL伪指令在汇编时被编译器替换成两条指令,即使一条指令可以完成该伪指令的功能。 语法格式 ADRL{cond} register,expr
bne 1b @ 若没有写成,继续
bne里的1b是向后跳转到局部标签1处执行,b表示backward
对应的还有bne 1f(向前跳到局部标签1处执行) 如:
1: ;A
cmp r0, #0
beq 1f ; r0==0那么向前跳转到B处执行
bne 1b ; 否则向后跳转到A处执行
1: ;B
1b,1f里的b和f表示backward和forward,1表示局部标签1
刚意识到这里出现了.align,经查,该指令为:对指令或者数据的地址进行对齐,关于该指令的详细介绍:http://blog.csdn.net/cs1275/article/details/8487468
存储控制器各寄存器值设定的说明:
1)位宽和等待控制寄存器BWSCON
BWSCON中每四位控制一个BANK,最高4位对应BANK7、接下来4位对应BANK6,依次类推。
STx:启动/禁止SDRAM的数据掩码引脚
WSx:是否使用存储器的WAIT信号
DWx:设置对应BANK的位宽,0b00对应8位,0b01对应16位,0b10对应32位,0b11表示保留
比较特殊的是BANK0,它没事ST0和WS0,DW0只读,由硬件跳线决定,0b01表示16位,0b10表示32位,BANK0只支持16、32两种位宽
所以可以确定BWSCON寄存器值为:0x22011110
2)BANK控制寄存器BANKCONx(x为0-5)
这些寄存器用来控制BANK0-BANK5外接设备的访问时序,使用默认0x0700即可
3)BANK控制寄存器BANKCONx(x为6-7)
MT[16:15]:设置BANK外接ROM/SRAM还是SDRAM,00=ROM/SRAM,01=保留,10=保留,11=SDRAM
MT=0b00时,与BANKCON0-BANKCON5类似
MT=0b11时,Trcd[3:2]:RAS to CAS delay,设为推荐值0b01
SCAN[1:0]:SDRAM的列地址数,本开发板使用的SDRAM列地址数为9,0b00=8位,0b01=9位,0b10=10位
所以本开发板,BANKCON6/7均设为0x00018005
4)刷新控制寄存器REFRESH
REFEN[23]: 0=禁止SDRAM的刷新功能,1=开启SDRAM的刷新功能
TREFMD[22]: SDRAM的刷新模式,0=CBR/Auto Refresh,1=SelfRefresh
Trp[21:20]: SDRAM RAS预充电时间 00=2 clocks,01=3clocks,10=4clocks,11=不支持
Tsrc[19:18]: SDRAM半行周期时间 00=4clocks,01=5clocks,10=6clocks,11=7clocks,SDRAM行周期时间Trc=Tsrc+Trp
Refresh Counter[10:0]: SDRAM刷新计数,刷新时间=(2^11+1-refresh_count)/HCLK,在未使用PLL时,HCLK=晶振频率12MHz,刷新周期为7.8125us
refresh_count=2^11+1-12*7.8125=1955
REFRESH=0x008C0000+1955=0x008C07A3
5)BANKSIZE寄存器
BURST_EN[7]: 0=ARM核禁止突发传输,1=ARM核支持突发传输
SCKE_EN[5]: 0=不使用SCKE信号令SDRAM进入省电模式,1=使用SCKE信号令SDRAM进入省电模式
SCLK_EN[4]: 0=时刻发出SCLK信号,1=仅在方位SDRAM期间发出SCLK信号
BK76MAP[2:0]: 设置BANK6/7的大小,0b010=128MB/128MB,0b001=64MB/64MB,0b000=32M/32M,0b111=16M/16M,0b110=8M/8M,0b101=4M/4M,0b100=2M/2M
本开发板外接64MB的SDRAM
则本开发板BANKSIZE设为0xB1
6)SDRAM模式设置寄存器MRSRBx(x为6-7)
CL[6:4]: 0b000=1clocks,0b010=2clocks,0b011=3clocks
本开发板取0b011,所以MRSRB6/7取值为0x30
leds.C文件
#define GPFCON (*(volatile unsigned long *)0x56000050) #define GPFDAT (*(volatile unsigned long *)0x56000054) #define GPF4_out (1<<(4*2)) #define GPF5_out (1<<(5*2)) #define GPF6_out (1<<(6*2)) void wait(volatile unsigned long dly) { for(; dly > 0; dly--); } int main(void) { unsigned long i = 0; GPFCON = GPF4_out|GPF5_out|GPF6_out; // 将LED1,2,4对应的GPF4/5/6三个引脚设为输出 while(1){ wait(30000); GPFDAT = (~(i<<4)); // 根据i的值,点亮LED1,2,4 if(++i == 8) i = 0; } return 0; }
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.dis clean: rm -f sdram.dis sdram.bin sdram_elf *.oarm-linux-ld -Ttext 0x30000000 head.o leds.o -o sdram_elf中-Ttext0x30000000为代码段的起始地址,此地址也是SDRAM的起始地址,更确切的说也是BANK6的起始地址。
相关文章推荐
- 从源码安装Mysql/Percona 5.5
- 二级域名原理以及程序
- 一根网线内的8根线哪4根是传输数据的,哪四根是防干扰的
- TCP三次握手及原理
- sqlserver索引的原理及索引建立的注意事项小结
- ajax 技术和原理分析
- 令人吃惊的SEO实验-拼音网站实验
- 路由器原理及路由协议
- Oracle数据块实现原理深入解读
- seajs1.3.0源码解析之module依赖有序加载
- 【原创】OpenStack Swift源码分析(三)proxy服务启动
- PHP安全编程:共享主机的源码安全
- [源码]mplayerc播放器源代码
- 网页设计与制作实验内容及时间汇总
- 通过命令查找源码的方法
- NAT实验大全
- 实验案例:Site to Site IPSec ***的配置
- 转载备忘:【实验】【VNC】Linux环境VNC服务安装、配置与使用
- 第三层交换技术的原理
- ISDN实验,有设备的可以试一下!