RT595 系列使用 FlexSPI 与外部 Flash 通讯的方式

一、概述

RT595 集成了 FlexSPI 电路,用于实现高速串行外部存储器与主控经片之间的通信,FlexSPI代表Flexible Serial Peripheral Interface,它提供了一种灵活的方式来连接和操作外部闪存设备,例如 Flash、Hyper RAM … 等,主要用于支援各种透过 Standard SPI、Dual SPI、Quad SPI、Octal SPI 进行通讯的设备,RT595 的 FlexSPI 架构如图 1,借由 IO_CTL对 IO 引脚进行控制,再对应 SPI Bus port 引脚将其配置到外部 Flash 进行通讯,以 NXP MIMXRT595-EVK 为例,如图 2 透过对应的 SPI Bus port ( FLEXSPI0 Port ) 与外部 Flash 进行通讯,本文将着重于透过 RT595 的 FlexSPI 模组对外部 Flash 的设定、擦除 / 读写进行解析进行解说。

图 1 ( 注 1 )
图 2 ( 注 2 )

二、 需求物件:

        2.1 硬体

                2.1.1 NXP RT595 EVK 详细规格如下列网址所示

https://www.nxp.com/design/development-boards/i-mx-evaluation-and-development-boards/i-mx-rt595-evaluation-kit:MIMXRT595-EVK

                2.1.2 Type A to mini B USB Cable : 1 pcs

        2.2 软体

                2.2.1 MCUXPRESSO ( IDE ) 软体开发环境如下列网址所示

https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/mcuxpresso-integrated-development-environment-ide:MCUXpresso-IDE

2.2.2 NXP RT595 SDK 原厂提供的 RT595 EVK Sample Code 如下列网址所示

                        https://mcuxpresso.nxp.com/en/welcome

三、 操作方式:

3.1 开启 evkmimxrt595_flexspi_octal_polling_transfer 的范例,并将范例烧录到 EVK 上,NXP RT595 EVK 板上配置有烧录功能的 IC,如图 3 红框

图 3 ( 注 3 )

3.2 将 USB Cable 连结到模组板 USB Connector,USB Cable 另一端连结到PC 如图 4

图 4  ( 注 3 )

3.3 执行 MCUXPRESSO 并将 NXP 的 SDK 导入到 IDE 中,操作流程如图 5、6

        3.3.1 点击 import SDK example(s)

        3.3.2 弹出 SDK import Wizard 视窗,点选 RT595

        3.3.3 点选 Next

        3.3.4 点选 sample code 

        3.3.5 点选 Finish 完成 Project 建立

图 5
图 6

3.4 Pin define

3.4.1 开启 SDK 建立好的专案 evkmimxrt595_flexspi_octal_polling_transfer

        3.4.2 点选 flexspi_octal_polling_transfer.c ( 如图 7 )

        3.4.3 查看 BOARD_InitPins 中的 Code ( 如图 7 )

图 7

        3.4.4 查看 BOARD_InitPins 将在分页中开启 pin_mux.c

        3.4.5 pin_mux.c 将会看到针对 FlexSPI 使用到的 Pin 设定

3.4.6 宣告一变数 port1_pin18_config 将对 P1_18 ( FLEXSPI0_SCLK ) 的相关参数储存其中,参数如下 ( 如图 8 ):

a ) IOPCTL_PIO_FUNC1:选择 IOPCTL function 为 1 ( FLEXSPI0_SCLK 功能 )

        b ) IOPCTL_PIO_PUPD_DI: Pull down 设定

        c ) IOPCTL_PIO_PULLDOWN_EN:Pullup / Pulldown 功能 Enable

d ) IOPCTL_PIO_INBUF_EN:对应 Reference Manual 建议,在 SPI 应用下开启此功能

e ) IOPCTL_PIO_SLEW_RATE_NORMAL:对应 Datasheet建议,在 SPI 应用下使用 Standard mode

        f ) IOPCTL_PIO_FULLDRIVE_EN:Full output drive mode

        g ) IOPCTL_PIO_ANAMUX_DI:Analog multiplexor disabled

        h ) IOPCTL_PIO_PSEDRAIN_DI:Normal push-pull output

        i ) IOPCTL_PIO_INV_DI:Input function is not inverted

3.4.7 IOCON_PinMuxSet function 中有 4 个参数需填入如下

a ) IOCON : 对应到 RT595 的 IOPCTL register address ( 0x40004000 )

b ) 1U : 对应到硬体规划的 GPIO Port 上 ( 这边宣告为 Port 1 )

c ) 18U : 对应到硬体规划的 GPIO Port Pin 上 ( 这边宣告为 Port 1 Pin 18 )

d ) port1_pin18_config : 该参数用来定义 IOPCTL register 的参数,详细参数说明如 3.4.6 所示

其馀 FLEXSPI0 Pin 的设定方式类似,这边就不再叙述

图 8

3.5 FLEXSPI0 通讯时脉设定 function

3.5.1 透过 BOARD_SetFlexspiClock function 中的参数进行通讯时脉设定,参数定义如下:

a ) FLEXSPI0 : 对应到 RT595 的 FLEXSPI0 register address ( 0x40134000 )

b ) 2 : 将 FLEXSPI0 的 Clock Source 设定为 SYSPLL0 AUX0_PLL_Clock,SYSPLL0 AUX0_PLL_Clock 源自于 SysPLL0 ( 528 MHz ),经过除频后为 396 MHz

               c ) 4 : 将 SYSPLL0 AUX0_PLL_Clock  ( 396 MHz ) / 4 等于 99 MHz

3.5.2 查看 flexspi_nor_flash_init 中的 Code ( 如图 9 )

图 9

3.5.3 查看 flexspi_nor_flash_init 将在分页中开启 flexspi_octal_flash_ops.c ( 如图 10 )

3.5.4 customLUT参数:该参数为 RT595 与外部 Flash 通讯时的相关资讯,需对应 Flash 来查看,查询 customLUT 后 main code 中可以找到对应的 Table,LUT 为 RT595 与 Device 通讯时,RT595 以查表的形式来定义要使用哪种格式与 Device 进行通讯,此处仅是将 customLUT 的参数映射到 localLUT 的结构变数中,当后续使用到该参数在细说该部分

图 10

3.5.5 进入 FLEXSPI_GetDefaultConfig function查看 ( 如图 11 ),function 中所设定的默认值如下:

  • config->rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackInternally默认由 MCU FlexSPI 产生 DQS 讯号来作为 Read Sample Clock
  • config->enableSckFreeRunning = false 选择不启用外部CLK,CLK源自 MCU 本身
  • config->enableDoze = true 当系统有打瞌睡模式请求时,AHB 时钟和串行时钟将被关闭。
  • config->enableHalfSpeedAccess = false 不启用降速功能 ( 降速除频值为 2 ),给外部 A_SCLK/B_SCLK
  • config->enableSckBDiffOpt = false 不启用B_SCLK为A_SCLK的差分时钟,通常做为 CLK_N、CLK_P 使用
  • config->enableSameConfigForAll = false 每个 FLEXSPI 都是独立 Size 计算
  • config->seqTimeoutCycle = 0xFFFFU 超时时间参数设定 ( 65535 * 1024 Serial Root Clock cycles ),超时产生中断并忽略AHB命令
  • config->ipGrantTimeoutCycle = 0xFFU IP Command 延迟时间设定 ( 255 * 1024 AHB Clock cycles ),在指定时间后 IP Command 未被下达则触发中断
  • config->txWatermark = 8 TX Watermark level is 8 * 64 Bits,当 Watermark 的空馀的程度大于或等于该水印值时,可触发中断
  • config->rxWatermark = 8 RX Watermark level is 8*64 Bits,当 Watermark 的空馀的程度大于或等于该水印值时,可触发中断
  • config->ahbConfig.ahbGrantTimeoutCycle = 0xFFU AHB 延迟时间设定 ( 255 * 1024 AHB Clock cycles ),超时即产生中断
  • config->ahbConfig.ahbBusTimeoutCycle = 0xFFFFU AHB 在设定时间内未收到或传输资料时的 time out 设定 ( 65535 * 1024 ahb clock cycles ),超时即产生中断
  • config->ahbConfig.resumeWaitCycle = 0x20U 配置在暂停命令序列恢复之前的等待空闲状态周期,等待超过设定值 AHB 个时钟后超时
  • config->ahbConfig.buffer[i].enablePrefetch = true AHB 读取预取使能
  • config->ahbConfig.buffer[i].masterIndex = 0xFU AHB RX Buffer 根据 AHB Master 的 ID (MSTR_ID) 进行分配,内容非0即使用
  • config->ahbConfig.buffer[i].bufferSize = 0 AHB RX 缓冲区大小
  • config->ahbConfig.buffer[i].enablePrefetch = true AHB 读取预取使能。
  • config->ahbConfig.buffer[i].bufferSize = 256U AHB RX 缓冲区大小

* 上述 i 值为缓冲区规划

  • config->ahbConfig.enableClearAHBBufferOpt = false 当 FlexSPI 返回停止模式 ACK 时,AHB RX/TX 缓冲区不会被自动清除
  • config->ahbConfig.enableReadAddressOpt = false 当 flash 以并行模式访问或 flash 是字寻址时,存在 AHB 读取突发起始地址对齐限制
  • config->ahbConfig.enableAHBPrefetch = false AHB 读取预取使能
  • config->ahbConfig.enableAHBBufferable = false FlexSPI 将在所有数据传输到外部设备并且 AHB 命令完成后返回 AHB 总线就绪
  • config->ahbConfig.enableAHBCachable = false 当存在 AHB 总线缓存读取访问时,FlexSPI 将不会检查它是否命中 AHB TX 缓冲区
图 11

3.5.6 进入 FLEXSPI Config 独立设定 ( 如图 12 ) 中所设定的值如下:

  • ahbConfig.enableAHBPrefetch = true AHB 读取预取使能
  • rxSampleClock = EXAMPLE_FLEXSPI_RX_SAMPLE_CLOCK Flash Read Sample Clk 来自 DQS Pin,即讯号来自于外部 Flash 的 DQS Pin
  • ahbConfig.enableAHBBufferable = true FlexSPI 将在所有数据传输到外部设备并且 AHB 命令完成后返回 AHB 总线就绪
  • ahbConfig.enableAHBCachable = true 当存在 AHB 总线缓存读取访问时,FlexSPI 将不会检查它是否命中 AHB TX 缓冲区

3.5.7 将 FLEXSPI Config 的参数设定到 FlexSPI register 中

图 12

3.5.8 将 deviceconfig 的参数设定到 FlexSPI register 的 Port A1 中 ( 如图 13 ),deviceconfig 的参数如下:

  • .flexspiRootClk = 99000000 FLEXSPI 的时钟频率
  • .flashSize = FLASH_SIZE Flash 的大小 ( KByte )
  • .CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle CS 的间隔单位可配置为 1 或 256 个周期
  • .CSInterval = 2 CS 讯号断言间隔,通过多个 CS 间隔单位来获取 CS 讯号断言间隔周期
  • .CSHoldTime = 3 CS 讯号保持时间
  • .CSSetupTime = 3 CS 讯号建立时间
  • .dataValidTime = 2 对外部设备的数据有效时间
  • .columnspace = 0 列空间大小
  • .enableWordAddress = 0 是否使能字(4字节)地址
  • .AWRSeqIndex = NOR_CMD_LUT_SEQ_IDX_WRITE AHB写命令的AHB序列ID
  • .AWRSeqNumber = 1 AHB 写命令的序列数目
  • .ARDSeqIndex = NOR_CMD_LUT_SEQ_IDX_READ AHB 读命令序列ID
  • .ARDSeqNumber = 1 AHB读命令的序列数目
  • .AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle AHB 写等待单位
  • .AHBWriteWaitInterval = 0 AHB 写等待间隔,通过多个 AHB 写间隔单位来完成AHB写等待周期
图 13

3.5.8 将 customLUT的参数设定到 FlexSPI register 中 ( 如图 14 )

3.5.9 设定软件复位完成后由硬件自动清零

3.5.10 Release CACHE,本范例不会使用到 CACHE 因此这边不做解说

图 14

3.5.11 后续的 flexspi_nor_ 类别的 Function,将会透过输入 Function 来对应 LUT 的 index 执行出不同的通讯方式,下列范例将透过 get vendor ID ( 如图 15 ) 参数来解析如何对应到 EVK 上使用的 Flash ( MX25UW51345GXDI00 )

图 15

3.5.12 这边先解析 LUT 的参数

a ) 该 LUT 是透过其他 function 的 CUSTOM_LUT_LENGTH 参数来决定取出 Table 中的哪个参数来使用 ( 如图 16 )

图 16

b ) 以 get vendor ID ( Read ID ) 参数为例 ( 如图 17 )

b1 . kFLEXSPI_Command_DDR:参数传输将以 DDR Mode 传输 ( 如图 16 ),对应到 Transmit Data 后续资料传输会以 8 bit 传输

b2 . kFLEXSPI_8PAD:参数传输将透过 8 Pin Mode 传输

b3 . 0x9F:对应 MX25UW51345GXDI00 参数 ( 如图 18 )

b4 . 0x60:对应 MX25UW51345GXDI00 参数 ( 如图 18 )

图 17 ( 注 4 )
图 18 ( 注 5 )

c ) 下一步骤的资料解析如下

c1 . kFLEXSPI_Command_RADDR_DDR:参数传输将以 DDR Mode 传输 ( 如图 19 ),对应到 Transmit Data 后续资料传输会以 32 bit 传输

c2 . kFLEXSPI_8PAD:参数传输将透过 8 Pin Mode 传输

c3. 0x20:设定传输 32 bit 的 0 值 ( 如图 18 ),若要变更该参数则可修改 flexspi_nor_get_vendor_id Function 中的 flashXfer.deviceAddress 参数

c4. kFLEXSPI_Command_DUMMY_DDR:参数传输将以 DDR Mode 传输 ( 如图 20 )

c5. 0x08:对应 MX25UW51345GXDI00 中所需的 Dummy 时间参数 ( 如图 21 ),需要等到 8 个 DDR mode 下的 SCLK 时间

图 19 ( 注 4 )
图 20 ( 注 4 )
图 21 ( 注 6 )

d ) 下一步骤的资料解析如下

d1 . kFLEXSPI_Command_READ_DDR:参数传输将以 DDR Mode 接收 ( 如图 22 )

d2 . kFLEXSPI_8PAD:参数传输将透过 8 Pin Mode 传输

d3 . 0x04 : 该参数在这边不被 function 参考,可以填任意值

d4 . kFLEXSPI_Command_STOP : 该参数是在告知 MCU 传输已结束

d5 . kFLEXSPI_1PAD : 参数传输将透过 1 Pin Mode 传输

d6 . 0x0 : 因 STOP Command 不传输实际 Data 因此填 0


图 22 ( 注 4 )

3.5.13 回到 flexspi_nor_get_vendor_id Function 中查看 ( 如图 23 ) 先关参数如下:

        a ) flashXfer.deviceAddress = 0,MCU 对 Flash 传输时的 Address

b ) flashXfer.port = FLASH_PORT,这边设定为 PortA1,因 NXP EVK 配置使用 PortA1 对 Flash 进行通讯

c ) flashXfer.cmdType = kFLEXSPI_Read,get vendor id 行为为 read,因此这边设定为 Read

d ) flashXfer.SeqNumber = 1,设定要执行的序列数目,范例中设定 1 即可

e ) flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_READID_OPI,LUT 循址 inedx

        f ) flashXfer.data = &temp,Read 后的参数摆设位址

        g ) flashXfer.dataSize = 1,读取的 ID Size 大小

h ) FLEXSPI_TransferBlocking : 透过该 Function 将 flashXfer 的参数设定到 FlexSPI register 中,并启动传输功能

i ) *vendorId = temp : 将从 Flash 中取得的 ID 参数回传到 vendorId 变数中

图 23

3.5.14 后续的其他 Function 的解析方式与上述解析雷同,本范例解析完毕


注 1:作者:NXP Semiconductors;出处:NXP 文件 IMXRT500RM Rev. 0.1 的 Fig.122

注 2:作者:NXP Semiconductors;出处:NXP 文件 spf-45800_d1

注 3 :作者:NXP Semiconductors;出处:NXP 文件 MIMXRT595EVKHUG User's Guide Rev. 0, 的 Fig.1

注 4 :作者:NXP Semiconductors;出处:NXP 文件 MIMXRT595EVKHUG User's Guide Rev. 0, 的 Table 404

注 5 :作者:MACRONIX INTERNATIONAL CO., LTD.;出处: MACRONIX 文件 MX25UM51345G Datasheet 的 Table 6

注 6 :作者:MACRONIX INTERNATIONAL CO., LTD.;出处: MACRONIX 文件 MX25UM51345G Datasheet 的 Figure 13.

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★博文作者未开放评论功能