前一篇博文介绍了RT1060 的最小系统硬件设计的一些要求和注意事项,接下来我们就来看看 RT1060 的外挂 QSPI Flash 是如何使用的吧。
学习 RT 的外挂 Flash 是每个做 RT 软件设计工程师的必修课。我手上正好有一块 RT1060 的电路板,它的 QSPI NOR Flash 是 Winbond 的 W25Q256JV。这颗 Flash 的存储容量是 32MB,支持 Standard/Dual/Quad SPI,支持原地执行代码(XIP),支持 3/4 字节地址模式,遵从 JEDEC216 标准,最高工作频率达到 133MHz。
首先,我们看看 RT1060 与 W25Q256JV 硬件是如何连接的。
原理图如下所示:
由于读写速度能达到 133MHz,所以在 PCB 布线时,最好注意信号线等长处理,长度差控制在 ±50mil 以内,阻抗匹配在 50 Ω左右,以确保信号的完整性。
硬件设计完成之后,我们再来看看软件吧。
市面上存在着各种各样的 Nor Flash,不同的厂家的驱动指令都大相径庭,RT1060 是如何做到兼容各种品牌,对不同 Nor Flash 进行读写操作呢?实际上,查找表(LUT,Look-up table)很好的解决了这个问题。查找表被定义为一组用于保存预编程的逻辑序列的寄存器。每条序列最多可包含 8 条指令,LUT 的结构如下图所示。
一条指令(Instruction)中包含 3 个参数:opcode、num_pads、operand。opcode 是指令的类型代码,比如 kFLEXSPI_Command_SDR 的代码是 0x01。num_pads 是指令所用到的管脚数,比如使用 QSPI 的四线就设置 num_pads = 2。operand 是指令的操作数,不同的 opcode 代表的意义不一样,比如 kFLEXSPI_Command_SDR 指令的operand 代表的是指令代码,而 kFLEXSPI_Command_RADDR_SDR 指令的 operand 代表的是地址位数。这 3 个参数的具体设置可查看 RT1060 参考手册里的表格 27-7。
FlexSPI 根据序列号中的指令设置与外挂 Flash 通讯,所以我们可以根据外挂 Flash 的指令来设置 LUT 表。比如,W25Q256JV 的 JEDEC ID 指令格式和时序图如下所示:
根据上面的时序图,定义 LUT 表如下:
/* Read ID */
[4 * NOR_CMD_LUT_SEQ_IDX_READID] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x9F, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),
这条指令包含了两个动作,一个是发送指令(kFLEXSPI_Command_SDR):0x9F,下一个是读数据(kFLEXSPI_Command_READ_SDR)。那么我们在读取 JEDEC ID 的函数中设置如下:
status_t flexspi_nor_get_vendor_id(FLEXSPI_Type *base, uint32_t *vendorId)
{
uint32_t temp;
flexspi_transfer_t flashXfer;
flashXfer.deviceAddress = 0;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Read;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_READID;
flashXfer.data = &temp;
flashXfer.dataSize = 3;
status_t status = FLEXSPI_TransferBlocking(base, &flashXfer);
*vendorId = temp;
/* Do software reset. */
FLEXSPI_SoftwareReset(base);
return status;
}
从上面的这个例子,我们基本上可以了解 RT1060 如何使用 LUT 表与 Nor Flash 通讯。更多 Nor Flash 设置的例子可以参考 RT1060 参考手册中的第 27.6.3 节。
另外,NXP 的官方 SDK 兼容 W25Q256JV,所以我们可以使用官方的 SDK 来驱动这颗 Nor Flash。SDK 支持的 IDE 包括:Keil MDK 、IAR 以及 MCUXpresso ,其中 MCUXpresso 是 NXP 自己开发的免费的 IDE ,我个人觉得用这个 IDE 开发 RT 的软件还是很好用的。如果您也对这个 IDE 感兴趣,我们可以多交流交流。我从 NXP 官网上(https://mcuxpresso.nxp.com/en/select)下载的 SDK 版本是 V2.8.2。我们可以从例程:flexspi_nor_polling_transfer 中学习到如何设置 LUT 表并驱动 Nor Flash。在用这个例程驱动 W25Q256JV 时,需要注意两点:
- 使能 QE 的指令和参数
函数:flexspi_nor_enable_quad_mode() 中的参数需要改成 0x02,如下所示:
status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base)
{
flexspi_transfer_t flashXfer;
status_t status;
uint32_t writeValue = FLASH_QUAD_ENABLE; // (W25Q256) 此参数值改为 0x02
/* Write enable */
status = flexspi_nor_write_enable(base, 0);
if (status != kStatus_Success)
{
return status;
}
/* Enable quad mode. */
flashXfer.deviceAddress = 0;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Write;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG;
flashXfer.data = &writeValue;
flashXfer.dataSize = 1;
status = FLEXSPI_TransferBlocking(base, &flashXfer);
if (status != kStatus_Success)
{
return status;
}
status = flexspi_nor_wait_bus_busy(base);
/* Do software reset. */
FLEXSPI_SoftwareReset(base);
return status;
}
LUT 表中写状态寄存器的指令改成 0x31,如下所示:
/* Enable Quad mode */
[4 * NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x31, kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04),
- LUT 表中擦除扇区的指令改成 0x20,如下所示:
/* Erase Sector */
[4 * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x20, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
以上是我对 RT1060外挂 QSPI Flash设计方面的一些理解,希望对有这方面了解需求的你有些帮助。如果要获得更详尽的信息,可以参考 NXP 官网的 RT1060 参考手册和 W25Q256 的数据手册。如果您还有这方面的疑问,欢迎在下面评论区评论。
在后续的博文中,我会继续写一些关于 RT1060 的设计笔记,请多多来大大通关注我哦。
参考资料
- i.MX RT1060 Processor Reference Manual - https://www.nxp.com.cn/products/processors-and-microcontrollers/arm-microcontrollers/i-mx-rt-crossover-mcus/i-mx-rt1060-crossover-mcu-with-arm-cortex-m7-core:i.MX-RT1060?tab=Documentation_Tab
- W25Q256JV Datasheet
评论