三、mini2440裸机程序之存储控制器实验

1.管脚介绍


        1)与SDRAM相关管脚:

 

 

        2)以上接法都可由S3C2440数据手册里寻找到:


红圈里面表示我当前使用开发板外接SDRAM的情况:其中(4Mx8x4B)X2表示使用了2片32M的SDRAM组成64M的内存,其中4 banks/chip,4M/bank,

每一片的数据总线16-bit,但是通过使用两片扩展成x32总线宽度.bank的选择通过地址总线的A[25:24]来选择,以上的选择对应了以下的连线方式:

 

关于地址总线的连接,因为SDRAM使用了32-bit数据总线,也就是SDRAM的存储单元为4个字节,但是S3C2440的存储单元是1个字节,

所以通过A0管脚接到S3C2440的地址总线管脚A2上,以下依次接下去的方式来使S3C2440每次访问内存时都能对齐在4字节上。



2.相关寄存器(由以上开发板的原理图我们可以知道,我们的SDRAM是挂在Bank6上的):

     

         1)BWSCON相关Pin:


:

如果是SRAM的话就使用UB/LB,否则不使用.

是否选择WAIT功能:选择否

数据总线宽度:选择32-bit

 我的最终配置是:BWSCON[27:24] = 0 0 10B

 

        2)BANKCON6相关Pin: 


  :其它Pin用于内存为ROM orSRAM.

  MT选择SDRAM,Trcd选择2 clocks就可以了(在下面选择Trp和Tsrc时一起讨论),SCAN是9-bit

 我的最终配置是:BANKCON6[16:15]=11B;BANKCON6[3:0]=0001B

 

        3)REFRESH相关Pin:


:

REFEN使能;

TREFMD选择全刷新,半刷新一般是用在系统休眠时;

Trcd,Trp和Trc都必须满足以下图示条件(图示来自相应SDRAM芯片手册):

        其中的上限值没有定死,Trcd和Trp必须大于20ns,Trc最好要大于70ns。HCLK为12MHz表明了一个时钟周期为83ns/clock,

所以在没有使用PLL时,Trcd,Trp和Trc怎么选都是满足要求的。

所以Trp选择2 clocks,Tsrc选择4 clocks。

需要注意的是:在使用了PLL之后要重新设置,因为条件可能不满足了

 

 

Refresh Counter(刷新计数器)涉及到HCLK,可以看以下图示


        从上图可以看出在没有设置PLL时,FCLK逻辑电平是直接由XTlpll(晶振频率12MHz)决定的;在默认情况下HCLK的时钟频率

是跟FCLK一样,而SDRAM使用的时钟频率正是由HCLK提供

        那么Refresh period =(2^11-refresh_count+1)/HCLK   (从refresh_count开始计数到溢出时就刷新一次),从下面我对SDRAM对

应型号的datasheet里面的截图可以看出64ms内刷新8192次,这样Refreshperiod = (64ms/8192*1000)us;再由

Refresh count = 2^11+1-12*Refresh period = 0x7A3.

 

我的最终配置是:REFRESH[23:18]= 1 0 00 00B;REFRESH[10:0] = 0x7A3

 

         4)BANKSIZE相关Pin:


注:

BUTST_EN:选择使能突发操作

SCKE_EN:   选择使能通过SCKE信号来使SDRAM进入省电模式

SCLK_EN:   选择推荐选项(在访问SDRAM期间SCLK才有效,没访问时为"L"电平)

DK76MAP:   选择64MB/64MB

 

我的最终配置为:BANKSIZE[7:0]= 1 0 1 1 0 001 B

 

        5)MRSRB6相关Pin:


这个寄存器里只有CL可以选择的,其它都是Fixed。

具体CL可选哪个,根据对应型号的SDRAM数据手册如下图:


可以看到我们使用的SDRAM的nCASLatency只支持2和3,而且各个版本都可以选择3.

 

我的最终配置为:MRSRB6[11:0]= 0 00 011 0 000 B

 

 

3.程序流程图设计:

                                                 

 

 

4.程序设计:

 

                     

  1)Makefile

memory.bin : memory.S led_display.c
    arm-linux-gcc -c -o memory.o memory.S
    arm-linux-gcc -c -o led_display.o led_display.c
    arm-linux-ld -Ttext 0x30000000 memory.o led_display.o -o memory_elf
    arm-linux-objcopy -O binary -S memory_elf memory.bin
    arm-linux-objdump -D -m arm memory_elf > memory.dis
clean:
    rm -f memory.dis memory.bin memory_elf *.o

 

   2)memory.S

 

 



#define    WTCON        0x53000000

#define    BWSCON        0x48000000
#define    BANKCON6    0x4800001C
#define    REFRESH        0x48000024
#define    BANKSIZE    0x48000028
#define    MRSRB6        0x4800002C


.Text
.global    _start

_start:

    /******关闭看门狗**********/
    ldr    r0 , =WTCON
    mov    r1 , #0x0
    str    r1 , [r0]
    /*****END关闭看门狗********/


    
    /***调用初始化内存子程序***/
    bl    memory_init
    /**********END***********/



    /*拷贝前4k内容到内存子程序*/
    bl    copy_bootsram_to_sdram    
    /************END**********/


    /*PC跳转到内存后继指令开始处*/
    ldr    pc , =begin_sdram



begin_sdram:
    @设置堆栈指针
    ldr    sp , =0x34000000



    /**********让灯全亮************
    #define    GPBCON        0x56000010
    #define    GPBDAT        0x56000014
    @把LED1-4管脚置为输出
    ldr    r0 , =GPBCON
    ldr    r1 , [r0]        @把GPBCON里的内容加载到r1里
    ldr    r2 , =(0xFF<<10)
    bic    r1 , r1 ,r2    @操作数取反码或上r1,用于清零工作
    ldr    r2 , =(0x55<<10)
    orr    r1 , r1 , r2
    str    r1 , [r0]    
    @灯全亮
    ldr    r0 , =GPBDAT
    ldr    r1 , [r0]    
    ldr    r2 , =(0x0F<<5)
    bic    r1 , r1 , r2
    str    r1 , [r0]
    ***********END***************/



    @跳转到main函数
    bl    main

LOOP:
    b    LOOP


memory_init:
/*******内存初始化子程序*********/

    @BWSCON[27:24] = 0 0 10B
    ldr    r0 , =BWSCON
    ldr    r1 , [r0]
    ldr    r2 , =(0x0F<<24)
    bic    r1 , r1 , r2
    ldr    r2 , =(0x02<<24)
    orr    r1 , r1 , r2
    str    r1 , [r0]    

    @BANKCON6[16:15]=11B;BANKCON6[3:0]=00 01B
    ldr    r0 , =BANKCON6
    ldr    r1 , [r0]
    ldr    r2 , =(0x03<<15)
    bic    r1 , r1 , r2
    orr    r1 , r1 , r2
    ldr    r2 , =0x0F
    bic    r1 , r1 , r2
    ldr    r2 , = 0x01
    orr    r1 , r1 , r2
    str    r1 , [r0]

    @REFRESH[23:18] = 1 0 00 00B;REFRESH[10:0] = 0x7A3
    ldr    r0 , =REFRESH
    ldr    r1 , [r0]
    ldr    r2 , =(0x3F<<18)
    bic    r1 , r1 , r2
    ldr    r2 , =(0x20<<18)
    orr    r1 , r1 , r2
    ldr    r2 , =0x7FF
    bic    r1 , r1 , r2
    ldr    r2 , = 0x7A3
    orr    r1 , r1 , r2
    str    r1 , [r0]

    @BANKSIZE[7:0] = 1 0 1 1 0 001 B
    ldr    r0 , =BANKSIZE
    ldr    r1 , [r0]
    ldr    r2 , =0xFF
    bic    r1 , r1 , r2
    ldr    r2 , =0xB1
    orr    r1 , r1 , r2
    str    r1 , [r0]    

    @MRSRB6[11:0] = 0 00 011 0 000 B
    ldr    r0 , =MRSRB6
    ldr    r1 , [r0]
    ldr    r2 , =0x3FF
    bic    r1 , r1 , r2
    ldr    r2 , =0x030
    orr    r1 , r1 , r2
    str    r1 , [r0]    

    mov    pc , lr        @函数返回
/******END内存初始化子程序*******/




copy_bootsram_to_sdram:
    /******拷贝前4K代码到sdram*******/
    mov    r0 , #0x0
    ldr    r1 , =0x30000000
    ldr    r2 , =4*1024
copy:
    ldr    r3 , [r0] , #4
    str    r3 , [r1] , #4
    cmp    r0 , r2
    bne    copy
    mov    pc , lr
    /*****END拷贝前4K代码到sdram*****/




 

   3)led_display.c


#define    GPBCON    (*(volatile unsigned long *)0x56000010)
#define    GPBDAT    (*(volatile unsigned long *)0x56000014)

void  delay(int dly)
{
    for(; dly > 0; dly--);
}
int main()
{
    GPBCON &= ~(0xFF<<10);
    GPBCON |= (0x55<<10);    //把GPB5~8都置为输出功能
    while(1){
    
        delay(50000);
        GPBDAT |= (0x0F<<5);    //LED灯灭
        delay(50000);
        GPBDAT &= ~(0x0F<<5);    //LED灯亮
    }
}


 

 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值