嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

本文主要是通过迁移的思维,记录本人初次使用NXP MCUXpresso SDK API进行BSP开发

MCUXpresso SDK SEMC API 接口链接
  在MCUXpresso SDK 框架下提供了对SEMC DDR进行操作的接口。
学习链接:https://community.nxp.com/t5/MCUXpresso-Community-Articles/i-MX-RT-memory-validation/ba-p/1130828

1. 首先阅读原理图

嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

DDR芯处使用IS42S32800J-6BLA1从手册上可以看得出来该芯片支持的最大工作时钟为166Mhz.
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

但是从MCU的手册上可以看出其支持的最大速率为200Mhz.
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

2. SDK api 应用

2.1 引脚配置

引脚复用配置

2.2 时钟配置

嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

从上图可以看到时钟源从SYM_PLL2_528Mhz至SYS_PLL2_PFD1(594Mhz)再通过4分频获取148.5MHz的时钟。
相关的配置代码如下所示:
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

2.3 外设配置

对DDR的初始化,还是需要有前置知识的,了解DDR的工作时钟、时序相关知识,以及初始化的状态机。
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

进入SEMC DDR的配置界面,如下所示:
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

第一,需要选择DDR的时钟源及其频率
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

第二,需要DDR的数据锁存模式,我们选择DQS模式。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

第三、需要配置片选信号,这个和硬件设计相关
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

第四、需要配置内存的物理起始位置,这个和MCU的地址分配相关。
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
第五、需要配置内存的容量,和所选的SDRAM芯片容量保持一致。
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

第六、配置SDRAM数据线的宽度及突发长度,数据宽度从原理图上可以看出来。突发长度可以从SDRAM手册上找到。
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
第七、配置列地址线的个数及CAS。列地址线的个数可以从手册上找出来,CAS可以选择2或者3也是在手册上的。
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

第八、预充电(Precharge)至有效(active)的等待时间tRP,在166MHz,从手册上查得该数值>=18
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
第九、Active Command To Read / Write Command Delay Time (tRCD)
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

第十、刷新恢复时间 取tRFC/tXSR当中的最大值。
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

第十一、写恢复(write recovery)时间 tWR
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

第十二、CKE off minimun time, 一般取tRAS
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
第十三、active to precharge, 取tRAS
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

第十四、self refresh reovery time 自刷新恢复时间,取tXSR
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
第十五、refresh to refresh wait time 刷新至刷新的等待时间,取tRC.
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
第十六、active to active wait time 有效至有效的等待时间, 取tRC = tRAS + tRP = tRCD + tWR + tRP
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
第十七、prescaler timer period, 取160个tCLK时钟周期

160 *  1000000000 / semc_clk = 160 * 1000000000 / 148500000

嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)
第十八、sdram idle time 必须小于 tRAS, 而tRAS的最大值为100000ns
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

且有一个限制条件:
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

周期为 tPrescalePeriod_Ns = 160*100000000/semc_clk
ITO* 160  * 1000000000 / 148500000  < 100000,
ITO  < 92.812

ITO取值意义如下,所以我们取[1,92]
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

第十九:refresh timer period /refresh upgent period, 从手册上可以看到刷新4096次,总用耗时64ms,每次的刷新时间为 64*1000000/4096,两者相同值。
嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

嵌入式实操----基于RT1170 使能SEMC配置SDRAM功能(八)

2.4 验证测试

SDRAM 时钟配置成148.5Mhz:

Index: D:/svn/SDK_2.8.0_MIMXRT1170-EAR3/boards/easyarm-rt1170-revb/driver_examples/semc/sdram/cm7/clock_config.c
===================================================================
--- D:/svn/SDK_2.8.0_MIMXRT1170-EAR3/boards/easyarm-rt1170-revb/driver_examples/semc/sdram/cm7/clock_config.c	(revision 7)
+++ D:/svn/SDK_2.8.0_MIMXRT1170-EAR3/boards/easyarm-rt1170-revb/driver_examples/semc/sdram/cm7/clock_config.c	(working copy)
@@ -136,7 +136,7 @@
     CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd1, 16);
     /* Configure Semc using SysPll2Pfd1 divided by 3 */
     rootCfg.mux = kCLOCK_SEMC_ClockRoot_MuxSysPll2Pfd1;
-    rootCfg.div = 3;
+    rootCfg.div = 4;
     CLOCK_SetRootClock(kCLOCK_Root_Semc, &rootCfg);
 #endif

最终针对148.5Mhz时钟的SDRAM配置代码如下所示:

status_t BOARD_InitSEMC(void)
{
    semc_config_t config;
    semc_sdram_config_t sdramconfig;
    uint32_t clockFrq = EXAMPLE_SEMC_CLK_FREQ;

    /* Initializes the MAC configure structure to zero. */
    memset(&config, 0, sizeof(semc_config_t));
    memset(&sdramconfig, 0, sizeof(semc_sdram_config_t));

    /* Initialize SEMC. */
    SEMC_GetDefaultConfig(&config);
    config.dqsMode = kSEMC_Loopbackdqspad; /* For more accurate timing. */
    SEMC_Init(SEMC, &config);

    /* Configure SDRAM. */
    sdramconfig.csxPinMux           = kSEMC_MUXCSX0;
    sdramconfig.address             = 0x80000000;
    sdramconfig.memsize_kbytes      = 32 * 1024; /* 32MB = 32*1024*1KBytes*/
    sdramconfig.portSize            = kSEMC_PortSize32Bit;
    sdramconfig.burstLen            = kSEMC_Sdram_BurstLen8;
    sdramconfig.columnAddrBitNum    = kSEMC_SdramColunm_9bit;
    sdramconfig.casLatency          = kSEMC_LatencyThree;
    sdramconfig.tPrecharge2Act_Ns   = 18; /* Trp 18ns */
    sdramconfig.tAct2ReadWrite_Ns   = 18; /* Trcd 18ns */
    sdramconfig.tRefreshRecovery_Ns = 70; /* Use the maximum of the (Trfc , Txsr). */
    sdramconfig.tWriteRecovery_Ns   = 12; /* 12ns */
    sdramconfig.tCkeOff_Ns =
        42; /* The minimum cycle of SDRAM CLK off state. CKE is off in self refresh at a minimum period tRAS.*/
    sdramconfig.tAct2Prechage_Ns       = 42; /* Tras 42ns */
    sdramconfig.tSelfRefRecovery_Ns    = 70;
    sdramconfig.tRefresh2Refresh_Ns    = 60;
    sdramconfig.tAct2Act_Ns            = 60;
    sdramconfig.tPrescalePeriod_Ns     = 160 * (1000000000 / clockFrq);
    sdramconfig.refreshPeriod_nsPerRow = 64 * 1000000 / 4096; /* 64ms/8192 */
    sdramconfig.refreshUrgThreshold    = sdramconfig.refreshPeriod_nsPerRow;
    sdramconfig.refreshBurstLen        = 1;
    sdramconfig.delayChain             = 2;
   sdramconfig.tIdleTimeout_Ns        = 92;

    return SEMC_ConfigureSDRAM(SEMC, kSEMC_SDRAM_CS0, &sdramconfig, clockFrq);
}

测试结果如下所示:

 SEMC SDRAM Example Start!

 EXAMPLE_SEMC_CLK_FREQ:  148500000 

 SEMC SDRAM Write 32 bit Start, Start Address 0x80000000, Data Length 8388607 !

 SEMC SDRAM Read 32 bit Data Start, Start Address 0x80000000, Data Length 8388607 !

 SEMC SDRAM Write 32 bit Start, Start Address 0x80000001, Data Length 8388607 !

 SEMC SDRAM Read 32 bit Data Start, Start Address 0x80000001, Data Length 8388607 !

 SEMC SDRAM Write 32 bit Start, Start Address 0x80000002, Data Length 8388607 !

 SEMC SDRAM Read 32 bit Data Start, Start Address 0x80000002, Data Length 8388607 !

 SEMC SDRAM Write 32 bit Start, Start Address 0x80000003, Data Length 8388607 !

 SEMC SDRAM Read 32 bit Data Start, Start Address 0x80000003, Data Length 8388607 !

 SEMC SDRAM 32 bit Data Write and Read Compare Succeed!

 SEMC SDRAM Write 16 bit Start, Start Address 0x80000000, Data Length 16777215 !

 SEMC SDRAM Read 16 bit Data Start, Start Address 0x80000000, Data Length 16777215 !

 SEMC SDRAM Write 16 bit Start, Start Address 0x80000001, Data Length 16777215 !

 SEMC SDRAM Read 16 bit Data Start, Start Address 0x80000001, Data Length 16777215 !

 SEMC SDRAM 16 bit Data Write and Read Compare Succeed!

 SEMC SDRAM Memory 8 bit Write Start, Start Address 0x80000000, Data Length 33554432 !

 SEMC SDRAM Read 8 bit Data Start, Start Address 0x80000000, Data Length 33554432 !

 SEMC SDRAM 8 bit Data Write and Read Compare Succeed!

 SEMC SDRAM Example End.

4. 总结

默认DDR工作时钟为198Mhz,本文将其修改为148.5Mz.主要是针对SDRAM各参数如何从芯片中获取,取值的约束条件做了详细说明,至于各参数的具体含义可以从DDR的协议规范当中找到,或者芯片手册当中学到。

上一篇:阿里面试Redis常考问题


下一篇:一.LED灯的点亮——从简单的汇编开始了解