0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

缺失DQS信号的FlexSPI连接Flash有何不同?

冬至子 来源:痞子衡嵌入式 作者:痞子衡 2023-06-02 17:53 次阅读

一、FlexSPI的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

2.2 i.MXRT1160/1170 FlexSPI2 2nd PortA

三、使能没有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 运行

工程路径:\\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,
};
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • RAM
    RAM
    +关注

    关注

    7

    文章

    1318

    浏览量

    113698
  • 调试器
    +关注

    关注

    1

    文章

    288

    浏览量

    23392
  • Flash存储
    +关注

    关注

    0

    文章

    38

    浏览量

    8235
  • QSPI接口
    +关注

    关注

    0

    文章

    14

    浏览量

    3276
收藏 人收藏

    评论

    相关推荐

    Vitex-6如何延迟dqs 3 ns

    嗨, 我正在为我的设计添加一个NAND闪存。闪存芯片支持源同步接口,可提供高达166MB / s的带宽。但是当我从闪存中读取DDR数据时。 DQS信号从闪存芯片传输到我的FPGA器件,以及与DQS
    发表于 03-29 14:03

    NOR Flash与NAND Flash何不

    Flash的原理是什么?Flash主要有哪几种?NOR Flash与NAND Flash何不
    发表于 10-22 08:47

    FlexSPIDQS信号作用是什么?哪些FlexSPI引脚组不支持DQS

    FlexSPIDQS信号作用是什么?哪些FlexSPI引脚组不支持DQS
    发表于 01-19 07:06

    FlexSPI NOR启动的连接方式

      大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是恩智浦i.MX RT500的FlexSPI NOR启动的连接方式。  这个i.MXRT FlexSPI NOR启动连接
    发表于 02-09 07:56

    启用FLEXSPI NOR Flash调试的教程

    如何启用FLEXSPI NOR Flash的调试
    发表于 12-12 06:13

    Hyperflash设备的不同FlexSPI数据信号顺序是怎样的?

    和 Hyperflash 之间的连接中,A_DATAx迹线与B_DATAx迹线交换。换句话说,我们以下场景:A_DATA0 与 B_DATA0 交换A_DATA1 与 B_DATA1 交换A_DATA2
    发表于 03-20 06:42

    imxrt1170中flexspi如何使用AHB操作?

    一个 imxrt1170 板,想使用 flexspi1(连接到 fpga)。我想在 flexspi1 上使用 AHB 总线操作,但是当我访问 BASE_ADDR(0x3000000
    发表于 03-27 08:16

    求助,可以忽略FlexSPI DQS吗?

    DQS 线用于读写数据选通。我一直在看一些 FlexSPI 示例:-sdk_flexspi_nor_polling_transferpolling_transfer_hyperRAM 在这
    发表于 03-29 07:34

    调试器因FlexSPI Nor Flash指令失败的原因?如何解决?

    尝试执行函数 flexspi_nor_flash_init(...) ,调试器就会断开连接并显示:我一种感觉,它与一些时钟配置有关,但不知道从这里去哪里出现问题的代码片段:int main(void
    发表于 03-29 08:05

    启动后需要使用RT1052中的DQS引脚进行I2C,要怎么操作?

    FlexSPIDQS (数据选通),即使我不需要或不想使用引脚。硬件场景如下:单个 IS25WP064A-JBLE 连接,没有 DQS(数据选通),只有内部 RAM(没有外部
    发表于 04-10 08:41

    如何设法将固件直接下载到连接flexspi PORT B的闪存?

    大家好, 我们一块定制板,W25Q128JV 连接FLEXSPI 端口 B,我无法让 MCUXpresso/Keil 直接将固件下载到闪存,我可以确认下载算法是正确的,因为相同的算法适用于
    发表于 05-04 08:44

    MXRT1050 FlexSPI有没有办法支持超过16个flash命令的NOR Flash设备?

    flash 命令的 NOR Flash 设备? 2. 有没有办法在没有 LUT 的情况下使用 FlexSPI 模块?-----
    发表于 05-08 06:52

    i.MXRT117x - FlexSPI1和FlexSPI2能否以133MHz的全时钟速度运行?

    ,我们无法让 FlexSPI2 以 133MHz 的全时钟速度运行。如果这是可能的,我们还没有想出如何去做。我们只能以半时钟频率运行 FlexSPI2。GPIO_EMC_B2_12 上的 DQS 引脚是否配置为
    发表于 05-23 06:31

    I.MXRT1170从FLEXSPI2启动

    设计将使用FlexSPI1 接外部的 HyperRAM,FlexSPI2 接QSPI Flash存储器芯片作为RT1176 引导设备。当代码在内部RAM里面执行的时候是正常的,遇到了从外部Fl
    的头像 发表于 12-01 15:06 1016次阅读

    探讨i.MX RT下FlexSPI driver实现Flash编程时对于中断支持问题

    前段时间有客户在官方社区反映i.MX RT1170下,使用官方SDK里FlexSPI驱动去擦写Flash时不能很好地支持全局中断。 客户项目里用了两块NOR Flash,分别挂在
    的头像 发表于 02-06 15:09 752次阅读