Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1239856
  • 博文数量: 124
  • 博客积分: 5772
  • 博客等级: 大校
  • 技术积分: 1647
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-27 10:39
文章分类

全部博文(124)

文章存档

2020年(1)

2019年(1)

2018年(5)

2017年(2)

2016年(17)

2015年(3)

2014年(7)

2013年(11)

2012年(13)

2011年(30)

2010年(34)

分类: 嵌入式

2011-05-08 18:29:30

主机环境: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灯闪烁速度比较快,不知道什么原因。
阅读(4030) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~