主机环境:UBUNTU10.04LTS+arm-linux-gcc 2.95.3
开发板环境:EdukitIII实验箱+s3c2410子板
问题描述:程序首先烧写到NAND FLASH中,启动CPU时,CPU会通过内部的硬件把NAND FLASH开始的4KB数据复制到成为“Steppingstone”的4KB的内部RAM中(起始地址为0),然后跳到地址0开始执行。本程序先使用汇编程序设置好存储控制器,使外接的SDRAM能够使用,然后把程序本身从Steppingstone复制到SDRAM中,最后跳到SDRAM中执行。该程序功能实现了循环点亮LED灯。
【1.硬件原理】
EDUKITIII实验箱的外设如NOR FLASH,IDE接口、网卡、CPLD、SDRAM等都是通过存储控制器与S3C2410连接的。本程序以设置SDRAM为例,来学习如何使用存储控制器。S3C2410存储控制器的地址空间分布如图1所示
图1 S3C2410存储控制器的地址空间分布图
可以看到,BANK6,7可以连接SDRAM,EDUKITIII实验箱是把SDRAM连接到BANK6,SDRAM型号为HY57V561620,共2片(位于S3C2410子板上),所以SDRAM容量一共为4LBank*4M*16bit*2=64MByte(1片HY57V561620共有4个逻辑bank即LBank,每个逻辑bank有13条行地址线,9条列地址线,共22条地址线,每个LBank可寻址范围为4M,每个存储单元位数为16位),硬件连接如图2所示
图2 S3C2410子板上SDRAM连接图
由图1可知,SDRAM的起始地址为0x30000000,容量为64MB,所以结束地址为0x30000000+64M=0x33FFFFFF。存储控制寄存器一共有13个,存储控制寄存器的地址从0x48000000到0x48000030,下面分别讨论这些存储控制寄存器的使用方法:
1.BWSCON,位宽和等待控制寄存器,地址和各位含义如图3
图3 BWSCON地址和各位含义
STx:启动/禁止SDRAM的数据掩码引脚,对于SDRAM,此位为1;对于SRAM,此位为0
WSx:是否使用存储器的WAIT信号,一般设为0
DWx:设置相应BANK的位宽,00对应8位,01对应16位,10对应32位,对于S3C2410,一共使用了2片SDRAM,每片16位,所以两片共同构成的位宽为32为,因此DW6=10。其余BANK没有使用,所以DW1-5可以设置为00。对于EDUKITIII,根据上述讨论,BWSCON寄存器的值为0x22011110
2.BANKCONx,x=0~5,BANK控制寄存器,地址及其各位含义如图4
图4 BANKCONx,x=0~5地址及其各位含义
这几个寄存器用来控制BANK0-BANK5外界设备的访问时序,使用默认值0x0700
3.BANKCONx,x=6~7,BANK控制寄存器,地址及其各位含义如图5
图5 BANKCONx,x=6~7,地址及其各位含义如图5
MT[16:15],设置该BANK外接的是ROM/SRAM(00),还是SDRAM(11)。
当MT=0时,此寄存器的使用与BANCON0-5类似
当MT=11时,
Trcd[3:2],设为推荐值01
SCAN[1:0],SDRAM的列地址数,00=8位,01=9位,10=10位,通过查询HY57V561620硬件手册中的引脚定义,如图6所示
图6 HY57V561620引脚定义
可以看到,Column Address:CA0-CA8,所以SDRAM的列地址为9,所以SCAN[1:0]=01,因此EDUKITIII实验箱中BANK6/7均设置为0x00018005
4.REFRESH,刷新控制器,地址及其各位含义如图7所示
图7 REFRESH地址及其各位含义
REFEN[23]:0表示禁止SDRAM刷新功能,1表示开启SDRAM刷新功能,该为应设置为1
TREFMD[22]:SDRAM的刷新模式,0为auto refresh,1为self refresh,该位设置为0
Trp[21:30],设为0
Tsrc[19:18],设为默认值11
Refresh Counter[10:0],该值的计算方法为:2^11+1-SDRAM时钟频率(MHz)*SDRAM刷新周期(us)。SDRAM刷新周期查找HY57V561620硬件手册得到,如图8所示
图8 HY57V561620特性
可以看到,“8192refresh cycles/64ms”所以SDRAM刷新周期=64ms/8192=7.8125us。EDUKITIII实验箱一共有2个晶振,电路连接如图9(查询ARM9基础实验教程)
图9 s3c2410晶振
这两个晶振都在s3c2410子板上,其中X101晶振频率为32.768kHz,仅用于RTC,X102晶振频率为12MHz,用于系统时钟,SDRAM的时钟频率HCLK,是X102经过PLL后的频率,本程序中未使用PLL,SDRAM的时钟频率就等于X102晶振频率,所以,Refresh Counter[10:0]=2^11+1-12*7.8125=1955,未使用PLL时,PEFRESH=0x008C0000+1955=0x008C07A3
5.BANKSIZE寄存器,地址及其各位含义如图10所示
图10 BANKSIZE地址及其各位含义
BURST_EN[7]:0=ARM核禁止突发传输,1=ARM核支持突发传输,本程序设置为1
SCKE_EN[5]:0=不使用SCKE信号令SDRAM进入省电模式,1=使用SCKE信号令SDRAM进入省电模式,设置为1
SLCK_EN[4]:0=总是发出SCLK信号,1=仅在访问SDRAM期间发出SCLK信号,设置为1
BK76MAP[2:0],设置BANK6/7的大小,本实验箱SDRAM大小为64MB,故设置为001,所以该寄存器的值为0xB1
6.MRSRBx,x=6~7,SDRAM模式设置寄存器,地址及其各位含义如图11所示
图11 MRSRBx,x=6~7,地址及其各位含义
只有CL[6:4]能修改,推荐设置为011,其余各位有固定的值,所以MRSRB6/7的值为0x30
以上讨论了各个寄存器应该取的值,利用这些值来对SDRAM进行设置。该程序包含两个文件head.S和leds.c,head.S负责初始化SDRAM,并调用leds.c,leds.c负责轮流点亮LED灯
【2.程序实现】
@************************************************************************* @Name: head.S @Desc: 设置SDRAM,把程序从steppingstone复制到SDRAM,然后在SDRAM中运行程序 @Parameter: @Return: @Author: yoyoba(stuyou@126.com) @Date: 2011-5-8 @Modify: 2011-5-8 @*************************************************************************
.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 @ 设置堆栈,为调用C程序准备堆栈 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个寄存器的开始地址 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 .long 0x000000B1 @ BANKSIZE .long 0x00000030 @ MRSRB6 .long 0x00000030 @ MRSRB7 .end
|
leds.c程序如下:
****************************************************************************** *Name: leds.c *Desc: led灯全灭,然后依次点亮4个LED灯,最后把4个LED灯全部点亮 *Parameter: *Return: *Author: yoyoba(stuyou@126.com) *Date: 2011-5-8 *Modify: 2010-5-8 ********************************************************************************/
#define GPFCON (*(volatile unsigned long *)0x56000050) //GPFCON地址为0x56000050
#define GPFDAT (*(volatile unsigned long *)0x56000054) //GPFDAT地址为0x56000054
void wait(unsigned long dly) { for(; dly > 0; dly--); }
int Main() //注意Main函数名的写法
{ GPFCON=0x00005500; //GPFCON写入0x00005500,即GFP4-7设置为输出功能 while(1) { wait(30000); GPFDAT=0x000000f0; //GPFDAT写入0x000000f0,即GPFDAT[7:4]=1111,4个LED灯全灭
wait(30000); GPFDAT=0x000000e0; //GPFDAT写入0x000000e0,即GPFDAT[7:4]=1110,LED4点亮 wait(30000); GPFDAT=0x000000d0; //GPFDAT写入0x000000d0,即GPFDAT[7:4]=1101,LED5点亮
wait(30000); GPFDAT=0x000000b0; //GPFDAT写入0x000000b0,即GPFDAT[7:4]=1011,LED6点亮
wait(30000); GPFDAT=0x00000070; //GPFDAT写入0x00000070,即GPFDAT[7:4]=0111,LED7点亮
wait(30000); GPFDAT=0x00000000; //GPFDAT写入0x00000000,即GPFDAT[7:4]=0000,4个LED灯全亮
} 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 *.o
|
通过配置文件,可以看到,该程序被链接到0x30000000,正好为SDRAM的起始地址。该程序具体的地址关系参考《嵌入式LINUX应用开发完全手册》韦东山。
在LINUX下输入make,生成sdram.bin,使用EDUKITIII实验箱提供的FLASH编程工具把sdram.bin烧到试验箱的NAND FLASH中(注意:SW104短接),NAND FLASH配置文件可以使用NAND FLASH烧写VIVI的配置文件,FLASH扇区设置为1-2(NAND FLASH中一个扇区为64KB,sdram.bin文件只有1K,因此使用2个FLASH扇区足够了)。烧写完成,重新启动开发板,观察LED被点亮的情况。
如果在WindowsXP+EmbestIDE环境中运行该程序,而不是直接烧写到NAND FLASH,LED灯点亮情况好像不对,似乎没有从SRAM拷贝到SDRAM中,因为LED灯闪烁速度比较快,不知道什么原因。
阅读(4336) | 评论(0) | 转发(1) |