痞子衡嵌入式:不清i.MXRTxxx裡FLEXSPI_MCR0暫存器保留位會造成IP CMD讀寫異常

痞子衡發表於2024-03-09

  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是不清i.MXRTxxx裡FLEXSPI_MCR0暫存器保留位會造成IP CMD讀寫異常

  痞子衡曾經寫過一篇文章 《改動i.MXRT1xxx裡IOMUXC_GPR暫存器保留位可能會造成系統異常》,這篇文章提出了一個觀點,即對於 MCU 外設暫存器應使用謹慎賦值法(應該先讀回初值再做位操作賦值,不要忽略初值直接整體賦值),如今三年過去了,這個經驗狠狠地反噬了痞子衡一把,一度把痞子衡除錯到崩潰,且聽痞子衡辛酸道來:

一、引出NAND訪問問題

  痞子衡最近需要在恩智浦無線系列 SoC(RW612)上除錯序列 NAND Flash 驅動,簡單理解這顆晶片其實就是 RT600 + 多模無線 SIP 到一起,但是其 MCU 部分對 RT600 做了精簡以及魔改。因為痞子衡對 i.MX RT 特別熟,所以自然想到先在 RT500/600 上調通序列 NAND Flash,然後再做簡單移植就大功告成了,沒想到被這麼個想法坑慘了。

  痞子衡手裡早就有成熟的 RT1050 系列序列 NAND Flash 驅動(並不是基於官方 SDK 底層驅動),單從 FlexSPI 外設角度來看,RT1xxx 和 RTxxx 差異不太大,基本是相容的,所以痞子衡很快就將程式碼從 RT1050 移植到了 RT500 上,工程編譯幾乎是一把過,然而在 RT500 上實測時卻連 NAND 的 JEDEC ID 都無法正常讀取,IP CMD 獲取到的值永遠是 0x0。

  • i.MX RT上序列NAND驅動: https://github.com/JayHeng/RT-SNAND

  由於序列 NAND Flash 驅動程式碼在 RT1050 上得到過驗證,所以其本身不存在邏輯問題,大機率問題還是出在 FlexSPI 外設配置上,於是痞子衡經過 RT1050 vs RT500 各種單元對比測試(此處耗費時間較長),最終發現是由 FLEXSPI_MCR0[7:6] 的配置值不同引起的。

二、關於FLEXSPI_MCR0暫存器保留位

  在 RT500 參考手冊(Rev.2)以及 RT600 參考手冊(Rev1.5)裡檢視 FlexSPI 模組的 MCR0 暫存器描述,會發現 MCR0[7:6] 是保留位,且復位預設值為 1。

1. RT500 手冊描述來看,這兩個保留位可讀不建議寫,且讀回值應該是 0
2. RT600 手冊對這兩個保留位描述是 both bits must be written with ones.

  作為對比我們再檢視一下 RT 四位數系列(如 RT1050)上相關描述,這兩個位並不是保留位,其具體功能是決定訪問 IP TX/RX FIFO 資料的方式是 AHB bus 還是 IP bus。預設值 1 表明只能從 AHB bus 訪問 IP TX/RX FIFO,這個初始值設定其實稍微有點不合理,畢竟 AHB bus 已經有專用的 AHB TX/RX Buffer 傳輸資料了。

三、FLEXSPI_MCR0暫存器保留位測試

  在 RT500/600 上 FLEXSPI_MCR0[7:6] 是保留位,那這個保留位到底是什麼意思?到底是沒有這個 ATDFEN/ARDFEN 相應功能,還是單純不對使用者開放而已,這裡就需要做一個實驗來驗證。

  痞子衡在 RT500-EVK 上用連在 FlexSPI PortA 上的那顆四線 NOR 做測試,我們嘗試用 IP CMD 發 Read JEDEC ID 命令讀取 2byte 資料,在 FLEXSPI_MCR0[7:6] 為預設 2'b11 的情況下,可以看到 FLEXSPI_RFDRx 暫存器全是 0,這意味著 IP bus 根本就沒有觸發 IP RX FIFO 工作。

  將 FLEXSPI_MCR0[7:6] 設為 2'b00 再測一次,這時可以看到 FLEXSPI_RFDRx 暫存器裡開始有資料了,IP bus 觸發 IP RX FIFO 幹活了。

  現在我們知道了,RT500/600 上 FLEXSPI_MCR0[7:6] 雖然是保留位,但是其 ATDFEN/ARDFEN 功能仍然是存在的。

四、SDK驅動處理方法

  在官方 SDK 2.14 的 fsl_flexspi 驅動 FLEXSPI_Init() 函式里對於 MCR0 暫存器採取得是忽略初值直接整體賦值的初始化方式,其關於 ATDFEN/ARDFEN 位操作根據特性宏來做條件編譯。這樣的處理導致 RT500/600 上 FLEXSPI_MCR0[7:6] 永遠被重置為 2'b00。例程測試結果上來看似乎沒有問題,但是這裡存在一定不合理的地方。

1. 在 RTxxx 標頭檔案 FlexSPI 模組暫存器定義裡沒有 ATDFEN/ARDFEN 位資訊,但有如下特性宏定義
  #define FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN (1)
  #define FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN (1)
2. 在 RT1xxx 標頭檔案 FlexSPI 模組暫存器定義裡有 ATDFEN/ARDFEN 位資訊,無上述特性宏定義

五、經驗與教訓

  回到文章開頭,痞子衡推薦的 MCU 外設暫存器謹慎賦值法在這個案例裡就完全失效了。我們知道 MCU 外設暫存器有保留位是業界常規做法,但是保留位到底是無功能還是功能不開放,這個要看具體情況。如果應用程式碼是基於官方 SDK 底層驅動,那麼可能不會遇到問題。如果你需要重寫底層驅動,想手撕暫存器,那就要特別小心了,關於暫存器保留位的處理是值得深思的。

  至此,不清i.MXRTxxx裡FLEXSPI_MCR0暫存器保留位會造成IP CMD讀寫異常痞子衡便介紹完畢了,掌聲在哪裡~~~

歡迎訂閱

文章會同時釋出到我的 部落格園主頁CSDN主頁知乎主頁微信公眾號 平臺上。

微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。

相關文章