MCUXpresso SDK FLEX SPI API 接口链接
在MCUXpresso SDK 框架下提供了SPI进行操作的接口。
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
/* 设备特性相关的参数 */
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不需要管这两个参数,默认就可以了,所以最终还是使用例程给出来的默认配置。
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
最后对Flexspi 各种读取模式做总结
希望对各位读者帮助。
欢迎订阅
“嵌入式实操”一个分享开发实践经验的地方。
文章会同时发布到我的 CSDN主页(嵌入式实操的博客_CSDN博客-05-RT1170 开发,06--Am335x,01--RT1052 Aworks 开发领域博主)、今日头条号 平台上。
留言与评论(共有 0 条评论) “” |