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.

★博文內容均由個人提供,與平台無關,如有違法或侵權,請與網站管理員聯繫。

★博文作者未開放評論功能