吕氏春秋8266 发表于 2010-12-5 13:08:26

裸奔程序5-内存控制器及SCATT文件

本帖最后由 吕氏春秋8266 于 2010-12-5 13:26 编辑

第四章 存储控制器

S3c2440存储控制器提供了访问外部设备所需的信号,有如下特征:
每个BANK空间为128M,总共1G
编程控制总线宽度(8/16/32),不过BANK0只能选择16/32
BANK0~BANK5外接ROM\SRAM,BANK6~BANK7还可外接SDRAM
BANK0~BANK6起始地址固定,BANK7起始地址可编程选择
每个BANK访问周期可编程控制
通过外部的“wait”信号延长总线的访问周期
S3c2440对外引出27根地址线ADDR0~ADDR26,其访问范围为128M,此外,CPU还对外引出8根片选信号nGCS0~nGCS7

在访问SDRAM时,CPU提供了一组用于SDRAM的信号
SDRAM时钟有效信号SCKE;
SDRAM时钟信号 SCLK0/SCLK1
数据掩码信号DQM0~DQM3
片选信号nGCS6~nGCS7
SDRAM行地址选通信号nSRAS
SDRAM列地址选通信号nSCAS

SDRAM结构:



我们先看看对SDRAM读写的时序图:


从上图我们可以看出,根据SDRAM芯片的列地址设置相关寄存器后,CPU就会从32位地址中自动分出L-BANK选择信号、行、列地址信号,然后先后发出行地址及信号,列地址及信号及L-BANK信号。也就是说,CPU分两次将行及列地址分别送入SDRAM进行锁存,然后再进行数据读写。

内存控制器
内在控制器为访问外部存储空间提供存储器控制信号,提供了13个特殊功能寄存器。
1、      BSWCON总线宽度控制寄存器用来控制各组存储器的总线宽度和访问周期。每4位控制一个BANK,最高位对应BANK7
BWx:设置相应BANK的位宽。00:8 ,01:16,10:32
WSx:是否使用存储器等待信号,通常为0
STx   :启动\禁止SDRAM掩码引脚,其中SDRAM:0,SRAM:1
2、      BANKCONx控制外接设备的访问时序。

其中BANK6~BANK7位来表示存储器的类型:
00:ROM或SRAM
11:SDRAM
Tacs:在nGCSn有效前地址信号建立时间
Tcos:在nOE   有效前芯片选择信号建立时间
Tacc: 访问周期,如启用nWAIT信号,则Tacc大于或等于4个周期
Tcoh:nOE信号无效后芯片选择信号保持时间
Tcah:nGCSn无效后地址保持时间
Tacp:页模式访问周期
PMC:页模式配置
如果BANK6~BANK7外接SDRAM时,即=11,则位定义如下:
Trcd:从RAS到CAS延时
SDRAM使用的频率是HCLK。
FCLK for CPU,
HCLK for the AHB bus peripherals,
PCLK for the APB bus peripherals.
在TQ2440开发板的uboot中,FCLK = 400MHz
FCLK:HCLK:PCLK = 1:4:8
TQ2440使用的是SDRAM是HY67V561620F,查看Spec.

RAS to CAS Delay的最小值为15~20 ns
HCLK为100MHz,所以一个clock为10ns,所以至少需要2个clock.

SCAN:列地址位数。00:8,01:9,10:10
查阅Spec,列地地址位数为9

BANK0~BANK5在系统复位后,其值为0x700表示Tacs=Tcos=Tcon=Tcah=Tacp=1,
Tacc=14个周期,PMC=0表示页配置正常模式。
BANK6~BANK7在系统复位后,其值为0x180008表示BANK6~BANK7外接SDRAM,同时设定RAS到CAS延时4个周期,8位列地址数目。


TQ2440中BANKCON6和BANKCON7的其它位数均为0。
综合以上各值,BANKCON6~BANKCON7设为0x00018005

3、      REFRESH用于设置SDRAM的自动刷新。
REFEN:0:无效1:使能有效
TREFMD 0:自动刷新;1:选择自刷新方式
Trp SDRAM预充电时间
Tsrc控制SDRAM半行周期时间
RefcntSDRAM刷新计数器,

得到刷新周期为64ms/8192=7.8125us,
TQ2440的HCKL为100MHz
结合公式,R_CNT=2^11 + 1 – 12 * 7.8125 = 1955。

Refresh count = 2^11 +1 -100X7.8125 = 1268 = 0x4F4
Trp():设置为0即可。(Precharge time)


4、      BANKSIZE寄存器用于调整BANK大小
BURST_EN:0/1 禁止/允许ARM核突发传输.。
SCKE_EN:0/1 不使用/使用SCKE信号令SDRAM进入省电模式
SCKE_EN:0/1 时刻/SDRAM访问期间发出SCKE信号,
BK67MAP:设置大小。000-32 001-64 010-128
本开发板仅使用BANK6的64M空间,其中BK76MAP(bit)配置BANK6/7映射的大小,可设置为010 = 128MB/128MB或001 = 64MB/64MB,只要比实际RAM大都行,多出来的空间程序会检测出来,不会发生使用不存在的内存的情况(Bootloader和Linux内核都会作内存检测)。。
5、      MRSRBx
能修改的只有位CL(CAS latency,000 = 1 clock, 010 = 2 clocks, 011=3 clocks),其他的全部是固定的(fixed),故值为0x00000030。SDRAM 不支持CL=1的情况,所以位取值为010(CL=2)或011(CL=3),开发板保守的值为0b11。

TQ2440存储器控制器
BWSCON: 0x22121110;GCS4=GCS6=GCS7=32bit,
   由于TQ2440外接NOR flash,开发板采用了最保守的值,即正常模式,每次读写一个数据,其它所有时钟周期均最大
BANK0:0x7ff4
BANK1~BANK5:0x2e50
表示外接SDRAM,其列地址为9位,RAS到CAS延时为2周期。
BANK6~BANK7:0x18005
设置寄存器刷新HCLK=100M u=7.812us   2048+1-100*7.81=1268=0x4f4
REFRESH:0x9404f4
BANKSIZE:0x32
MRSRBx:0x30

程序说明:
因为存储寄存器为连续地址空间,有初始化程序中,我们用如下代码进行设置:
;初始化存储控制器寄存器,使SDRAM可用

      adr r0,MEMDAT
      ldr r1,=BWSCON
      add r2,r0,#52
0
      ldr r3,,#4
      str r3,,#4
      cmp r2,r0
      bne %b0      
      
MEMDAT DATA
      DCD 0x22121110
      DCD 0x7ff4
      DCD 0x2e50
      DCD 0x2e50
      DCD 0x2e50
      DCD 0x2e50
      DCD 0x2e50
      DCD 0x18005
      DCD 0x18005
      DCD 0x9404f4
      DCD 0x32
      DCD 0x30
      DCD 0x30
adr r0,MEMDAT是伪指令,其汇编为如下个一条指令:
   add      r0,pc,#0x18 ; #0xa4显然它被汇编成基于PC+8+偏移地址模式,能正确读取。

在本例中,我们程序是从NAND中启动,在初始化存储寄存器的基础后,我们打算将点亮LED灯代码从CPU内部RAM中搬移到SDRAM中运行,自然我们产生第一个问题,我们知道,从NAND和SDRAM中运行,其地址不一致,如何保证各模块间地址正确编译呢,在这里,我们将scatter文件来控制。
LOAD_IMAGE 0x0
{
   LOAD_FLASH 0x0 0x1000            ;4K flash
   {
    s3c2440.o(Init,+First)
    TestMain.o(+ro)
   }
   LOAD_SDRAM 0x30000000 0x4000000;64Msdram
   {
    led.o(+ro)
   }
}
第二个问题,我们只想搬运LED代码并将它放在0x30000000,如何得到它在RAM中的起始地址及大小呢,这就将用到如下三个定义
   IMPORT |Load$$LOAD_SDRAM$$Base|   
       IMPORT |Image$$LOAD_SDRAM$$Base|
       IMPORT |Image$$LOAD_SDRAM$$Length|
其拷贝代码如下:
   ldr r0,=|Load$$LOAD_SDRAM$$Base|
      ldr r1,=|Image$$LOAD_SDRAM$$Base|
      ldr r2,=|Image$$LOAD_SDRAM$$Length|
      
      add r2,r0,r2
      
0
      ldr r3,,#4
      str r3,,#4
      cmp r0,r2
      bne %b0
因为,程序从CPU内部RAM跳转至SDRAM中运行,因此,其范围大于32M空间,必须使用ldr pc,=_LEDDISPLAY指令进行跳转。_LEDDISPLAY由LOAD_SDRAM 0x30000000 0x4000000 模块决定,其值为0x30000000
说明:经过反复测试和反汇编我们得知,如果我们将LOAD_FLASH 初始值改为非0,比如0x1000,|Load$$LOAD_SDRAM$$Base|的值由编译器根据LOAD_FLASH模块的初始值进行决定,在进行软件甚至JLINK仿真时都能通过,但下载到NAND中将不会正常运行。这是因为软件或JLINK仿真都是将程序下载到指定的位置运行,地址正确。但下载到NAND中时,其地址永远从0x0处运行,将导致地址错误。

吕氏春秋8266 发表于 2010-12-5 13:13:17

附上源代码,呵呵!

nuckzjt 发表于 2010-12-5 15:05:15

先顶一个,收藏一下,以后学习到这里了好做参考!

天嵌_support1 发表于 2010-12-6 11:16:17

2# 吕氏春秋8266


不错哈,给网友加精一下。供其他网友学习讨论

nuckzjt 发表于 2010-12-23 21:10:27

很不错的 学习机会,希望继续努力,

xinanjiaoda 发表于 2011-4-24 21:31:41

相当的牛逼
页: [1]
查看完整版本: 裸奔程序5-内存控制器及SCATT文件