S3C2440 SDRAM内存驱动

发布者:caijt最新更新时间:2016-04-26 来源: eefocus关键字:S3C2440  SDRAM  内存驱动 手机看文章 扫描二维码
随时随地手机看文章
SDRAM(Synchronous Dynamic Random Access Memory,同步动态随机存储器)也就是通常所说的内存。内存的工作原理、控制时序、及相关控制器的配置方法一直是嵌入式系统学习、开发过程中的一个难点。我们从其硬件的角度来分析其原理,然后再引出SDRAM的驱动编写过程。
内存是代码的执行空间,以PC机为例,程序是以文件的形式保存在硬盘里面的,程序在运行之前先由操作系统装载入内存中,由于内存是RAM(随机访问存储器),可以通过地址去定位一个字节的数据,CPU在执行程序时将PC的值设置为程序在内存中的开始地址, CPU会依次的从内存里取址,译码,执行,在内存没有被初始化之前,内存好比是未建好的房子,是不能读取和存储数据的,因此我们要想让MTOS运行在内存里必须进行内存的初始化。
通用存储设备:
在介绍内存工作原理之前有必要了解下存储设备的存储方式:ROM,RAM
l  ROM(Read-Only Memory):只读存储器,是一种只能读出事先所存数据的固态半导体存储器。其特性是一旦储存资料就无法再将之改变或删除。通常用在不需经常变更资料的电子或电脑系统中,资料并且不会因为电源关闭而消失。如:PC里面的BIOS。
l  RAM(Random Access Memory) :随机访问存储器,存储单元的内容可按需随意取出或存入,且存取的速度与存储单元的位置无关的存储器。可以理解为,当你给定一个随机有效的访问地址,RAM会返回其存储内容(随机寻址),它访问速度与地址的无关。这种存储器在断电时将丢失其存储内容,故主要用于存储短时间内随机访问使用的程序。计算机系统里内存地址是一个四字节对齐的地址(32位机),CPU的取指,执行,存储都是通过地址进行的,因此它可以用来做内存。
RAM按照硬件设计的不同,随机存储器又分为DRAM(Dynamic RAM)动态随机存储器和SRAM(Static RAM) 静态随机存储器。
l  DRAM:它的基本原件是小电容,电容可以在两个极板上短时间内保留电荷,可以通过两极之间有无电压差代表计算机里的0和1,由于电容的物理特性,要定期的为其充电,否则数据会丢失。对电容的充电过程叫做刷新,但是制作工艺较简单,体积小,便于集成化,经常做为计算机里内存制作原件。比如:PC的内存,SDRAM, DDR, DDR2, DDR3等,缺点:由于要定期刷新存储介质,存取速度较慢。
l  SRAM:它是一种具有静止存取功能的内存,不需要刷新电路即能保存它内部存储的数据。因此其存取速度快,但是体积较大,功耗大,成本高,常用作存储容量不高,但存取速度快的场合,比如CPU的L1 cache,L2cache(一级,二级缓存) ,寄存器。
 
为了满足开发的需要MINI2440在出厂时搭载了三种存储介质:
(1)NOR FLASH(2M):ROM存储器,通常用来保存BootLoader,引导系统启动
(2)NAND FLASH(256M,型号不一样,Nandflash大小不一样):保存操作系统映像文件和文件系统
(3)SDRAM(64M):内存,执行程序
l  NOR FLASH:它的特点是支持XIP芯片内执行(eXecute In Place),这样应用程序可以直接在Flash闪存内运行,不必再把代码读到系统RAM中,也就是说可以随机寻址。NOR FLASH的成本较高。
l  NAND FLASH:它能提供极高的单元密度,可以达到高存储密度,并且写入和擦除的速度也很快。其成本较低,不支持XIP。可做嵌入式里的数据存储介质。如:手机存储卡,SD卡等。

1.1.1   S3C2440存储器地址段(Bank)

S3C2440对外引出了27根地址线ADDR0~ADDR26,它最多能够寻址128MB,而S3C2440的寻址空间可以达到1GB,这是由于S3C2440将1GB的地址空间分成了8个BANKS(Bank0~Bank7),其中每一个BANK对应一根片选信号线nGCS0~nGCS7,当访问BANKx的时候,nGCSx管脚电平拉低,用来选中外接设备, S3C2440通过8根选信号线和27根地址线,就可以访问1GB。如图2-48所示。

 
图2-48 S3C2440存储器BANK
如图所示,左侧图对应不使用Nandflash启动时(通过跳线设置),存储器Bank分布图,通常在这种启动方式里选择Norflash启动,将Norflash焊接在Bank0, 系统上电后,CPU从Bank0的开始地址0x00000000开始取指运行。
上图右侧是选择从Nandflash引导启动(通过跳线设置),系统上电后,CPU会自动将Nandflash里前4K的数据复制到S3C2440内部一个4K大小 SRAM类型存储器里(叫做Steppingstone),然后从Steppingstone取指启动。
其中Bank0~Bank5可以焊接ROM或SRAM类型存储器,Bank6~Bank7可以焊接ROM,SRAM,SDRAM类型存储器,也就是说,S3C2440的SDRAM内存应该焊接在Bank6~Bank7上,最大支持内存256M,Bank0~Bank5通常焊接一些用于引导系统启动小容量ROM,具体焊接什么样存储器,多大容量,根据每个开发板生产商不同而不同,比如MINI2440开发板将2M的Norflash焊接在了Bank0上,用于存放系统引导程序Bootloader,将两片32M,16Bit位宽SDRAM内存焊接在Bank6和Bank7上,并联形成64M,32位内存。
由于S3C2440是32位芯片,理论上讲可以达到4GB的寻址范围,除去上述8个BANK用于连接外部设备,还有一部分的地址空间是用于设备特殊功能寄存器,其余地址没有被使用。
表2-14 S3C2440设备寄存器地址空间
外接设备 起始地址 结束地址
存储控制器 0x48000000 0x48000030
USB Host控制器 0x49000000 0x49000058
中断控制器 0x4A000000 0x4A00001C
DMA 0x4B000000 0x4B0000E0
时钟和电源管理 0x4C000000 0x4C000014
LCD控制器 0x4D000000 0x4D000060
NAND FLASH控制器 0x4E000000 0x4E000014
摄像头接口 0x4F000000 0x4F0000A0
UART 0x50000000 0x50008028
脉宽调制计时器 0x51000000 0x51000040
USB设备 0x52000140 0x5200026F
WATCHDOG计时器 0x53000000 0x53000008
IIC控制器 0x54000000 0x5400000C
IIS控制器 0x55000000 0x55000012
I/O端口 0x56000000 0x560000B0
实时时钟RTC 0x57000040 0x5700008B
A/D转换器 0x58000000 0x58000010
SPI 0x59000000 0x59000034
SD接口 0x5A000000 0x5A000040
AC97音频编码接口 0x5B000000 0x5B00001C

1.1.2   SDRAM内存工作原理

SDRAM的内部是一个存储阵列。阵列就如同表格一样,将数据“填”进去。在数据读写时和表格的检索原理一样,先指定一个行(Row),再指定一个列(Column),我们就可以准确地找到所需要的单元格,这就是内存芯片寻址的基本原理,如图2-49所示。

 
图2-49内存行,列地址寻址示意图
这个单元格(存储阵列)就叫逻辑 Bank(Logical Bank,下文简称 L-Bank)。 由于技术、成本等原因,不可能只做一个全容量的 L-Bank,而且最重要的是,由于SDRAM的工作原理限制,单一的 L-Ban k将会造成非常严重的寻址冲突,大幅降低内存效率。所以人们在 SDRAM内部分割成多个 L-Bank,目前基本都是 4个(这也是SDRAM规范中的最高L-Bank数量),由此可见,在进行寻址时就要先确定是哪个 L-Bank,然后在这个选定的 L-Bank中选择相应的行与列进行寻址。因此对内存的访问,一次只能是一个 L-Bank工作。如图2-50:

 
图2-50内存存储单元
当对内存进行操作时(见下图),先要确定操作L-Bank,因此要对L-Bank进行选择。在内存芯片的外部管脚上多出了两个管脚BA0, BA1,用来片选4个L-Bank。如前所述, 32位的地址长度由于其存储结构特点,分成了行地址和列地址。通过下面的内存结构图可知,内存外接管脚地址线只有13根地址线A0~A12,它最多只能寻址8M内存空间,到底使用什么机制来实现对64M内存空间进行寻址的呢?SDRAM的行地址线和列地址线是分时复用的,即地址要分两次送出,先送出行地址(nSRAS行有效操作),再送出列地址(nSCAS列有效操作)。这样,可以大幅度减少地址线的数目,提高器件的性能和制作工艺复杂度。但寻址过程也会因此而变得复杂。实际上,现在的SDRAM一般都以L-Bank为基本寻址对象的。由L-Bank地址线BAn控制L-Bank间的选择,行地址线和列地址线贯穿连接所有的L-Bank,每个L-Bank的数据的宽度和整个存储器的宽度相同,这样,可以加快数据的存储速度。同时,BAn还可以使未被选中的L-Bank工作于低功耗的模式下,从而降低器件的功耗。
 
 
图2-51 HY57561620内部结构图
 
开发板内存控制器管脚接线(以MINI2440开发板为例):
(1)确定BA0、BA1的接线
表2-15 BA0、BA1接线

 
 
Bank Size: 外接内存容量大小(HY57561620是4Mbit*16bit*4Bank*2Chips/8=64MB)
Bus Width: 总线宽度 (两片16位HY57561620,并联成32位)
Base Component:单个芯片容量(bit)(256Mb)
Memory Configration:内存配置 ((4M*16*4banks)*2Chips )
由硬件手册Bank Address管脚连接配置表可知,使用A[25:24]两根地址线作为Bank片选信号,正好两根接线可以片选每个存储单元的4个BANKS。
(2)确定其它接线
SDRAM内存是焊接在BANK6~BANK7上的,其焊接管脚,如图2-52:

 
图2-52 S3C2440 16位宽内存芯片
上图是S3C2440提供的两片16位芯片并联连接示意图,An是CPU地址总线,其中A2~A14为内存芯片寻址总线,之所以地址寻址总线从A2开始是因为内存地址都是按字节对齐的,,A24,A25为L-Bank片选信号,Dn为CPU数据总线,其它为对应控制信号线。
表2-16 内存芯片各管脚说明
外接管脚名 内接管脚名 全称 描述
A2~A14 A0~A12 Address 地址线
D0 ~D31 DQ0~DQ31 Data Input/Output 数据线
A24,A25 BA0,BA1 Bank Address L-BANK片选信号
DQM0~DQM3 LDQM, UDQM Data Input/Output Mask 高,低字节数据掩码信号
SCKE SCKE Clock Enable 输入时钟有效信号
SCLK SCLK Clock 输入时钟
nSCS0 nSCS General Chip Select 片选信号(它与nGCS6是同一管脚的两个功能)
nSRAS nSRAS Row Address Strobe 行地址选通信号
nSCAS nSCAS Column Address Strobe 列地址选通信号
nWE newnWE Write Enable 写入有效信号
我们通过S3C2440 16位宽内存芯片接线图可以看出,两片内存芯片只有两个地方不一样,LDQM, UDQM和数据总线DQn接线方式不一样。
由于存储芯片位宽为16位,一次可以进行两个字节的读取。但是,通常操作系统里最小寻址单位是1字节,因此内存控制器必须要保证可以访问内存里每一个字节。UDQM ,LDQM分别代表16位数据的高,低字节读取信号,当读取数据时,LDQM /UDQM分别用来控制16位数据中高低字节能否被读取,当LDQM /UDQM为低电平时,对应的高/低字节就可以被读取,如果LDQM /UDQM为高电平时,对应的高/低字节就不能被读取。当向内存里写入数据时,LDQM /UDQM控制数据能否被写入,当LDQM /UDQM为低电平时,对应的高/低字节就可以被写入,如果LDQM /UDQM为高电平时,对应的高/低字节就不能被写入。通过对LDQM /UDQM信号的控制可以控制对两个存储芯片存储数据,由于两个存储单元的地址线是通用的,他们都能接收到CPU发出的地址信号,但是,发给两个存储单元的LDQM /UDQM信号是不同的,以此来区分一个字的高低字节。
S3C2440A为32位CPU,也就是说其数据总线和地址总线宽度都是32位(可以理解为32根线一端连接CPU内部,另外一端连接向内存控制器),那么内存数据的输入/输出端也要保证是32位总线,MINI2440上采用两片16位宽总线内存芯片并联构成32位总线。其中一个芯片连接到CPU数据总线的低16位,另外一个芯片连接到数据总线上的高16位,并联成32位总线,因此两个芯片的输入/输出总线连接到CPU总线上的不同管脚上。

1.1.3   SDRAM的读操作

SDRAM进行读操作时,先向地址线上送上要读取数据的地址,通过前面的知识了解到,地址被分成3部分,行地址,列地址,L-Bank片选信号。片选(L-Bank的定址)操作和行有效操作可以同时进行。
在CS、L-Bank定址的同时,RAS(nSRAS行地址选通信号)也处于有效状态。此时 An地址线则发送具体的行地址。A0~A12,共有13根地址线(可表示8192行),A0~A12的不同数值就确定了具体的行地址。由于行有效的同时也是相应 L-Bank有效,所以行有效也可称为L-Bank有效。
行地址确定之后,就要对列地址进行寻址了。但是,地址线仍然是行地址所用的 A0~A12。没错,在SDRAM中,行地址与列地址线是复用的。列地址复用了A0~A8,共9根(可表示512列)。那么,读/写的命令是怎么发出的呢?其实没有一个信号是发送读或写的明确命令的,而是通过芯片的可写状态的控制来达到读/写的目的。显然WE信号(nWE)就是一个关键。WE无效时,当然就是读取命令。有效时,就是写命令。
SDRAM基本操作命令, 通过各种控制/地址信号的组合来完成(H代表高电平,L代表低电平,X表示高,低电平均没有影响)。此表中,除了自刷新命令外,所有命令都是默认CKE(SCKEl输入时钟频率有效)有效。列寻址信号与读写命令是同时发出的。虽然地址线与行寻址共用,但CAS(nSCAS列地址选通信号)信号则可以区分开行与列寻址的不同,配合A0~A8,A9~A11来确定具体的列地址。
读取命令与列地址一块发出(当WE为低电平是即为写命令)然而,在发送列读写命令时必须要与行有效命令有一个间隔,这个间隔被定义为 tRCD,即RAS to CAS Delay(RAS至 CAS延迟),这个很好理解,在地址线上送完行地址之后,要等到行地址稳定定位后再送出列地址,tRCD是SDRAM的一个重要时序参数,相关数值参看对应芯片硬件手册。通常tRCD以时钟周期(tCK,Clock Time)数为单位,比如笔者MINI2440所用内存芯片里面写到tRCD为20nst,如果将来内存工作在100MHz,那么RCD至少要为2个时钟周期, RCD=2。

 
图2-53 SDRAM读操作时序图
在选定列地址后,就已经确定了具体的存储单元,剩下就是等待数据通过数据 I/O通道(DQ)输出到内存数据总线上了。但是在列地址选通信号CAS 发出之后,仍要经过一定的时间才能有数据输出,从CAS与读取命令发出到第一笔数据输出的这段时间,被定义为 CL(CAS Latency,CAS潜伏期)。由于CL只在读取时出现,所以CL又被称为读取潜伏期(RL,Read Latency)。CL的单位与tRCD一样,也是时钟周期数,具体耗时由时钟频率决定(笔者官方手册CL=3)。不过,CAS并不是在经过CL周期之后才送达存储单元。实际上CAS与RAS一样是瞬间到达的。由于芯片体积的原因,存储单元中的电容容量很小,所以信号要经过放大来保证其有效的识别性,这个放大/驱动工作由S-AMP负责。但它要有一个准备时间才能保证信号的发送强度,这段时间我们称之为tAC(Access Time from CLK,时钟触发后的访问时间)。

1.1.4    SDRAM预充电操作

从存储体的结构图上可以看出,原本逻辑状态为1的电容在读取操作后,会因放电而变为逻辑0。由于SDRAM的寻址具有独占性,所以在进行完读写操作后,如果要对同一L-Bank的另一行进行寻址,就要将原先操作行关闭,重新发送行/列地址。在对原先操作行进行关闭时,DRAM为了在关闭当前行时保持数据,要对存储体中原有的信息进行重写,这个充电重写和关闭操作行过程叫做预充电,发送预充电信号时,意味着先执行存储体充电,然后关闭当前L-Bank操作行。预充电中重写的操作与刷新操作(后面详细介绍)一样,只不过预充电不是定期的,而只是在读操作以后执行的。

1.1.5    SDRAM突发操作

突发(Burst)是指在同一行中相邻的存储单元连续进行数据传输的方式,连续传输所涉及到存储单元(列)数量就是突发长度(Burst Length,简称BL)。
在目前,由于内存控制器一次读/写P-Bank位宽的数据,也就是8个字节,但是在现实中小于8个字节的数据很少见,所以一般都要经过多个周期进行数据的传输,上文写到的读/写操作,都是一次对一个存储单元进行寻址,如果要连续读/写,还要对当前存储单元的下一单元进行寻址,也就是要不断的发送列地址与读/写命令(行地址不变,所以不用再对地寻址)。虽然由于读/写延迟相同可以让数据传输在I/O端是连续的,但是它占用了大量的内存控制资源,在数据进行连续传输时无法输入新的命令效率很低。为此,引入了突发传输机制,只要指定起始列地址与突发长度,内存就会依次自动对后面相应长度数据的数据存储单元进行读/写操作而不再需要控制器连续地提供列地址,这样,除了第一笔数据的传输需要若干个周期(主要是之间的延迟,一般的是tRCD + CL)外,其后每个数据只需一个周期即可。
总结下:
SDRAM的基本读操作需要控制线和地址线相配合地发出一系列命令来完成。先发出芯片有效命令(ACTIVE),并锁定相应的L-BANK地址(BA0、BA1给出)和行地址(A0~A12给出)。芯片激活命令后必须等待大于tRCD(SDRAM的RAS到CAS的延迟指标)时间后,发出读命令。CL(CAS延迟值)个时钟周期后,读出数据依次出现在数据总线上。在读操作的最后,要向SDRAM发出预充电(PRECHARGE)命令,以关闭已经激活的L-BANK。等待tRP时间(PRECHAREG命令后,相隔tRP时间,才可再次访问该行)后,可以开始下一次的读、写操作。SDRAM的读操作支持突发模式(Burst Mode),突发长度为1、2、4、8可选。

1.1.6    SDRAM写操作

SDRAM的基本写操作也需要控制线和地址线相配合地发出一系列命令来完成。先发出芯片有效命令,并锁定相应的L-BANK地址(BA0、BA1给出)和行地址(A0~A12给出)。芯片有效命令发出后必须等待大于tRCD的时间后,发出写命令数据,待写入数据依次送到DQ(数据线)上。在最后一个数据写入后,延迟tWR时间。发出预充电命令,关闭已经激活的页。等待tRP时间后,可以展开下一次操作。写操作可以有突发写和非突发写两种。突发长度同读操作。
 

图2-54 SDRAM写操作时序图

1.1.7    SDRAM的刷新

SDRAM之所以成为DRAM就是因为它要不断进行刷新(Refresh)才能保留住数据,因此它是SDRAM最重要的操作。
刷新操作与预充电中重写的操作一样,都是用S-AMP先读再写。但为什么有预充电操作还要进行刷新呢?因为预充电是对一个或所有 L-Bank中的工作行操作,并且是不定期的,而刷新则是有固定的周期,依次对所有行进行操作,以保留那些很长时间没经历重写的存储体中的数据。但与所有L-Bank预充电不同的是,这里的行是指所有L-Bank中地址相同的行,而预充电中各L-Bank中的工作行地址并不是一定是相同的。那么要隔多长时间重复一次刷新呢?目前公认的标准是,存储体中电容的数据有效保存期上限是64ms(毫秒,1/1000秒),也就是说每一行刷新的循环周期是64ms。这样刷新时间间隔就是: 64m/行数s。我们在看内存规格时,经常会看到4096 Refresh Cycles/64ms或8192 Refresh Cycles/64ms的标识,这里的4096与8192就代表这个芯片中每个L-Bank的行数。刷新命令一次对一行有效,刷新间隔也是随总行数而变化,4096行时为 15.625μs(微秒,1/1000毫秒),8192行时就为 7.8125μs。刷新操作分为两种:Auto Refresh,简称AR与Self Refresh,简称SR。不论是何种刷新方式,都不需要外部提供行地址信息,因为这是一个内部的自动操作。对于 AR,SDRAM内部有一个行地址生成器(也称刷新计数器)用来自动的依次生成行地址。由于刷新是针对一行中的所有存储体进行,所以无需列寻址,或者说CAS在 RAS之前有效。所以,AR又称CBR(CAS Before RAS,列提前于行定位)式刷新。由于刷新涉及到所有L-Bank,因此在刷新过程中,所有 L-Bank都停止工作,而每次刷新所占用的时间为9个时钟周期(PC133标准),之后就可进入正常的工作状态,也就是说在这9个时钟期间内,所有工作指令只能等待而无法执行。64ms之后则再次对同一行进行刷新,如此周而复始进行循环刷新。显然,刷新操作肯定会对SDRAM的性能造成影响,但这是没办法的事情,也是DRAM相对于 SRAM(静态内存,无需刷新仍能保留数据)取得成本优势的同时所付出的代价。SR则主要用于休眠模式低功耗状态下的数据保存,这方面最著名的应用就是 STR(Suspend to RAM,休眠挂起于内存)。在发出AR命令时,将CKE置于无效状态,就进入了SR模式,此时不再依靠系统时钟工作,而是根据内部的时钟进行刷新操作。在SR期间除了CKE之外的所有外部信号都是无效的(无需外部提供刷新指令),只有重新使CKE有效才能退出自刷新模式并进入正常操作状态。
SDRAM相关寄存器:
(1)BWSCON寄存器(BUS WIDTH & WAIT CONTROL REGISTER)
表2-17 SDRAM控制寄存器(BWSCON)

 
 
 
根据开发板的存储器配置和芯片型号,设置每个BANK焊接芯片的位宽和等待状态
BWSCON,每4位对应一个BANK,这4位分别表示:
l  STx:启动/禁止SDRAM的数据掩码引脚(UB/LB),SDRAM没有高低位掩码引脚,此位为0,SRAM连接有UB/LB管脚,设置为1
l  注:UB/LB数据掩码引脚用来控制芯片读取/写入的高字节和低字节(对比硬件手册SDRAM和SRAM的接线图)
l  WSx:是否使用存储器的WAIT信号,通常设为0
l  DWx:设置焊接存储器芯片的位宽,笔者开发板使用两片容量为32M,位宽为16的SDRAM组成64M,32位存储器,因此DW7,DW6位设置为0b10,其它BANK不用设置采用默认值即可。
l  BANK0对应的是系统引导BANK,这4位比较特殊,它的设置是由硬件跳线决定的,因此不用设置
l  BWSCON设置结果:0x22000000
(2)BANKCON0~BANKCON5 (BANK CONTROL REGISTER)
表2-18 BANKCON0~BANKCON5控制寄存器(BANKCON0~BANKCON5)

 
这6个寄存器用来设置对应BANK0~BANK5的访问时序,采用默认值0x700即可
(3)BANKCON6~BANKCON7 (BANK CONTROL REGISTER)
表2-19 BANKCON6~BANKCON7控制寄存器(BANKCON6~BANKCON7)

 
 
 
由于内存都焊接在这两个BANK上,因此内存驱动主要是对这两个寄存器进行设置
l  MT:设置BANK6~BANK7的存储器类型,
00=ROM or SRAM 01=保留
10=保留         11=SDRAM
内存为SDRAM,设置为0b11,对应的应该设置Trcd和SCAN位,其它位和SDRAM无关
l  Trcd:RAS to CAS Delay行地址选通到列地址选通延迟,这个参数请看后面的内存工作原理扩展部分解释,笔者内存芯片为HY57V561620,由其芯片手册可知其Trcd为最少20ns,如果内存工作在100MHz,则该值至少要为2个时钟周期,通常设置为3个时钟周期,因此设置为0b01
l  SCAN:SDRAM Column Address Number SDRAM的列地址数,笔者内存芯片为HY57V561620,列地址数为9,设置为0b01
l  BANK6,BANK7设置结果为:0x18005
(4)REFRESH (REFRESH CONTROL REGISTER)
表2-20刷新频率设置寄存器(REFRESH)

 
 
 
SDRAM的刷新有效,刷新频率设置寄存器(刷新)
l  REFEN:开启/关闭刷新功能,设置为1,开启刷新
l  TREFMD:SDRAM刷新模式,0=CBR/AutoRefresh,  1=Self Refresh,设置为0,自动刷新
l  Trp:行地址选通预充电时间,一般设置为0b00即可
l  Tsrc:单行刷新时间,设置为0b11即可。
l  Refresh Counter:内存存储单元刷新数,它通过下面公式计算出:
Refresh Counter = 2^11 + 1 – SDRAM时钟频率(MHz)* SDRAM刷新周期(uS)
SDRAM的刷新周期,也就是内存存储单元间隔需要多久进行一次刷新,前面内存工作原理分析可知电容数据保存上限为64ms,笔者使用内存芯片每个L-Bank共有8192行,因此每次刷新最大间隔为:64ms/8192 = 7.8125uS,如果内存工作在外部晶振频率12MHz下,Refresh Counter = 1955,如果内存工作在100MHz下,那么Refresh Counter = 1269(取大整数)
l  REFRESH寄存器设置为:
0x8e0000 + 1269 = 0x008e04f5(HCLK = 100MHz)
0x8e0000 + 1955 = 0x008e07a3(HCLK = 12MHz)
(5)BANKSIZE寄存器(BANKSIZE REGISTER)
表2-21 BANKSIZE寄存器(BANKSIZE)

 
 
设置内存的突发传输模式,省电模式和内存容量。
l  BURST_EN:是否开启突发模式, 0 = ARM内核禁止突发传输 1 = 开启突发传输,设置为1,开启突发传输
l  SCKE_EN:是否使用SCKE信号作为省电模式控制信号, 0 = 不使用SCKE信号作为省电模式控制信号 1 = 使用SCKE信号作为省电模式控制信号,通常设置为1
l  SCLK_EN: 设置向存储器输入工作频率,0 = 一直输入SCLK频率,即使没有内存操作也会输入, 1 = 仅当进行内存数据操作时才输入SCLK频率,通常设置为1
l  BK76MAP:设置Bank6/7的内存容量,笔者使用开发板内存为两片32M内存芯片并联成64M,它们全部都外接到Bank6上,因此选择0b001
l  BANKSIZE寄存器设置为:0xb1
(6)SDRAM模式设置寄存器MRSRx (SDRAM MODE REGISTER SET REGISTER)
表2-22 SDRAM模式设置寄存器(MRSRx)
 
 
 
该寄存器用于设置CAS潜伏周期,可以手动设置的位只有CL[6:4]位,通过前面内存工作原理可知,笔者使用开发板CL=3,即0b011
l  MRSR6,MRSR7设置为:0x00000030

1.1.8   内存驱动实验

设置该工程加载时运行时地址为0x30000000,如图2-55所示:
 
图2-55设置加载时运行时地址
init.s:本程序文件主要实现了,关闭看门狗,初始化内存,拷贝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接口配置寄存器
ldr r1, =0x00015400                       ; GPIO配置数据
str r1, [r0]                                     ; 设置GPIO
ldr r0, =0x56000014                    ; LED控制寄存器地址
ldr r1, =0x0                                  ; 全部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
mov pc, lr                                                 ; 调用返回
 
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                                       ; 循环到最后一个寄存器时退出函数
mov pc,lr                                                           
 
memdata
DCD 0x22000000                 ;BWSCON
DCD 0x00000700                 ;BANKCON0    
DCD 0x00000700                 ;BANKCON1    
DCD 0x00000700                 ;BANKCON2    
DCD 0x00000700               ;BANKCON3             
DCD 0x00000700                 ;BANKCON4    
DCD 0x00000700                 ;BANKCON5    
DCD 0x00018005                 ;BANKCON6    
DCD 0x00018005                 ;BANKCON7    
DCD 0x008e07a3                  ;REFRESH        
DCD 0x000000b1                 ;BANKSIZE      
DCD 0x00000030                 ;MRSRB6 
DCD 0x00000030                 ;MRSRB7
 
END
main.c:本程序文件主要实现led灯的初始化,然后四个led灯循环滚动亮5遍,xmain函数返回。
/* C语言函数 */
/* 端口F寄存器预定义 */
#define        GPBCON           (*(volatile unsigned long *)0x56000010)
#define        GPBDAT            (*(volatile unsigned long *)0x56000014)
#define       LEDS               (1<<5|1<<6|1<<7|1<<8)
#define       DELAYVAL    (0x1ffff)
extern int delay(int time);        /* 声明外部声明汇编函数 */
 
int i = 5;
int xmain()
{
         GPBCON  = 0x00015400;          //GPF4--GPF7设置为output
         while(i > 0) {
                    //第一个LED灯亮
             GPBDAT=(GPBDAT&(~LEDS)) | (1<<6|1<<7|1<<8);
              delay(DELAYVAL);              //调用汇编语言编写的延时程序
      
                    //第二个LED灯亮
             GPBDAT=(GPBDAT&(~LEDS)) | (1<<5|1<<7|1<<8);
             delay(DELAYVAL);              //调用汇编语言编写的延时程序
      
                    //第三个LED灯亮
             GPBDAT=(GPBDAT&(~LEDS)) | (1<<5|1<<6|1<<8);
             delay(DELAYVAL);                       //调用汇编语言编写的延时程序      
     
                    //第四个LED灯亮
             GPBDAT=(GPBDAT&(~LEDS)) | (1<<5|1<<6|1<<7);
             delay(DELAYVAL);                       //调用汇编语言编写的延时程序
             i--;      
    }
    return 0;
 }
 
delay.s:本程序文件主要通常汇编来实现延时功能。
;汇编指令延时程序     
EXPORT delay
AREA  DELAY,CODE,READONLY          ;该伪指令定义了一个代码段,段名为Init,属性只读
;下面是延迟子程序
delay
         sub r0,r0,#1             ;r0=r0-1           
           cmp r0,#0x0             ;将r0的值与0相比较
           bne delay                 ;比较的结果不为0(r0不为0),继续调用delay,否则执行下一条语句
           mov pc,lr                 ;返回
  
       END                             ;程序结束符
   
内存的初始化也可以用下面的C程序实现:
C语言版本:
#define       MEM_CTL_BASE               0x48000000
#define       MEM_CTL_END                0x48000034
/* SDRAM 13个寄存器的值 */
unsigned long  const    mem_cfg_val[]={         // 声明数组存放内存控制器设置数据
           0x22000000,                //BWSCON
           0x00000700,                //BANKCON0
           0x00000700,                //BANKCON1
           0x00000700,                //BANKCON2
           0x00000700,                //BANKCON3   
           0x00000700,                //BANKCON4
           0x00000700,                //BANKCON5
           0x00018005,                //BANKCON6
           0x00018005,                //BANKCON7
           0x008e07a3,                 //REFRESH(HCLK = 12MHz,该值为0x008e07a3
                                                //HCLK = 100MHz 0x008e04f5)
           0x000000b1,                //BANKSIZE
           0x00000030,                //MRSRB6
           0x00000030,                //MRSRB7
};
void mem_init(void)
{
         int    i = 0;
         unsigned long *p = (unsigned long *)MEM_CTL_BASE;
         for(; i < (MEM_CTL_END - MEM_CTL_BASE)/4; i++)
                    p[i] = mem_cfg_val[i];
}
关键字:S3C2440  SDRAM  内存驱动 引用地址:S3C2440 SDRAM内存驱动

上一篇:S3C2440 UART串口驱动
下一篇:S3C6410 时钟初始化

推荐阅读最新更新时间:2024-03-16 14:51

冲孔打桩机的自动控制系统设计
0 引言 冲孔打桩机主要由桩锤、支架、卷扬机以及其他辅助设备组成,其工作原理是利用冲孔打桩机的卷扬机构,将电动机输出动力的回转运动转变为往复运动,通过钢丝绳来带动桩锤的提升,并在一定高度时使桩锤自由下落,利用桩锤的冲击作用冲挤土层或破碎岩石,同时钻渣随泥浆(或用取渣桶)排出,最后在地基土中形成桩孔。施工人员在桩孔内放置钢筋笼,灌注混凝土而制成桩。 目前,冲孔打桩机的打桩作业均由人工手动机械式操纵来完成。操作人员在工作过程中需要频繁对离合装置、刹车装置等控制部件进行操纵,劳动强度很大。随着微电子技术和自动控制理论的发展,将自动控制技术应用于冲孔打桩机,实现打桩的全自动化或半自动化,使操作人员从繁琐重复的体力劳动中解放出来成为
[单片机]
冲孔打桩机的自动控制系统设计
ARM与SDRAM芯片的联接
通常ARM芯片内置的内存很少,要运行Linux,需要扩展内存。ARM9扩展内存使用SDRAM内存,ARM11使用 DDR SDRAM。以ARM9核心的S3C2440为例,介绍一下内存的扩展。 S3C2440通常外接32位64MBytes的SDRAM,采用两片16位256Mbits的SDRAM芯片(如HY57V561620),SDRAM芯片通过地址总线、数据总线、若干控制线与S3C2440芯片相连。 S3C2440的地址总线:27根地址线----ADDR 。 S3C2440的数据总线:32根数据线----DATA 。 S3C2440的SDRAM控制线: 1、SDRAM片选----nGCS6(对应ARM的地址0x3000 0
[单片机]
S3C2440的ADC程序
使用ADC只需要对相应的寄存器进行配置,然后启动ADC即可,启动ADC有两种方法: 1. 手动完成启动。 2. 读取上一次转换结果后自动启动下一次ADC转换。 得到ADC是否转换完成的信息的方法有两种方法: 1. 查询法:查询寄存器ADCCON的第15位(ADC的转换完成位)。 2. 中断法:转换完成后,产生ADC中断信号。 当不使用触摸屏时,与ADC相关的寄存器主要有据寄存器ADCCON和寄存器ADCDAT0。寄存器ADCCON主要用于选择ADC的启动方式、设置ADC转换时钟以及ADC转换结束标志位等。寄存器ADCDAT0中存放了ADC抓换所得的结果,ADC转换结束后,可以直接读改寄存器的值来得到转换结果。 注意:普通
[单片机]
S3C2440之UART驱动代码模板(RealView MDK)
好记心不如烂笔头,为方便以后查看代码及代码重复利用,这里贴出S3C2440 UART驱动代码。使用友善MINI2440开发板,开发环境为RealView MDK 4.22。需要注意的是,本代码中,对GPIO的初始化放在了s3c2440.s中完成,采用keil自带的html方式进行配置。 该源码结构简单明了,原始工程下载地址: 点击打开链接 UART控制器初始化: void Uart_Init(void) { #define rULCON0 (*(volatile unsigned int*)0x50000000) #define rUCON0 (*(volatile unsigned int*
[单片机]
s3c2440 移植linux内核 添加网卡支持 yaffs2文件系统支持
三、内核的移植 说明:针对的是百问网的jz2440 gcc:4.9.1 1、移植内核 首先,下载源码包:https://www.kernel.org/ 现在时间为2014年12月20日其主界面截图为: 在此,就在下较新的稳定的版本作为尝试。在这里有个命名问题需要说明一下,最前面的2.6或者3.18是主版本号码,后面的次版本号是比如2.6.32.65中的32,再后面的比如2.6.32.65中的65是升级版本号,主版本号为奇数的是开发本比如3.17,主版本号为偶数的为稳定版比如3.18,一般情况下名字后面是-rc1的是测试版。然后紧接着下载其对应版本的补丁文件(假如存在补丁文件)这里下载的源码包的名字为lin
[单片机]
<font color='red'>s3c2440</font> 移植linux内核 添加网卡支持 yaffs2文件系统支持
S3C2440开发板中SDRAM \NOR FLASH\ NAND FLASH地址分配
TQ2440 开发板的NOR FLASH是16bit数据位宽,选择从NOR FLASH启动,所以OM0接VDD,OM1接VSS,NOR FLASH接的是ngcs0,也就是接在BANK0.因为选择的NOR FLASH是2Mbyte,所以NOR FLASH的地址范围是0x0000 0000 --- 0x001f ffff。上电时,程序会从Norflash中启动,ARM直接取Norflash中的指令运行。 NAND FLASH 以页为单位读写,要先命令,再给地址,才能读到NAND的数据。NAND FLASH是接在NAND FLASH控制器上而不是系统总线上,所以没有在8个BANK中分配地址。如果S3C2440被配置成从Nand Flash
[单片机]
s3c2440的USB主机控制器
s3c2440提供了USB主机接口,它与OHCI v1.0完全兼容。要使用该功能,就必须熟悉OHCI v1.0规范;而要熟悉OHCI v1.0规范,那么还必须先熟悉USB v1.1协议。因此涉及到该部分的内容较多,要想正确使用s3c2440所提供的USB主机接口也不是一件容易的事情。在这里,我主要介绍USB设备枚举过程中所涉及到的一些知识,并给出具体的实现程序。 OHCI(Open HCI)是目前使用比较广泛的三种USB主机控制器规范之一。USB体系结构是由四个主要部分组成:客户软件/USB驱动,主机控制器驱动(HCD),主机控制器(HC)和USB驱动。前两者由软件实现,后两者由硬件实现。而OHCI就是规范了主机控制器驱动
[单片机]
基于S3C2440嵌入式系统主板的电磁兼容性设计
作者:许凯华,董淑云,刘玉华,胡立祥 华中师范大学  随着电子设备的频率越来越高,世界各国对电子产品电磁辐射标准的执行变得越来越严格,如何保证能在有限时间很好地在设计阶段发现并解决EMI/EMC问题非常重要,而PCB往往是一个电子系统的核心构成部分,一个经仔细电磁干扰设计的PCB板,能大幅度降低阻抗不匹配、传输线问题、信号互相耦合等现象引发的信号反射、延迟等线路不稳定因素,同时也可达到降低电磁辐射发射干扰,大大提高系统的稳定性和可靠性。本文将以嵌入式系统主板为平台,运用 EMIStream仿真软件,并采用源端串联端接阻抗的方法分析了解决嵌入式高速主板存在的电磁干扰问题。 1 电磁兼容性 1.1 电磁兼容和电磁干扰
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved