痞子衡嵌入式:i.MXRT中不支持DQS的FlexSPI引脚组连接Flash下载与启动注意事项
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是i.MXRT中不支持DQS的FlexSPI引脚组连接Flash下载与启动注意事项。
最近痞子衡在支持一个印度客户,这个客户项目主芯片选择的是恩智浦 i.MXRT1176,客户设计板子时选择将四线 NOR Flash 挂在了主芯片 FlexSPI2 2nd Pinmux( GPIO_SD_B1[05:00] )上,选择这组引脚当然是可以的,但客户在使用恩智浦配套下载工具以及 SDK 例程时发现无法正常使用,体验上跟默认 FlexSPI1 1st Pinmux( GPIO_SD_B2[11:05] )挂载 Flash 完全不同,这其实跟 FlexSPI DQS 信号设计有关,且听痞子衡道来:
一、FlexSPI的DQS信号作用
关于 DQS 信号,痞子衡写过一篇文章 《串行NOR Flash的DQS信号功能简介》,里面介绍了 DDR、Octal Flash、Hyper Flash 芯片上的 DQS 信号作用,文章中没有提及四线 QSPI Flash,因为一般的四线 QSPI Flash 芯片并没有 DQS 信号引脚。FlexSPI 模块的 DQS 信号当然可以用来连接 Octal Flash、Hyper Flash 上的 DQS 引脚,那么对于四线 QSPI Flash,这个 DQS 信号就没有作用了吗?其实不是的。
我们翻开 i.MXRT1170 的数据手册(Data Sheet)找到 FlexSPI parameters 小节里的如下内容,就很清楚了。FlexSPIn_MCR0[RXCLKSRC] 位对应了三种 DQS 信号源设置:0x0 - Dummy read strobe looped back internally 设置即完全不用 DQS 引脚(可作它用),对应最高 60MHz SDR 访问速度;0x1 - Dummy read strobe looped back through the DQS pad 设置即从 DQS 引脚上回环,因此 DQS 引脚需要悬空,对应最高 133MHz SDR 访问速度;0x3 - Read strobe from memory device DQS pad 设置即接到存储芯片 DQS 引脚上,对应最高 166MHz SDR 访问速度;
• Dummy read strobe generated by FlexSPI controller and looped back internally (FlexSPIn_MCR0[RXCLKSRC] = 0x0)
• Dummy read strobe generated by FlexSPI controller and looped back through the DQS pad (FlexSPIn_MCR0[RXCLKSRC] = 0x1)
• Read strobe provided by memory device and input from DQS pad (FlexSPIn_MCR0[RXCLKSRC] = 0x3)
二、哪些FlexSPI引脚组不支持DQS?
目前恩智浦已量产的所有 i.MXRT 型号里(RT500/600/1010/1015/1020/1050/1060/1160/1170),大部分的 FlexSPI 引脚组合都是包含 DQS 信号设计的,只有如下两个例外。没有 DQS 信号的引脚组合连 Flash 时,应配置 FlexSPIn_MCR0[RXCLKSRC] 为 0x0 - looped back internally。
2.1 i.MXRT600 FlexSPI0 PortB
见 《FlexSPI NOR连接方式大全(RT600)》 一文第三节、单Flash连接方式里的第四种Flash连接方式。
2.2 i.MXRT1160/1170 FlexSPI2 2nd PortA
见 《FlexSPI NOR连接方式大全(RT1160/1170)》 一文第二节、单Flash连接方式里第一张表格里的最后一组连接方式。
三、使能没有DQS的FlexSPI连接的Flash
对于不含 DQS 信号的 FlexSPI 引脚组合,使用恩智浦相关工具操作连接在其上的 NOR Flash 是需要做一些改动的,我们以 i.MXRT1170-Validation 板卡为例来介绍具体改动。
i.MXRT1170-Validation 板卡是专供恩智浦内部使用的,分为 CPU1/2/3/4 四款,每款的硬件连接不同,其中 CPU2 板卡在 FlexSPI2 2nd PortA 上连接了一颗镁光的 MT25QL128:
3.1 SDK中FlexSPI擦写Flash例程改动
我们现在打开 SDK 里的 FlexSPI 例程,这个例程是针对 MIMXRT1170-EVK 板卡写的,在 EVK 上 NOR Flash 默认是连在 FlexSPI1 1st PortA 上的,因此我们需要对例程做一些改动。
例程路径:\SDK_2.x.x_MIMXRT1170-EVK\boards\evkmimxrt1170\driver_examples\flexspi\nor\polling_transfer\cm7
首当其冲的改动当然是 pin_mux.c 文件里的 BOARD_InitPins() 函数,需要将 FlexSPI1 1st Pinmux 换成 FlexSPI2 2nd Pinmux:
void BOARD_InitPins(void)
{
CLOCK_EnableClock(kCLOCK_Iomuxc);
//IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B2_05_FLEXSPI1_A_DQS, 1U);
//IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B2_06_FLEXSPI1_A_SS0_B, 1U;
//IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B2_07_FLEXSPI1_A_SCLK, 1U);
//IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B2_08_FLEXSPI1_A_DATA00, 1U);
//IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B2_09_FLEXSPI1_A_DATA01, 1U);
//IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B2_10_FLEXSPI1_A_DATA02, 1U);
//IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B2_11_FLEXSPI1_A_DATA03, 1U);
//IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B2_05_FLEXSPI1_A_DQS, 0x0AU);
//IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B2_06_FLEXSPI1_A_SS0_B, 0x0AU);
//IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B2_07_FLEXSPI1_A_SCLK, 0x0AU);
//IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B2_08_FLEXSPI1_A_DATA00, 0x0AU);
//IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B2_09_FLEXSPI1_A_DATA01, 0x0AU);
//IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B2_10_FLEXSPI1_A_DATA02, 0x0AU);
//IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B2_11_FLEXSPI1_A_DATA03, 0x0AU);
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_00_FLEXSPI2_A_SS0_B, 1U;
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_01_FLEXSPI2_A_SCLK, 1U);
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_02_FLEXSPI2_A_DATA00, 1U);
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_03_FLEXSPI2_A_DATA01, 1U);
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_04_FLEXSPI2_A_DATA02, 1U);
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_05_FLEXSPI2_A_DATA03, 1U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_00_FLEXSPI2_A_SS0_B, 0x0AU);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_01_FLEXSPI2_A_SCLK, 0x0AU);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_02_FLEXSPI2_A_DATA00, 0x0AU);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_03_FLEXSPI2_A_DATA01, 0x0AU);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_04_FLEXSPI2_A_DATA02, 0x0AU);
IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_05_FLEXSPI2_A_DATA03, 0x0AU);
}
然后再改一下 app.h 文件里的宏定义,从 FlexSPI1 换到 FlexSPI2,并相应调整 Flash 属性(EVK 上是 IS25WP128,Validation 板上是 MT25QL128),以及更新 flexspi_clock_init() 函数:
//#define EXAMPLE_FLEXSPI FLEXSPI1
//#define EXAMPLE_FLEXSPI_AMBA_BASE FlexSPI1_AMBA_BASE
//#define EXAMPLE_FLEXSPI_CLOCK kCLOCK_Flexspi1
#define EXAMPLE_FLEXSPI FLEXSPI2
#define EXAMPLE_FLEXSPI_AMBA_BASE FlexSPI2_AMBA_BASE
#define EXAMPLE_FLEXSPI_CLOCK kCLOCK_Flexspi2
static inline void flexspi_clock_init(void)
{
// 在 BOARD_BootClockRUN() 函数里给 FlexSPI 设置的时钟源是 OSC_RC_48M_DIV2 / 2 即 12MHz
// 这里没有再次分频,因此 FlexSPI root clock 就是 12MHz
//CLOCK_SetRootClockDiv(kCLOCK_Root_Flexspi1, 2);
//CLOCK_SetRootClockMux(kCLOCK_Root_Flexspi1, 0);
CLOCK_SetRootClockDiv(kCLOCK_Root_Flexspi2, 2);
CLOCK_SetRootClockMux(kCLOCK_Root_Flexspi2, 0);
}
上面都是大家能意识到的改动,但其实最容易被忽略的改动是 flexspi_nor_flash_ops.c 文件里的 flexspi_nor_flash_init() 函数,config.rxSampleClock 设置必须要改成 kFLEXSPI_ReadSampleClkLoopbackInternally 才行。代码全部改完之后下载运行就可以正常擦写 Flash 了。
void flexspi_nor_flash_init(FLEXSPI_Type *base)
{
// 省略部分代码 ...
flexspi_clock_init();
flexspi_config_t config;
FLEXSPI_GetDefaultConfig(&config);
config.ahbConfig.enableAHBPrefetch = true;
config.ahbConfig.enableAHBBufferable = true;
config.ahbConfig.enableReadAddressOpt = true;
config.ahbConfig.enableAHBCachable = true;
//config.rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackFromDqsPad;
config.rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackInternally;
FLEXSPI_Init(base, &config);
// 省略部分代码 ...
}
3.2 SDK中Flashloader工程使用
现在我们再来用一下 SDK 里的 flashloader 工程,这个应用程序可以与恩智浦专用命令行上位机 blhost.exe 进行交互,工程需要用调试器下载进主芯片内部 RAM 运行,具体步骤可参考 《Flashloader初体验(blhost)》。
工程路径:\SDK_2.x.x_MIMXRT1170-EVK\boards\evkmimxrt1170\bootloader_examples\flashloader\cm7
flashloader 运行起来之后,使用 blhost 工具按序执行下列命令,也一样能对 Flash 进行擦写:
blhost -u -- get-property 1
# 选中 FlexSPI2
blhost -u -- fill-memory 0x20000000 4 0xcf900002
blhost -u -- configure-memory 9 0x20000000
# 配置 NOR Flash(forced internal DQS)
blhost -u -- fill-memory 0x20000000 4 0xc1000053 # 其中bit[7:4]是关键设置!!!
blhost -u -- fill-memory 0x20000004 4 0x00110000
blhost -u -- configure-memory 9 0x20000000
blhost -u -- get-property 25 9
# 下载包含 IVT 头的 App
blhost -u -- flash-erase-region 0x60000000 0x8000
blhost -u -- fill-memory 0x20000000 4 0xf000000f
blhost -u -- configure-memory 9 0x20000000
blhost -u -- write-memory 0x60001000 ivt_app.bin
上面命令序列里第二条 fill-memory 命令的参数 0xc1000053 是关键,从 flashloader 源代码里看它其实是在设置 serial_nor_config_option_t.option0.B.misc_mode 为 kSerialNorEnhanceMode_InternalLoopback,这个设置对于四线 QSPI Flash 而言就是设 config->memConfig.readSampleClkSrc 为 kFlexSPIReadSampleClk_LoopbackInternally:
enum
{
kSerialNorEnhanceMode_Disabled = 0,
kSerialNorEnhanceMode_0_4_4_Mode = 1,
kSerialNorEnhanceMode_0_8_8_Mode = 2,
kSerialNorEnhanceMode_DataOrderSwapped = 3,
kSerialNorEnhanceMode_2ndPinMux = 4,
kSerialNorEnhanceMode_InternalLoopback = 5,
};
status_t parse_sfdp(uint32_t instance,
flexspi_nor_config_t *config,
jedec_info_table_t *tbl,
serial_nor_config_option_t *option)
{
status_t status = kStatus_InvalidArgument;
do
{
// 省略部分代码...
uint8_t misc_mode = option->option0.B.misc_mode;
if (misc_mode == kSerialNorEnhanceMode_Disabled)
{
// 省略部分代码...
}
#if FLEXSPI_ENABLE_NO_CMD_MODE_SUPPORT
else if (misc_mode == kSerialNorEnhanceMode_0_4_4_Mode)
{
// 省略部分代码...
}
#endif // FLEXSPI_ENABLE_NO_CMD_MODE_SUPPORT
else if (misc_mode == kSerialNorEnhanceMode_InternalLoopback)
{
config->memConfig.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackInternally;
}
else
{
// Do nothing
}
// 省略部分代码...
} while (0);
return status;
}
3.3 下载工具MCUBootUtility配置
flashloader 的使用对一般客户来说太复杂了,还是图形化工具 MCUBootUtility 更方便,打开这个工具,按如下配置(主要就是图中蓝框圈起来的 Misc Mode 设置),也可以正常擦写 Flash。熟悉这个工具原理的朋友应该知道它底层依赖得就是 3.2 节里的 flashloader 与 blhost。
3.4 SDK例程里的FDCB启动头改动
最后就是 SDK 里全部例程的 XIP build 都需要一个 FDCB 头,这个头定义在 evkmimxrt1170_flexspi_nor_config.c 文件里,这里也要改一下 readSampleClkSrc 和 serialClkFreq 配置才行。
const flexspi_nor_config_t qspiflash_config = {
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
//.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
.readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackInternally,
.csHoldTime = 3u,
.csSetupTime = 3u,
.controllerMiscOption = 0x10,
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_4Pads,
//.serialClkFreq = kFlexSpiSerialClk_133MHz,
.serialClkFreq = kFlexSpiSerialClk_60MHz,
.sflashA1Size = 16u * 1024u * 1024u,
.lookupTable =
{
// Read LUTs
FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
FLEXSPI_LUT_SEQ(MODE8_SDR, FLEXSPI_4PAD, 0x00, DUMMY_SDR, FLEXSPI_4PAD, 0x04),
FLEXSPI_LUT_SEQ(READ_SDR, FLEXSPI_4PAD, 0x04, 0, 0, 0),
},
},
.pageSize = 256u,
.sectorSize = 4u * 1024u,
.ipcmdSerialClkFreq = 0x1,
.blockSize = 256u * 1024u,
.isUniformBlockSize = false,
};
至此,i.MXRT中不支持DQS的FlexSPI引脚组连接Flash下载与启动注意事项痞子衡便介绍完毕了,掌声在哪里~~~
欢迎订阅
文章会同时发布到我的 博客园主页、CSDN主页、知乎主页、微信公众号 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

痞子衡嵌入式:i.MXRT中不支持DQS的FlexSPI引脚组连接Flash下载与启动注意事项的更多相关文章
- 痞子衡嵌入式:揭秘i.MXRT600的ISP模式下用J-Link连接后PC总是停在0x1c04a的原因(Debug Mailbox)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT600中的Debug Mailbox实现对JLink调试的影响. 事情缘起痞子衡的同事 - 喜欢打破砂锅问到底的Kerry小 ...
- 痞子衡嵌入式:i.MXRT中FlexSPI外设不常用的读选通采样时钟源 - loopbackFromSckPad
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT中FlexSPI外设不常用的读选通采样时钟源 - loopbackFromSckPad. 最近碰到一个客户,他们在 i.MX ...
- 痞子衡嵌入式:揭秘i.MXRT1060,1010上串行NOR Flash冗余程序启动设计
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1060,1010上串行NOR Flash冗余程序启动设计. 工业产品设计里经常会有冗余程序/备份程序设计的需求,因为在工业 ...
- 痞子衡嵌入式:i.MXRT中FlexSPI外设对AHB Burst Read特性的支持
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是FlexSPI外设对AHB Burst Read特性的支持. 痞子衡之前写过一篇关于FlexSPI LUT的文章 <从头开始认识i ...
- 痞子衡嵌入式:一种i.MXRT下从App中进入ROM串行下载模式的方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT下在App中利用ROM API进ISP/SDP模式的方法. 我们知道i.MXRT系列分为两大阵营:CM33内核的i.MXRT ...
- 痞子衡嵌入式:关于i.MXRT中FlexSPI外设lookupTable里配置Normal read的一个小误区
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT中FlexSPI外设lookupTable里配置Normal read的一个小误区. 关于串行四线NOR Flash,当其作 ...
- 痞子衡嵌入式:其实i.MXRT下改造FlexSPI driver同样支持AHB方式去写入NOR Flash
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT下改造FlexSPI driver以AHB方式去写入NOR Flash. 痞子衡前段时间写过一篇 <串行NAND Fl ...
- 痞子衡嵌入式:理解i.MXRT中FlexSPI外设lookupTable里配置访问行列混合寻址Memory的参数值
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT中FlexSPI外设lookupTable里配置访问行列混合寻址Memory的参数值. 关于 FlexSPI 外设的 loo ...
- 痞子衡嵌入式:史上最强i.MX RT学习资源汇总(持续更新中...)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MX RT学习资源. 类别 资源 简介 官方汇总 i.MXRT产品主页 恩智浦官方i.MXRT产品主页,最权威的资料都在这里,参考手 ...
随机推荐
- php 扩展kafka
一.安装librdkafka cd /usr/local/src/ git clone https://github.com/edenhill/librdkafka.git cd librdkafka ...
- mysql中的条件语句case when/if函数
主要知识点为case函数,if函数,ifnull函数,elt函数几部分,主要用于mysql语句中的逻辑判断 待操作的表如下: p.p1 { margin: 0; font: 16px Menlo; c ...
- 用swoole实现异步任务队列
应用场景如下: 假如要发100封邮件,for循环100遍,这种方法显然是不可取的. 在一些比较繁杂的业务里,我们很可能有超过1万的邮件要群发.那我们怎么处理这个延迟的问题? 答案就是用异步.把&quo ...
- HGAME2020 reverse maze
1.查壳,发现是64位的linux文件,由于虚拟机没装linux,只能静态调了 2.拖入ida分析,找到主函数 2.1.思路分析 1.先将对应的ASCII的转换成字符,因为迷宫题一般都是用wsad,或 ...
- wireshark 调试 https/http2和grpc流量
本文浏览器以 Chrom 为例 平常需要抓包的场景比较少,记录一下防止下次忘记配置 1. 解析 TLS 在本地创建用于保存 ssl logfile 的文件(文件可以存放到任意位置), 并添加到环境变量 ...
- Redisson 分布式锁源码 11:Semaphore 和 CountDownLatch
前言 Redisson 除了提供了分布式锁之外,还额外提供了同步组件,Semaphore 和 CountDownLatch. Semaphore 意思就是在分布式场景下,只有 3 个凭证,也就意味着同 ...
- python使用笔记22--mock接口开发
1.mock接口开发 mock是模拟一个接口的意思 为了不阻止测试,开发一个接口,返回你想要的数据,模拟各种场景 需要安装第三方模块flask,flask是web轻量级开发框架 1.1 flask p ...
- python 查看导入模块的函数和方法
将twain.pyd复制到Python27 \ Lib \ site-packages 首先 import XXX(包括pyd的文件名)print(dir(XXX))print(help(xxx)) ...
- 替代Infinity绝佳的自主开发chrome插件
最近闲来无事在好朋(da)友(shen)的帮助下开发一个chrome插件,目的是为了替换infinity主页插件, 当然在此也推荐一波infinity确实不错,界面和易用性都是非常好用的水准了. 主页 ...
- C# 连接MySQL数据库 ,查询条件中有中文时,查询不出结果
使用C#成功连接上MySql数据库后,但如果查询条件中有中文,查询结果就为空. String connetStr = "server=127.0.0.1;port=3306;user=roo ...