嵌入式实操-基于RT1170 使能FlexSPI功能(三十三)

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

MCUXpresso SDK FLEX SPI API 接口链接
  在MCUXpresso SDK 框架下提供了SPI进行操作的接口。

1. 首先阅读原理图


FLEXSPI1_A_SS0_B----GPIO_SD_B2_06
FLEXSPI1_A_SCLK----GPIO_SD_B2_07
FLEXSPI1_A_DATA1----GPIO_SD_B2_08
FLEXSPI1_A_DATA2----GPIO_SD_B2_09
FLEXSPI1_A_DATA3----GPIO_SD_B2_10
FLEXSPI1_A_DATA4----GPIO_SD_B2_11

2. SDK api 应用

2.1 芯片重要参数

2.2 引脚配置

/* 设备特性相关的参数 */
flexspi_device_config_t deviceconfig = {
    .flexspiRootClk = 120000000,
    .flashSize = FLASH_SIZE,
    .CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle,
    .CSInterval = 2,
    .CSHoldTime = 1,
    .CSSetupTime = 1,
    .dataValidTime = 2,
    .columnspace = 0,
    .enableWordAddress = false,
    .AWRSeqIndex = NOR_CMD_LUT_SEQ_IDX_AHB_PAGEPROGRAM_QUAD_1,
    .AWRSeqNumber = 2,
    .ARDSeqIndex = NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD,
    .ARDSeqNumber = 1,
    /* W25Q256 typical time=0.7ms,max time=3ms 
     *  fAHB = 528MHz,T AHB = 1/528us
     *  unit = 32768/528 = 62.06us
     *  取延时时间为1ms,
     *  AHBWriteWaitInterval = 1*1000/62.06 = 17
     */
    .AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit32768AhbCycle,
    .AHBWriteWaitInterval = 17,
};


CSInterval = tCEH = 7nS

tPP页编程间隔

如果工作时钟是120M, 则一个时钟周期就是1/120Mhz = 8.33 ns

片选间隔设置成2个时钟周期CSInterval = 2 满足,其实设置成3是比较合理的。


片选保持设置成1个时钟周期
CSHoldTime = 1,满足


片选设置设置成1个时钟周期
CSSetupTime = 1,满足

数据有效时间设置成dataValidTime =2,满足

IS25WP128F没有列地址,所以columnspace = 0

enableWordAddress 其含义为是否使能4字节地址模式,在三字节地址模式下面,最大的访问空间范围为0-16M,所以如果容量超过16M的flash,需要开启4字节地址模式访问16M以后的范围。
AHBWriteWaitUnit AHBWriteWaitInterval 这两个字段在野火的视频上是从Flash的tPP(page program time)参数来换算的,但是后期通过代理商的FAE向原厂请教这两个参数的配置,给出的答复:这两个参数是调试8线的hyperflash的时候用到的,nor不需要管这两个参数,默认就可以了,所以最终还是使用例程给出来的默认配置。

2.3 外设配置

2.4 FlexSpi LUT

FlexSpi LUT表对应的index位置实现的功能是确定的,但是不同的flash对应的CODE是一样的,所以就需要去适配。


两者关系的建立在customLUT。

接下来以IS25LP_WP128F为例
在工程中evkmimxrt1170_flexspi_nor_config.c文件的修改:

/*
 * Copyright 2018-2020 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "evkmimxrt1170_flexspi_nor_config.h"

/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.xip_board"
#endif

/*******************************************************************************
 * Code
 ******************************************************************************/
#if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1)
#if defined(__CC_ARM) || defined(__ARMCC_VERSION) || defined(__GNUC__)
__attribute__((section(".boot_hdr.conf"), used))
#elif defined(__ICCARM__)
#pragma location = ".boot_hdr.conf"
#endif


//Pre-defined LUT index
#define NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD                         0
#define NOR_CMD_LUT_SEQ_IDX_READ_STATUSREG                         1
#define NOR_CMD_LUT_SEQ_IDX_WRITE_ENABLE                           3 
#define NOR_CMD_LUT_SEQ_IDX_ERASE_SECTOR                           5
#define NOR_CMD_LUT_SEQ_IDX_ERASE_BLOCK                            8
#define NOR_CMD_LUT_SEQ_IDX_PAGE_PROGRAM_SINGLE                    9
#define NOR_CMD_LUT_SEQ_IDX_CHIP_ERASE                             11
#define NOR_CMD_LUT_SEQ_IDX_DUMMY                                  15

//Reserved
#define NOR_CMD_LUT_SEQ_IDX_WRITE_STATUSREG                        2
#define NOR_CMD_LUT_SEQ_IDX_READ_ID                                4

#if  0
const flexspi_nor_config_t qspiflash_config = {
    .memConfig =
        {
            .tag              = FLEXSPI_CFG_BLK_TAG,
            .version          = FLEXSPI_CFG_BLK_VERSION,
            .readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
            .csHoldTime       = 3u,
            .csSetupTime      = 3u,
            // Enable DDR mode, Wordaddassable, Safe configuration, Differential clock
            .controllerMiscOption = 0x10,
            .deviceType           = kFlexSpiDeviceType_SerialNOR,
            .sflashPadType        = kSerialFlash_4Pads,
            .serialClkFreq        = kFlexSpiSerialClk_133MHz,
            .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,
};
#endif

const flexspi_nor_config_t hyperflash_config = {
    .memConfig =
        {
            .tag = FLEXSPI_CFG_BLK_TAG,
            .version = FLEXSPI_CFG_BLK_VERSION,
            .readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackInternally,
            .csHoldTime = 3u,
            .csSetupTime = 3u,
            .columnAddressWidth = 0u,

            .waitTimeCfgCommands = 0x10,
            // Enable DDR mode, Wordaddassable, Safe configuration, Differential clock
            #if 0
            .controllerMiscOption =
                (1u << kFlexSpiMiscOffset_DdrModeEnable) | (1u << kFlexSpiMiscOffset_WordAddressableEnable) |
                (1u << kFlexSpiMiscOffset_SafeConfigFreqEnable) | (1u << kFlexSpiMiscOffset_DiffClkEnable),
            #endif
            .deviceType = kFlexSpiDeviceType_SerialNOR,
            .sflashPadType = kSerialFlash_4Pads,
            .serialClkFreq = kFlexSpiSerialClk_133MHz,
            .sflashA1Size = 16u * 1024u * 1024u,
            .dataValidTime = {16u, 16u},

            .busyOffset = 0x0000,
            .busyBitPolarity = 0x01,
            .lutCustomSeqEnable = false,
            .lookupTable =
                {
                    // QSPI Read
                    [4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD] = 
                        FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x6B, RADDR_SDR, FLEXSPI_1PAD, 0x18),
                    [4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD + 1] = 
                        FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x08, READ_SDR, FLEXSPI_4PAD, 0x4),

                    // Read Status
                    [4 * NOR_CMD_LUT_SEQ_IDX_READ_STATUSREG] = 
                        FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05, READ_SDR, FLEXSPI_1PAD, 0x04),

                    // Write enable
                    [4 * NOR_CMD_LUT_SEQ_IDX_WRITE_ENABLE] = 
                        FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06, STOP, FLEXSPI_1PAD, 0x00),

                    // Erase Sector
                    [4 * NOR_CMD_LUT_SEQ_IDX_ERASE_SECTOR] = 
                        FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xD7, RADDR_SDR, FLEXSPI_1PAD, 0x18),

                    // Erase Block 32KB
                    [4 * NOR_CMD_LUT_SEQ_IDX_ERASE_BLOCK] = 
                        FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x52, RADDR_SDR, FLEXSPI_1PAD, 0x18),

                    // Page Program
                    [4 * NOR_CMD_LUT_SEQ_IDX_PAGE_PROGRAM_SINGLE] = 
                        FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x02, RADDR_SDR, FLEXSPI_1PAD, 0x18),
                    [4 * NOR_CMD_LUT_SEQ_IDX_PAGE_PROGRAM_SINGLE + 1] = 
                        FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0x04, STOP, FLEXSPI_1PAD, 0x00),

                    // Chip Erase
                    [4 * NOR_CMD_LUT_SEQ_IDX_CHIP_ERASE] = 
                        FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xC7, STOP, FLEXSPI_1PAD, 0x00),

                    // Dummy
                    [4 * NOR_CMD_LUT_SEQ_IDX_DUMMY] = 0,

                    // write status reg
                    [4 * NOR_CMD_LUT_SEQ_IDX_WRITE_STATUSREG] = 
                        FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x01, WRITE_SDR, FLEXSPI_1PAD, 0x04),

                    // read id
                    [4 * NOR_CMD_LUT_SEQ_IDX_READ_ID] = 
                        FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xAB, DUMMY_SDR, FLEXSPI_1PAD, 0x18),
                    [4 * NOR_CMD_LUT_SEQ_IDX_READ_ID + 1] = 
                        FLEXSPI_LUT_SEQ(READ_SDR, FLEXSPI_1PAD, 0x04, STOP, FLEXSPI_1PAD, 0x00),
                },
        },
    .pageSize = 256u,
    .sectorSize = 4u * 1024u,
    .blockSize          = 32u * 1024u,                
    .ipcmdSerialClkFreq = true,
};


#endif /* XIP_BOOT_HEADER_ENABLE */

在IS25LP_WP_128F手册上,对应的操作如下所示:

#define NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD 0


#define NOR_CMD_LUT_SEQ_IDX_READ_STATUSREG 1


#define NOR_CMD_LUT_SEQ_IDX_WRITE_ENABLE 3


#define NOR_CMD_LUT_SEQ_IDX_ERASE_SECTOR 5


#define NOR_CMD_LUT_SEQ_IDX_ERASE_BLOCK 8


#define NOR_CMD_LUT_SEQ_IDX_PAGE_PROGRAM_SINGLE 9


#define NOR_CMD_LUT_SEQ_IDX_CHIP_ERASE 11

#define NOR_CMD_LUT_SEQ_IDX_DUMMY 15

//Reserved
#define NOR_CMD_LUT_SEQ_IDX_WRITE_STATUSREG 2


#define NOR_CMD_LUT_SEQ_IDX_READ_ID 4

4. 总结

最后对Flexspi 各种读取模式做总结


希望对各位读者帮助。
欢迎订阅
嵌入式实操”一个分享开发实践经验的地方。
文章会同时发布到我的
CSDN主页(嵌入式实操的博客_CSDN博客-05-RT1170 开发,06--Am335x,01--RT1052 Aworks 开发领域博主今日头条号 平台上。

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章