(三)内存 SDRAM 驱动实验 (杨铸 130 页)(勉强能懂个大概)

SDRAM 芯片讲解:

 

地址: 行地址 (A0-A12) 列地址 (A0-A8)    片选信号(BA0 BA1)(L-BANK)(因为SDRAM有 4片)

两片SDRAM 连线唯一区别在 UDQM LDQM 

DQM0 ---片1 LDQM

DQM1----片1 UDQM

DQM2----片2  LDQM

DQM3---片2   UDQM

————————————————————————————————————————————————————————————

1、读操作(见杨铸 121)

地址线上送上要读数据的地址自然要有地址才行,(就好比送快递,首先你得确定好要送达的目的地址在哪里一样)

确定地址:CS低电平 即 nSCS0 拉低,选中外接设备 , L—BANK 也选中SDRAM 内部对应 某一片 (这样就定址了),而且同时

RAS 行地址选通信号也处于有效状态,当然这是要写列地址肯定要 行地址稳定才行(需要时间 tRCD=2),

列地址也假装不稳定,需要一个时间延迟(我们称为 CAS 潜伏期),当然并非不稳定,是芯片自身原因。

地址这样一步步确定,就可以读了(怎么不是写啊,因为 WE 无效,不让写啊,所以相当于读了。有效,就是写)

 

2、预充电操作

要对同一个L-BANK 的另一行进行寻址,自然要把原先一行关掉。重新发行列地址。

关掉原先一行,要预充电(目的是对整个存储体原有信息进行重写,然后再关闭操作行)

即预充电包含两步(重写+关闭原先行),但是预充电不定期,只在读操作执行

 

3、写操作

和读操作一样,唯一区别是 经过行延迟(tRCD后)输入写命令(WE低电平有效,拉低,就可以写)

在写完最后一个数据后, 延迟 tWR,发送预充电命令。关闭激活页。

等待 tRP 时间后可以进行下一次操作。 

 4、写操作

5、刷新操作

——————————————————————————————————————————————

以上可以结合 杨铸书籍和s3c2440芯片手册 memory contrl 来分析的,不算难,除了刷新没耐性看,还好

 ————————————————————————————————————————————————————————————

开始做内存驱动实验:(2.6.8)

本程序文件主要实现了: 关闭看门狗,初始化内存,复制ROM数据到内存中,然后调到内存执行 Xmain 函数,从 xmain 函数返回后, 将 全部 LED 点亮,进入死循环。

 ;
; 内存初始化实验
;
    AREA Init, CODE, READONLY
    ENTRY
start
    ; close watchdog
    ldr r0, = 0x53000000    ; 将看门狗控制寄存器地址放入r0
    mov r1, #0
    str r1, [r0]            ; 设置看门狗控制寄存器的值为0


    bl initmem                ; 跳转到initmem代码段,初始化内存
    
    bl copyall                ; 跳转到数据拷贝代码段,将ROM中数据拷贝到内存中
    
    IMPORT xmain            ; 引入main.c中的xmain函数
ldr sp, =0x34000000 ; 调用C程序之前先初始化栈指针 ldr lr, =endxmain ; 设置xmain函数的返回地址 ldr pc, =xmain ; 跳转到C程序中的xmain函数的入口处执行 endxmain ldr r0, =0x56000010 ; LED的GPIO接口配置寄存器(只针对QQ2440,MINI2440开发板) ldr r1, =0x00015400 ; GPIO配置数据 str r1, [r0] ; 设置GPIO ldr r0, =0x56000014 ; LED控制寄存器地址 ldr r1, =0x000000e0 ; 全部LED亮 str r1,[r0] loop b loop ; 死循环 copyall IMPORT |Image$$RO$$Base| ; 引入编译器Image$$RO$$Base符号变量 IMPORT |Image$$RW$$Limit| ; 引入编译器Image$$RW$$Limit符号变量 ldr r0, = |Image$$RO$$Base| ; 取得Image$$RO$Base域基址的值 ldr r1, = |Image$$RW$$Limit|; 取得Image$$RW$Base域结束地址的值 ldr r2, =0x0 ; 数据拷贝源地址
copyallloop teq r0,r1 ; 测试是否拷贝完成 beq quitcopyallloop ; 拷贝完成,跳往quitcopyallloop退出 ldr r3, [r2], #4 ; 四字节加载 str r3, [r0], #4 ; 四字节存储 b copyallloop ; 返回继续执行
quitcopyallloop bx lr ; 调用返回 (lr 即存放 PC指针的值,也就是子程序的返回地址)

initmem ; 内存初始化 ldr r0, =0x48000000 ; 加载内存相关寄存器首地址r0 ldr r1, =0x48000034 ; 加载内存相关寄存器尾地址到r1 adr r2, memdata ; 将寄存器配置数据地址段首地址加载到r2 // 这里是相对地址 initmemloop ldr r3, [r2], #4 ; 循环设置存寄存器 str r3, [r0], #4 teq r0, r1 bne initmemloop ; 循环到最后一个寄存器时退出函数
bx lr memdata DCD 0x22000000 ;BWSCON 选中 bank6 bank7 32bit数据输入输出 // 用于分配一片连续的字存储单元并用指定的数据初始化(参考芯片手册, BWSCON 到 MRSRB7 正好13个字,也就是 0x48000000---0x48000034) DCD 0x00000700 ;BANKCON0 DCD 0x00000700 ;BANKCON1 DCD 0x00000700 ;BANKCON2 DCD 0x00000700 ;BANKCON3 DCD 0x00000700 ;BANKCON4 DCD 0x00000700 ;BANKCON5 DCD 0x00018005 ;BANKCON6 // 确定存储芯片类型为 SDRAM RAS到CAS delay 3个时钟周期 列地址 9 bit DCD 0x00018005 ;BANKCON7 // 同上 DCD 0x008e07a3 ;REFRESH // sdram 刷新控制 DCD 0x000000b1 ;BANKSIZE DCD 0x00000030 ;MRSRB6 DCD 0x00000030 ;MRSRB7 END

 

 

讲解:http://www.cnblogs.com/idle_man/archive/2010/12/18/1910158.html (跳转到数据拷贝代码段,将ROM中数据拷贝到内存中)//  这里看杨铸 P95 页一目了然

 

copyall                        
    IMPORT |Image$$RO$$Base|    ; 引入编译器Image$$RO$$Base符号变量   
    IMPORT |Image$$RW$$Limit|    ; 引入编译器Image$$RW$$Limit符号变量
    ldr r0, = |Image$$RO$$Base|    ; 取得Image$$RO$Base域基址的值
    ldr r1, = |Image$$RW$$Limit|; 取得Image$$RW$Base域结束地址的值

 

对于刚学习ARM的人来说,如果分析它的启动代码,往往不明白下面几个变量的含义:|Image$$RO$$Limit|、|Image$$RW$$Base|、|Image$$ZI$$Base|。

在ADS的Debug Settings中有一栏是Linker/ARM Linker,在output选项中有一个RO base选项,下面应该有一个地址,我这里是0x0000 0000(不是每个都一样的),后面的RW base 地址是0x3000 0000,

然后在Options选项中有Image entry point ,是一个初始程序的入口地址,我这里是0x0000 0000 。

|Image$$RO$$Base| = Image entry point = 0x0000 0000 ;表示程序代码存放的起始地址

|Image$$RO$$Limit|=程序代码起始地址+代码长度+1=0x0c100000+Tatal RO size+1

|Image$$RW$$Base| = 0x0c200000 ;由RW base 地址指定

 

 

 

内存初始化也可以通过C语言来实现:

 1 #define MEM_CTL_BASE  0x48000000
 2 #define MEM_CTL_END   0x48000034
 3 unsigned long const mem_cfg_val[]=
 4 {
 5         0x22000000,        //BWSCON                  //  用于分配一片连续的字存储单元并用指定的数据初始化
 6         0x00000700,        //BANKCON0    
 7         0x00000700,        //BANKCON1    
 8         0x00000700,        //BANKCON2    
 9         0x00000700,     //BANKCON3        
10         0x00000700,        //BANKCON4    
11         0x00000700,        //BANKCON5    
12         0x00018005,        //BANKCON6    
13         0x00018005,        //BANKCON7    
14         0x008e07a3,        //REFRESH    
15         0x000000b1,        //BANKSIZE    
16         0x00000030,        //MRSRB6    
17         0x00000030,        //MRSRB7
18 
19 }    ;
20 void mem_init(void)
21 {
22     int i=0;
23     unsigned long * p=(unsigned long *)MEM_CTL_BASE;
24     for(:i<(MEM_CTL_END-MEM_CTL_BASE)/4;i++)
25     p[i]=mem_cfg_val[i];
26 
27 
28 
29 }

 

转载于:https://www.cnblogs.com/shengruxiahua/p/5094417.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值