欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第6课,SDRAM

程序员文章站 2022-04-01 22:07:35
...

注:以下内容学习于韦东山老师arm裸机第一期****

如果想要完全了解SDRAM,参考: 高手进阶,终极内存技术指南-完整/进阶版

    一.SDRAM的访问方法

        1.1 SDRAM结构图

            第6课,SDRAM
            a.由4个BANK组成,可以看作是表格
            b.里面的每个格子有16位数据(2440接有两片SDRAM,每一片提供16位数据)
            c.访问时,需要先发出片选信号选中SDRAM,然后发出BANK信号选中哪个BANK,最后发出行地址和列地址(这些信号都是由内存控制器发出)
            

        1.2 内存控制器执行流程

            假设当CPU执行 ldr r0, =0x30000000

                          ldr r1, [r0] /* 读内存的数据 */

                          

            1.2.1 CPU将地址发送给内存控制器

            1.2.2 内存控制器根据地址发出片选信号nGCS6

            1.2.3 根据接的类型是SDRAM,拆分地址

                    a.BANK地址
                    b.发出行地址
                    c.发出列地址
                    (需要去设置每个地址有多少地址条,设置内存控制器中的相关寄存器)

            1.2.4 读取数据

        

    二.内存控制器中相关寄存器的设置

        2.1 设置BWSCON寄存器,如下图        (最终设置为0x22000000)

          第6课,SDRAM

            我们只需要设置BANK6    

            2.1.1 DW6 [25:24] Determines data bus width for bank 6(决定bank6的位宽)
                              00 = 8-bit 01 = 16-bit, 10 = 32-bit 11 = reserved

                  我们使用两个16位的芯片拼接成32位的,因此设置为10

            2.1.2 WS6 [26] Determines WAIT status for bank 6.(决定bank6的等待信号)
                           0 = WAIT disable, 1 = WAIT enable                  
                  假设CPU的读写速度很慢,CPU发出读写命令后,内存芯片没有在规定时间准备好数据,可以向CPU发出wait信号,请求CPU宽限一点时间,我们用不到
                  设置为0

            
            2.1.3 ST6 [27] Determines SRAM for using UB/LB for bank 6.(决定SRAM是否使用UB/LB引脚)
                            0 = Not using UB/LB (The pins are dedicated nWBE[3:0)(nWBE表示写某个字节的时候是否真正写进去)
                            1 = Using UB/LB (The pins are dedicated nBE[3:0])(读/写字节的时候都可以使用nBE[3:0]这个引脚来决定是否使用这个byte)

        我们的内存是32位的,如果我们想要修改某个字节,仍然需要提供4个字节的数据,这时便需要通过nWBE[3:0](SDRAM中的L_nWBE[3:0])

         当想要读一个字节的时候,仍然会读到32位的数据,会从中挑出需要的字节(具体方法在上一节中提到过).因此不需要nBE来屏蔽某一个字节

          因此对于SDRAM,我们选择为0       


            

        2.2 设置BANKCON6寄存器,如下图   (最终设置为0x18001)

                第6课,SDRAM
            设置该寄存器对照时序图如下:    
                第6课,SDRAM
            2.2.1 MT [16:15] Determine the memory type for bank6 and bank7.(决定bank6,bank7外面接的是ROM还是RAM还是SDRAM,如果是SDRAM就会将地址拆分)
                    00 = ROM or SRAM             01 = Reserved (Do not use)
                    10 = Reserved (Do not use)  11 = Sync. DRAM

                    我们外接的SDRAM,设置为11

            

            Memory Type = ROM or SRAM [MT=00] (15-bit)

            下面的15位是为ROM或者SRAM准备的,可以跳过

            
            
            2.2.2 Tacs [14:13] Address set-up time before nGCS (地址信号发出多久之后发出片选信号)
                    00 = 0 clock 01 = 1 clock 10 = 2 clocks 11 = 4 clocks
                    
            2.2.3 Tcos [12:11] Chip selection set-up time before nOE (片选信号发出多久之后发出读信号)
                    00 = 0 clock 01 = 1 clock 10 = 2 clocks 11 = 4 clocks
            
            2.2.4 Tacc [10:8] Access cycle(读一个周期消耗的时间)
                    000 = 1 clock     001 = 2 clocks
                    010 = 3 clocks    011 = 4 clocks
                    100 = 6 clocks     101 = 8 clocks
                    110 = 10 clocks 111 = 14 clocks
                    
            2.2.5 Tcoh [7:6] Chip selection hold time after nOE(读信号失效后片选信号持续多长时间)
                    00 = 0 clock 01 = 1 clock
                    10 = 2 clocks 11 = 4 clocks
                    
            2.2.6 Tcah [5:4] Address hold time after nGCSn(片选信号失效后地址信号持续多长时间)
                    00 = 0 clock 01 = 1clock 10 = 2 clocks 11 = 4 clocks
                    
            2.2.7 Tacp [3:2] Page mode access cycle @ Page mode(页模式读一个周期消耗的时间)
                    00 = 2 clocks 01 = 3 clocks
                    10 = 4 clocks 11 = 6 clocks
            
            PMC [1:0] Page mode configuration(页模式的配置)
                    00 = normal (1 data)         01 = 4 consecutive accesses
                    10 = 8 consecutive accesses 11 = 16 consecutive accesses

            Memory Type = SDRAM [MT=11] (4-bit)(下面的4位是为SDRAM准备的,我们只需要设置这4位)


 
           Trcd [3:2] RAS to CAS delay(RAS->CAS,内存控制器先发出行地址再发出列地址,两个地址的间隔delay)
                    00 = 2 clocks 01 = 3 clocks 10 = 4 clocks         

                根据芯片手册来设置,搜索Trcd,找到下图

                第6课,SDRAM

                可以设置为20ns,2440的HCLK=100MHZ,t = 10ns,因此可以设置为2clocks,设置为00

                
            SCAN [1:0] Column address number(设置列地址占据多少位,bank有4个肯定占据2位,剩下的就是行地址)
                    00 = 8-bit 01 = 9-bit 10= 10-bit      

                根据芯片手册来选择,在芯片手册上说明A0-A8表示列地址,9位,如下图:

                第6课,SDRAM

                ,因此设置为01

                

        2.3 设置REFRESH寄存器(在使用过程中需要不断的刷新SDRAM,否则数据会丢失),如下图: 最终设置为0x8404f5

            第6课,SDRAM
            SCAN [1:0] Column address number(设置列地址占据多少位,bank有4个肯定占据2位,剩下的就是行地址)
                    00 = 8-bit 01 = 9-bit 10= 10-bit 

                    设置为1,使能SMRAM的刷新

            
            2.3.2 TREFMD [22] SDRAM Refresh Mode(SDRAM刷新模式)
                        0 = CBR/Auto Refresh
                        1 = Self Refresh
                            In self-refresh time, the SDRAM control signals are driven to the
                            appropriate level.                    

                    设置为0,自动刷新

            
            2.3.3 Trp [21:20] SDRAM RAS pre-charge Time(行地址信号的冲电时间)
                        00 = 2 clocks 01 = 3 clocks 10 = 4 clocks 11 = Not support

                        在芯片手册搜索Trp中有如下图:

           第6课,SDRAM

                       我们设置为trp >= 20ns即可,2440的HCLK=100MHZ,t = 10ns,因此可以设置为2clocks,设置为00

        
            2.3.4 Tsrc [19:18] SDRAM Semi Row cycle time(SDRAM行周期时间)
                        00 = 4 clocks 01 = 5 clocks 10 = 6 clocks 11 = 7 clocks
                        SDRAM Row cycle time: Trc=Tsrc+Trp
                        If Trp = 3clocks & Tsrc = 7clocks, Trc = 3+7=10clocks.
                

                        在芯片手册中搜索不到Tsrc,但是给了一个公式Trc=Tsrc+Trp,因此在芯片手册中搜索Trc,如下图:

                            第6课,SDRAM

                        我们可以取63ns,Tsrc = Trp - Trc = 63 - 20 = 43ns

                        因此我们可以设置为01,表示5clocks

                                     
            2.3.5 Reserved [17:16] Not used 00
                  Reserved [15:11] Not used 0000            

            2.3.6 Refresh Counter [10:0] SDRAM refresh count value.(刷新周期值)
                                        Refer to chapter 6 SDRAM refresh controller bus priority section.(参见芯片手册第6章SDRAM刷新控制器总线优先级部分)
                                        Refresh period = (211-refresh_count+1)/HCLK    (刷新周期 = 211 - refresh_count+1 ==>refresh_count = 211 + 1 -  刷新周期)
                                        
                                        Ex) If refresh period is 7.8 us and HCLK is 100MHz,(假设刷新周期=7.8us,HCLK=100MHZ)
                                        the refresh count is as follows:
                                        Refresh count = 211 + 1 - 100x7.8 = 1269
                 

                  在芯片手册中找到下图:

                    第6课,SDRAM

                  指明了64ms刷新8192次,因此刷新周期= 64 / 8192 = 7.8,因此Refresh count = 211 + 1 - 100x7.8 = 1269

                  

        2.4 设置BANKSIZE寄存器,如下图:        最终设置为0xb1

                第6课,SDRAM
              2.4.1 BURST_EN [7] ARM core burst operation enable.(ARM核突发操作使能,即一次访问多个字节)
                            0 = Disable burst operation.
                            1 = Enable burst operation.                            

                            设置为1,使能

                            
              2.4.1 BURST_EN [7] ARM core burst operation enable.(ARM核突发操作使能,即一次访问多个字节)
                            0 = Disable burst operation.
                            1 = Enable burst operation.

                            设置为1,使能SDRAM休眠模式

                            
                2.4.4 SCLK_EN [4] SCLK is enabled only during SDRAM access cycle for reducing
                            power consumption. When SDRAM is not accessed, SCLK
                            becomes 'L' level.
                            0 = SCLK is always active.
                            1 = SCLK is active only during the access (recommended).

                            1是推荐值,设置为1,可以减少SDRAM的功耗

                
                2.4.5 Reserved [3] Not used
                
                2.4.6 BK76MAP [2:0] BANK6/7 memory map(BANK6/7内存映射)
                            010 = 128MB/128MB 001 = 64MB/64MB
                            000 = 32M/32M 111 = 16M/16M
                            110 = 8M/8M 101 = 4M/4M
                            100 = 2M/2M               

                        我们接了两个SDRAM,组成了64M的内存,因此要设置为001,64MB

                        

        2.5 设置MRSRB6寄存器,如下图:    最终设置为0x20

            第6课,SDRAM
            2.5.1 Reserved [11:10] Not used
            
            2.5.2 WBL [9] Write burst length(突发访问长度)
                    0: Burst (Fixed)
                    1: Reserved
                    设置为0,固定的突发访问的长度
                    
            2.5.3 TM [8:7] Test mode
                    00: Mode register set (Fixed)
                    01, 10 and 11: Reserved          
                    设置为00
                    
            2.5.4 CL [6:4] CAS latency
                    000 = 1 clock, 010 = 2 clocks, 011=3 clocks
                    Others: reserved
                    内存控制器读SDRAM,发出BANK地址,行地址,列地址,对于SDRAM需要等一会才有数据
                    在芯片手册上有下图:
                    第6课,SDRAM
                    需要等待2或者3个clocks,我们可以选择第2个或者第三个clocks,这个值会发给SDRAM,这个值会保存在SDRAM中的MR(Mode Register)中,
                    以后就会在收到列地址后等待这些时间再向2440返回数据


            2.5.5 BT [3] Burst type
                    0: Sequential (Fixed)
                    1: Reserved            

                    设置为0

            
            2.5.6 BL [2:0] Burst length
                    000: 1 (Fixed)
                    Others: Reserved 

                    设置为0

                    

    三.SDRAM程序编写

    
#include "s3c2440_soc.h"

void SdramInit(void)
{
	/* BWSCON = (0x2 << 24) | (0x2 << 28)*/
	BWSCON = 0x22000000;

	/* BANKCON6 = (0x3 << 15) | (0x1 << 0) */
	BANKCON6 = 0x18001;

	/* BANKCON6 = (0x3 << 15) | (0x1 << 0) */
	BANKCON7 = 0x18001;

	/* REFRESH = (1 << 23) | (1 << 18) | (1269 << 0) */
	REFRESH = 0x8404f5;

	/* BANKSIZE = (1 << 7) | (1 << 5) | (1 << 4) | (1 << 0) */ 
	BANKSIZE = 0xb1;

	/* MRSRB6 = (2 << 4) */
	MRSRB6 = 0x20;
	
	
}

int SdramTest(void)
{
	int i;
	volatile unsigned char *p = (volatile unsigned char *)0x30000000;

	for (i = 0; i < 250; i++)
		p[i] = 55;		

	for (i = 0; i < 250; i++)
	{
		if (p[i] == 55)
			return 0;
	}

	return -1;	
}