【10】STM32F767——————>SDRAM之W9825G6HK-6 附件有《高手进阶,终极内存技术指南——完整/进阶版》下载地址

  1. 简述:
    1. SDRAM全称(Synchronous Dynamic Random Access Memory),即同步动态随机存储器,与SRAM(静态存储器)区别:容量大、价格便宜; 
    2. STM32控制器芯片内部有一定大小的SRAM和FLASH作为内存和程序存储空间,但当程序教大RAM/ROM不够用时,就需要外扩存储器(例如8031需要外扩ROM一样); 
    3. STM32F767IGT6自带了512K字节的SRAM,扩展SDRAM主要用来跑算法、驱动led屏、GUI;
    4. F7有2个SDRAM存储驱动,可独立配置;
      1. SDNE0+SDCLKE0:存储区域1
      2. SDNE1+SDCLKE1:存储区域2
    5. 实验板采用的芯片为:W9825G6KH,32M; 4Bank; 行:A0-A12;列:A0-A8;16位数据传输;
    6. 芯片存储结构为:
      1. 行地址:8192个
      2. 列地址:512个
      3. bank数目:4个
      4. 位宽:16位
      5. 芯片容量:8192*512*16 = 64Mbit = 32MByte;
  2. FMC介绍:
    1. 简述:STM32F767使用FMC外设来管理扩展的存储器,FMC(Flexible Memory Controller),可变存储控制器,用于驱动SRAM、SDRAM、NOR FLASH、NAND FLASH类型的存储器(不支持DDR类型的SDRAM);FSMC,可变静态存储控制,不能用于驱动SDRAM这样的动态存储器,因为驱动SDRAM需要定时刷新;
    2. 存储区域:
      1. bank1 : 0xc000 0000 ------ 0xcfff ffff;
      2. bank2 : 0xd000 0000 ------ 0xdfff ffff;
    3. 初始化常用寄存器设置
      1. FMC_SDCRx: 设置SDRAM芯片功能
      2. FMC_SDCMR:设置时序;
      3. FMC_SDRTT:设置刷新频率;
    4. 框图【10】STM32F767——————>SDRAM之W9825G6HK-6 附件有《高手进阶,终极内存技术指南——完整/进阶版》下载地址_第1张图片【10】STM32F767——————>SDRAM之W9825G6HK-6 附件有《高手进阶,终极内存技术指南——完整/进阶版》下载地址_第2张图片
  3. W9825G6KH框图【10】STM32F767——————>SDRAM之W9825G6HK-6 附件有《高手进阶,终极内存技术指南——完整/进阶版》下载地址_第3张图片
  4. 电气连接
    1. FMC:A0-12 ------> SDRAM:A0 ------>A12;地址线:行/列
    2. FMC:BA0,BA1(或者叫A14,A15) ------> SDRAM:BA0,BA1; bank地址线
    3. FMC:D0-D15 ------>SDRAM:D0 ------>D15; 数据线
    4. FMC:SDCKE0 ------>SDRAM:CKE  时钟使能
    5. FMC:SDNE0 ------>SDRAM:CS(4、5决定用哪个bank)芯片使能
    6. FMC:SDCLK ------>SDRAM:CLK时钟线 同步时钟信号
    7. FMC:SDNWE ------>SDRAM:WE  写入使能
    8. FMC:SDNCAS ------>SDRAM:CAS  列选通
    9. FMC:SDNRAS ------>SDRAM:RAS  行选通
    10. FMC:NBL1 ------>SDRAM:UDQM    
    11. FMC:NBL0 ------>SDRAM:LDQM   10、11 数据掩码,表示DQ的有效部分
  5. 存储单元
    1. SDRAM的存储单元(bank)是以阵列的形式排列的; 如下图所示:
    2. 存储框图【10】STM32F767——————>SDRAM之W9825G6HK-6 附件有《高手进阶,终极内存技术指南——完整/进阶版》下载地址_第4张图片【10】STM32F767——————>SDRAM之W9825G6HK-6 附件有《高手进阶,终极内存技术指南——完整/进阶版》下载地址_第5张图片
    3. 功能分析:
      1. SDRAM寻址原理:将存储阵列看成一个表格,通过行/列地址确定唯一位置(矩阵键盘);
      2. 常见的SDRAM都有4个bank,寻址时要先指定bank号、行地址、列地址,才能找到目标地址;  
    4. 寻址过程:
      1. 首先RAS拉低,行地址有效,地址线A0~A12所表示的地址会被锁存在行地址译码器里面,bank地址线上的BS0,BS1表示选择的bank地址,对应相应的bank;
      2. CAS拉低,列地址有效,地址线A0~A12所表示的地址会被锁存在列地址译码器里面; 这样就完成一次寻址操作; 
    5. 数据传输
      1. 是用8位、16位数据传输
      2. LDQM(DQM0):低电平时D[7:0]数据有效; 
      3. UDQM(DQM1):低电平时D[15:0]数据有效; 
    6. SDRAM常用命令
      1. 命令禁止:CS高电平,停止新命令,不能停止当前正在执行的命令; 
      2. 空操作:用于选中SDRAM,防止SDRAM接受错误指令,以便接下来发送命令; 
      3. 行有效:
      4. 列有效:
        1. 读:WE:高,
        2. 写:WE:低
      5. 预充电(PRECHARGE):用于关闭bank中所打开的行地址,由于SDRAM的寻址具有独占性,所以在进行完读写操作后,如果要对同一bank的另一行进行寻址,就要将原来有效(打开)的行关闭,重新发送行/列地址; bank关闭现有行,准备打开新行的操作就叫做预充电(precharge)
      6. 刷新(refresh),用于刷新一行数据; SDRAM里面存储的数据,需要不断的进行刷新操作才能保留住,刷新命令对于SDRAM尤为重要;预充电和刷新都可以实现对SDRAM数据的刷新,不过预充电仅对当前打开的行有效(仅刷新当前行); 刷新命令:可以依次对所有的行进行刷新操作
        1. 自动刷新:
        2. 自我刷新:休眠模式低功耗状态下的数据保存,CKE(低电平)进入自我刷新模式; CKE(高)退出自我刷新; 
      7. 模式寄存器(Mode Register Set):每次SDRAM初始化都要用到; 【10】STM32F767——————>SDRAM之W9825G6HK-6 附件有《高手进阶,终极内存技术指南——完整/进阶版》下载地址_第6张图片
        1. 突发传输技术:只要指定起始列地址和突发长度 ,内存就会依次地自动对后面相应数量的存储单元进行读/写操作,而不需要控制器连续地提供列地址 ;这样除了第一个数据的传输需要若干个周期外,其后面每个数据只需要一个周期即可获得;
        2. 突发长度(Burst Length):BL : 可选项:1、2、4、8 Full Page; 常见设定1;
        3. 突发访问地址模式(Addresssing Mode):可以设置为顺序(sequential)和交错(interleave,地址是乱序的);一般选择顺序
        4. 列地址选通延迟(CAS Latency)CL:一般设置2/3个时钟周期,注意列地址选通延迟(CL)仅在读命令有效,写命令不需要; 
        5. 写模式(Wrete Mode):设置单次写的模式,可以选择突发写入或者单次写入; 
  6. 软件流程
    1. SDRAM初始化
      1. 框图【10】STM32F767——————>SDRAM之W9825G6HK-6 附件有《高手进阶,终极内存技术指南——完整/进阶版》下载地址_第7张图片
      2. 上电,提供不少于100us的时钟
      3. 发送nop命令
      4. 发送预充电(precharge)命令,控制所有bank进行预充电,并等待Trp(依据芯片手册设置为:2,芯片是15ns,时钟周期:9.25ns)时间;
      5. 发送至少2个自动刷新(auto refresh)命令,每个命令后需等待Trc时间,通常设置为7;
      6. 发送加载模式寄存器(load mode register )命令,配置SDRAM的工作参数,并等待Tmrd时间,表示加载模式寄存器命令行后的延迟; 通常设置为:2;
      7. 初始化完成,下一步读写初始化; 上述参数可通过数据手册找到; 
      8. 【10】STM32F767——————>SDRAM之W9825G6HK-6 附件有《高手进阶,终极内存技术指南——完整/进阶版》下载地址_第8张图片
      9.  /*********************************************************
         * 函数名:BSP_SDRAM_Init()
         * 描述  :
         * 输入  :无
         * 输出  :无
         * 返回  :无 
         * 调用  :内部调用 
         **********************************************************/
        void BSP_SDRAM_Init(void)
        {
        	 /*##-1- Configure the SDRAM device #########################################*/
        	 /* SDRAM device configuration */
        	 FMC_SDRAM_TimingTypeDef  FMC_SDRAM_TimingInitStructure;
        	  
        	 FMC_SDRAM_TimingInitStructure.LoadToActiveDelay    = 2;    //加载模式寄存器到激活时间的延迟为2个时钟周期
        	 FMC_SDRAM_TimingInitStructure.ExitSelfRefreshDelay = 8;    //退出自刷新延迟为8个时钟周期
        	 FMC_SDRAM_TimingInitStructure.SelfRefreshTime	   = 6;     //自刷新时间为6个时钟周期                      
        	 FMC_SDRAM_TimingInitStructure.RowCycleDelay 	   = 6;     //行循环延迟为6个时钟周期
        	 FMC_SDRAM_TimingInitStructure.WriteRecoveryTime    = 2;    //恢复延迟为2个时钟周期
        	 FMC_SDRAM_TimingInitStructure.RPDelay			   = 2;     //行预充电延迟为2个时钟周期
        	 FMC_SDRAM_TimingInitStructure.RCDDelay			   = 2;     //行到列延迟为2个时钟周期
        	 
             SDRAM_Handle_InitStructure.Instance                = FMC_SDRAM_DEVICE;                     //SDRAM在BANK5,6  
        	 SDRAM_Handle_InitStructure.Init.SDBank 			= FMC_SDRAM_BANK1;                      //SDRAM接在BANK5上
        	 SDRAM_Handle_InitStructure.Init.ColumnBitsNumber	= FMC_SDRAM_COLUMN_BITS_NUM_9;          //列数量
        	 SDRAM_Handle_InitStructure.Init.RowBitsNumber		= FMC_SDRAM_ROW_BITS_NUM_13;            //行数量
        	 SDRAM_Handle_InitStructure.Init.MemoryDataWidth	= FMC_SDRAM_MEM_BUS_WIDTH_16;           //数据宽度为16位
        	 SDRAM_Handle_InitStructure.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;         //一共4个BANK
        	 SDRAM_Handle_InitStructure.Init.CASLatency 		= FMC_SDRAM_CAS_LATENCY_3;              //CAS为3
        	 SDRAM_Handle_InitStructure.Init.WriteProtection	= FMC_SDRAM_WRITE_PROTECTION_DISABLE;   //失能写保护
        	 SDRAM_Handle_InitStructure.Init.SDClockPeriod		= FMC_SDRAM_CLOCK_PERIOD_2;             //SDRAM时钟为HCLK/2=216M/2=108M=9.3ns
        	 SDRAM_Handle_InitStructure.Init.ReadBurst			= FMC_SDRAM_RBURST_ENABLE;              //使能突发
        	 SDRAM_Handle_InitStructure.Init.ReadPipeDelay		= FMC_SDRAM_RPIPE_DELAY_1;              //读通道延时
        	 
        	 /* Initialize the SDRAM controller */
        	 HAL_SDRAM_Init(&SDRAM_Handle_InitStructure, &FMC_SDRAM_TimingInitStructure);
        
        	 /* Program the SDRAM external device */
        	 BSP_SDRAM_Initialization_Sequence(&SDRAM_Handle_InitStructure);    //发送初始化序列命令,设置模式寄存器; 
        }
        
        /*********************************************************
         * 函数名:BSP_SDRAM_Initialization_Sequence()
         * 描述  :发送初始化序列命令,设置模式寄存器
         * 输入  :无
         * 输出  :无
         * 返回  :无 
         * 调用  :内部调用 
         **********************************************************/
         void BSP_SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram)
        {
            u32 temp = 0;
            //初始化完成,还需设置操作序列; 模式寄存器; 
            
            BSP_SDRAM_SendCmd(0,FMC_SDRAM_CMD_CLK_ENABLE,1,0);//bank1,时钟使能,刷新次数,
            delay_us(500);  //不低于100us;
            BSP_SDRAM_SendCmd(0,FMC_SDRAM_CMD_PALL,1,0);//对所有存储区预充电
            BSP_SDRAM_SendCmd(0,FMC_SDRAM_CMD_AUTOREFRESH_MODE,8,0);//设置自刷新次数; 
            
            /*配置:1:访问长度;        [2:0]
                    2:访问类型          [3]
                    3:CAS周期值         [6:4]
                    4:运行模式          [8:7]
                    5:突发写模式        [9]     
                    6:保留位            [11:10]    */
            temp=(u32)SDRAM_MODEREG_BURST_LENGTH_1      |	//设置突发长度:1(可以是1/2/4/8)
                  SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |	//设置突发类型:连续(可以是连续/交错)
                  SDRAM_MODEREG_CAS_LATENCY_3           |	//设置CAS值:3(可以是2/3)
                  SDRAM_MODEREG_OPERATING_MODE_STANDARD |   //设置操作模式:0,标准模式
                  SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;     //设置突发写模式:1,单点访问
            
            BSP_SDRAM_SendCmd(0,FMC_SDRAM_CMD_LOAD_MODE,1,temp);   //设置SDRAM的模式寄存器
        
            //刷新频率计数器(以SDCLK频率计数),计算方法:
        	//COUNT=SDRAM刷新周期/行数-20=SDRAM刷新周期(us)*SDCLK频率(Mhz)/行数
            //我们使用的SDRAM刷新周期为64ms,SDCLK=216/2=108Mhz,行数为8192(2^13).
        	//所以,COUNT=64*1000*108/8192-20=825.75;
            HAL_SDRAM_ProgramRefreshRate(&SDRAM_Handle_InitStructure,824);      //中文参考手册P365;
        }
        
        /*********************************************************
         * 函数名:BSP_SDRAM_SendCmd(u8 bankx, u8 cmd , u8 refresh, u16 regval)
         * 描述  :简化设置模式寄存器程序;
                    1、bankx:0:  bank5发送命令
                              1:  bank6发送命令
                    2、cmd指令:
                            第一次调用:SDRAM时钟使能
                              二      :所有存储区预充电
                              三      :自动刷新次数
                              四      :设置模式寄存器
                              五      :自刷新
         * 输入  :无
         * 输出  :无
         * 返回  :无 
         * 调用  :内部调用 
         **********************************************************/
         u8 BSP_SDRAM_SendCmd(u8 bankx, u8 cmd , u8 refresh, u16 regval)
        {   
            u32 target_bank = 0;
            FMC_SDRAM_CommandTypeDef    FMC_SDRAM_CommandInitStructure;
            
            if(bankx == 0)
                target_bank = FMC_SDRAM_CMD_TARGET_BANK1;
            if(bankx == 1)
                target_bank = FMC_SDRAM_CMD_TARGET_BANK2;
            
            FMC_SDRAM_CommandInitStructure.CommandMode              =   cmd;            //命令
            FMC_SDRAM_CommandInitStructure.CommandTarget            =   target_bank;    //目标bank
            FMC_SDRAM_CommandInitStructure.AutoRefreshNumber        =   refresh;        //自刷新次数
            FMC_SDRAM_CommandInitStructure.ModeRegisterDefinition   =   regval;         //要写入模式寄存器的值
            
            if(HAL_SDRAM_SendCommand(&SDRAM_Handle_InitStructure,&FMC_SDRAM_CommandInitStructure,0x1000) == HAL_OK)
                return 0;
            else
                return 1;
        }

         

    2. 写操作
      1. 框图【10】STM32F767——————>SDRAM之W9825G6HK-6 附件有《高手进阶,终极内存技术指南——完整/进阶版》下载地址_第9张图片
      2. 发送激活命令:此命令同时发送行地址和bank地址,发送该命令后,需要等待Trcd(据芯片手册设置为:2,芯片是15ns,时钟周期:9.25ns)时间,才可以发送写命令; 
      3. 写命令:发送写命令的同时,设置列地址,完成对SDRAM的寻址,同时将数据 通过DQ数据线,存入SDRAM;
      4. 使能自动预充电:发送写命令的同时,拉高A10地址线,使能自动预充电以提高读写效率
      5. 执行预充电:预充电在发送激活命令的Tras时间后启动,并且需要等待Trp时间,来完成
      6. 完成一次数据 写入:最后发送第二个激活命令,启动下一次数据传输,这样就完成了一次数据的读取
    3. 读操作
      1. 框图【10】STM32F767——————>SDRAM之W9825G6HK-6 附件有《高手进阶,终极内存技术指南——完整/进阶版》下载地址_第10张图片
      2. 发送激活命令:此命令同时发送行地址和bank地址,发送该命令后,需要等待Trcd(据芯片手册设置为:2,芯片是15ns,时钟周期:9.25ns)时间,才可以发送写命令; 
      3. 读命令:发送读命令的同时,设置列地址,完成对SDRAM的寻址; 读操作还有一个CL延迟(CAS Latency),所以需要等待给定的CL延迟(2或3个clk)后,再从DQ数据线上读取数据;
      4. 使能自动预充电:发送写命令的同时,拉高A10地址线,使能自动预充电以提高读写效率
      5. 执行预充电:预充电在发送激活命令的Tras时间后启动,并且需要等待Trp时间,来完成
      6. 完成一次数据 写入:最后发送第二个激活命令,启动下一次数据传输,这样就完成了一次数据的读取;
  7. 读/写例程:
    /*********************************************************
     * 函数名:BSP_FMC_SDRAM_WriteBuffer(u8 *pBuffer,u32 WriteAddr,u32 n);
     * 描述  :在指定地址(SDRAM_BANK_ADDR + WriteAddr)处连续写入数据
                1、pBuffer:字节地址
                2、WriteAddr:要写入的地址
                3、写入的字节数
     * 输入  :无
     * 输出  :无
     * 返回  :无 
     * 调用  :内部调用 
     **********************************************************/
     void BSP_FMC_SDRAM_WriteBuffer(u8 *pBuffer,u32 WriteAddr,u32 n)
     {
         for(;n!=0;n--)
         {
            *(vu8*)(BSP_SDRAM_BANK5_ADDR + WriteAddr) = *pBuffer;
             WriteAddr ++;
             pBuffer ++;
         }
     }
    
    /*********************************************************
     * 函数名:BSP_FMC_SDRAM_ReadBuffer(u8 *pBuffer,u32 ReadAddr,u32 n);
     * 描述  :在指定地址(SDRAM_BANK_ADDR + WriteAddr)处连续读出数据
                1、pBuffer:字节地址
                2、WriteAddr:要读出的地址
                3、写入的字节数
     * 输入  :无
     * 输出  :无
     * 返回  :无 
     * 调用  :内部调用 
     **********************************************************/
     void BSP_FMC_SDRAM_ReadBuffer(u8 *pBuffer,u32 ReadAddr,u32 n)
     {
         for(;n!=0;n--)
         {
            *pBuffer++ = *(vu8*)(BSP_SDRAM_BANK5_ADDR + ReadAddr);
             ReadAddr++;  
         }
     }

     

  8. 总结:仍需努力; 
  9. 参考资料
    1. 正点原子:STM32F7 开发指南(HAL 库版)
    2. 野火:STM32 HAL 库开发实战指南
    3. 《高手进阶,终极内存技术指南——完整/进阶版》免费下载地址http://www.armbbs.cn/forum.php?mod=viewthread&tid=1930
    4. 官方例程:STM32Cube_FW_F7_V1.4.0

你可能感兴趣的:(STM32F7)