当前位置:首页 > 技术分析 > 正文内容

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

ruisui885个月前 (01-14)技术分析45

本文主要是通过迁移的思维,记录本人初次使用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. 首先阅读原理图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qTWOXGYP-1616410062182)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/6057feda1d181.png)]

DDR芯处使用IS42S32800J-6BLA1从手册上可以看得出来该芯片支持的最大工作时钟为166Mhz.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ySJKUJ2a-1616410062187)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/6057ffa173d6b.png)]

但是从MCU的手册上可以看出其支持的最大速率为200Mhz.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6CBTG5s3-1616410062191)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/60580129bcfb3.png)]

2. SDK api 应用

2.1 引脚配置

引脚复用配置

2.2 时钟配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-75JlQGrZ-1616410062196)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/6058272b304cd.png)]

从上图可以看到时钟源从SYM_PLL2_528Mhz至SYS_PLL2_PFD1(594Mhz)再通过4分频获取148.5MHz的时钟。
相关的配置代码如下所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f82yVIHQ-1616410062201)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/6058267a981aa.png)]

2.3 外设配置

对DDR的初始化,还是需要有前置知识的,了解DDR的工作时钟、时序相关知识,以及初始化的状态机。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rb44zg8B-1616410062204)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/60582a0331852.png)]

进入SEMC DDR的配置界面,如下所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lc7tfEvK-1616410062208)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/60582a2f3707f.png)]



在这里插入图片描述

第一,需要选择DDR的时钟源及其频率

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L13QIjQ7-1616410062210)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/60582b1a49ef6.png)]

第二,需要DDR的数据锁存模式,我们选择DQS模式。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(img-6PpdiigO-1616410062212)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/60582afe564ca.png)]

第三、需要配置片选信号,这个和硬件设计相关

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oBB5pDrd-1616410062214)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/60582b7bc8b18.png)]

第四、需要配置内存的物理起始位置,这个和MCU的地址分配相关。


第五、需要配置内存的容量,和所选的SDRAM芯片容量保持一致。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q5YFmIFn-1616410062218)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/60582c0e1cf83.png)]

第六、配置SDRAM数据线的宽度及突发长度,数据宽度从原理图上可以看出来。突发长度可以从SDRAM手册上找到。




第七、配置列地址线的个数及CAS。列地址线的个数可以从手册上找出来,CAS可以选择2或者3也是在手册上的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OQ2SnkBN-1616410062223)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/60582fb3e39ec.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PdpxZ9Ru-1616410062224)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/60582f1dd4655.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p4jbMJ2h-1616410062226)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/60583026eac64.png)]

第八、预充电(Precharge)至有效(active)的等待时间tRP,在166MHz,从手册上查得该数值>=18




第九、Active Command To Read / Write Command Delay Time (tRCD)



[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qUn0WMOr-1616410062234)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/60583551c0021.png)]

第十、刷新恢复时间 取tRFC/tXSR当中的最大值。





[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q5kHX6uD-1616410062239)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/6058488c43a50.png)]

第十一、写恢复(write recovery)时间 tWR

在这里插入图片描述



在这里插入图片描述

第十二、CKE off minimun time, 一般取tRAS




第十三、active to precharge, 取tRAS



在这里插入图片描述

第十四、self refresh reovery time 自刷新恢复时间,取tXSR




第十五、refresh to refresh wait time 刷新至刷新的等待时间,取tRC.




第十六、active to active wait time 有效至有效的等待时间, 取tRC = tRAS + tRP = tRCD + tWR + tRP


第十七、prescaler timer period, 取160个tCLK时钟周期

160 *  1000000000 / semc_clk = 160 * 1000000000 / 148500000


第十八、sdram idle time 必须小于 tRAS, 而tRAS的最大值为100000ns

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kfv4jMU3-1616410062262)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/605861ba9e04c.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SIgHIUB7-1616410062265)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/60585419c8d2c.png)]

且有一个限制条件:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KsOMMcJT-1616410062267)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/605856c4cc5ee.png)]

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

ITO取值意义如下,所以我们取[1,92]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Qzfhzhx-1616410062269)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/60585a5b0f6c3.png)]

第十九:refresh timer period /refresh upgent period, 从手册上可以看到刷新4096次,总用耗时64ms,每次的刷新时间为 64*1000000/4096,两者相同值。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TYL1SxUl-1616410062270)(http://139.224.41.215:4999/server/../Public/Uploads/2021-03-22/6058610be8c32.png)]

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的协议规范当中找到,或者芯片手册当中学到。

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/260.html

标签: threebsp
分享给朋友:

“嵌入式实操——基于RT1170 使能SEMC配置SDRAM功能(八)” 的相关文章

2024年10 大 Linux 桌面发行版推荐

年已过半,现在是探究 2024 年最流行的 Linux 发行版的最佳时机。Linux 是一个开源操作系统,构建在 Linux 内核上,并集成了 GNU shell 实用程序、桌面环境、应用程序、包管理系统。由于其通用性、安全性、用户友好性和多样性,它的受欢迎程度超过了其他操作系统。在本文中,我们将从...

适合旧电脑2022年值得推荐的 10 款轻量级 Linux 发行版

推荐 10 款轻量级Linux 发行版,它们是 2022 年的轻量级、对旧硬件友好的 Linux 发行版。1、Linux LiteLinux Lite 是一款基于#ubuntu# 和 Debian 的、正在不断开发和完善的 Linux 发行版,极好看的 Xfce 桌面,并基于 Ubuntu,采用了...

Gitlab概览

Gitlab是开源的基于Git的仓库管理系统,也可以管理软件开发的整个生命周期,是项目管理和代码托管平台,支撑着整个DevOps的生命周期。Gitlab很容易选为GitHub,作为公司私有库管理的工具。我们可以用Gitlab Workflow来协同整个团队的软件开发管理过程。软件开发阶段Gitlab...

Python 幕后:Python导入import的工作原理

更多互联网精彩资讯、工作效率提升关注【飞鱼在浪屿】(日更新)Python 最容易被误解的方面其中之一是import。Python 导入系统不仅看起来很复杂。因此,即使文档非常好,它也不能让您全面了解正在发生的事情。唯一方法是研究 Python 执行 import 语句时幕后发生的事情。注意:在这篇文...

K8s里我的容器到底用了多少内存?

作者:frostchen导语 Linux下开发者习惯在物理机或者虚拟机环境下使用top和free等命令查看机器和进程的内存使用量,近年来越来越多的应用服务完成了微服务容器化改造,过去查看、监控和定位内存使用量的方法似乎时常不太奏效。如果你的应用程序刚刚迁移到K8s中,经常被诸如以下问题所困扰:容器的...

Python中的11 种数组算法

1. 创建数组 创建数组意味着留出一个连续的内存块来存储相同类型的元素。在大多数语言中,您可以在创建数组时指定数组的大小。假设您正在书架上整理一组书籍,并且您需要为正好 10 本书预留空间。功能架上的每个空间都对应于数组中的一个索引。# Example in Python arr = [1, 2,...