无线电爱好网

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

【i.MX RT 系列】Flexspi LUT 介紹

2023-12-26 10:34| 发布者: 闪电| 查看: 1| 评论: 0

摘要: 一、LUT 與 SPI Flash 命令表的聯繫1. LUT 簡介LUT 全稱是 Look Up Table ,顧名思義就是查找表格,可以自定義一些 Flash 的命令序列,然後提供給 Flexspi 去調用:看到這裡可能還是很困惑這是個什麼東西,我們從大 ...

一、LUT 與 SPI Flash 命令表的聯繫

1. LUT 簡介

LUT  全稱是 Look Up Table ,顧名思義就是查找表格,可以自定義一些 Flash 的命令序列,然後提供給 Flexspi 去調用:

 

 

看到這裡可能還是很困惑這是個什麼東西,我們從大部分人接觸的 SPI Flash 說起,以 Winbond W25Q128JVSIQ 為例。



2. 標準 SPI Flash 命令表介紹

如下圖,平時接觸最多的 SPI 是四條線,也就是標準 SPI:CLK 、CS、 MOSI、 MISO,

 

 

假設現在要讀取 Flash 的 ID ,需要怎麼操作呢?首先在手冊中找到命令表:

 

 

注意這是標準 SPI 的命令表,可以看到讀取 Device ID 的命令是 90h ,h 代表十六進制,意思是代碼中發送該命令要使用 0x90,發送 0x90 之後是等待兩個 byte 的無效時鐘(可以在 MOSI 上發送兩個 byte 數據,此時 Flash 端不會理會這些數據),接下來再發送 0x00 ,發完之後就可以在 MISO 的數據線上讀取 Flash 返回的數據了,詳細過程如下圖;

 

 以上就是對 Flash 操作的一個完整過程,其它的命令大同小異。



3.  4 線 QSPI Flash 命令表介紹

這裡再以一個 QSPI 的命令為例(QSPI 即 4 條數據線 + CS + CLK):

 

快速讀取數據的命令是 0xEB :
首先先發送 0xEB ;
再發送 24bit 的讀取地址,分 3 個 byte 發送 ;
接著是 3 個 dummy 時鐘 ;
注意此時的時鐘個數與上一個讀取 ID 命令的是有區別的,這裡 1 個 dummy 是 2 個時鐘周期,讀取 ID 的是 8 個 CLK ,這個其實也很好理解,標準 SPI 只有一條數據線發送\接收,那麼 1 byte 就需要 8 個時鐘周期才能完整讀取;
對於QSPI 而言它有 4 跟數據線,1 個時鐘周期可以讀取 4bit 數據,2 個時鐘周期就可以讀取 8bit 也就是 1 byte,所以 dummy 的時鐘周期也就減少了,等待 3 個dummy 周期後就可以接收數據了。

 

4. SPI Flash 命令對應到 LUT 

以上兩個命令我們可以稱它們為 2 個命令序列,一個是讀取 Device ID 的命令序列,另外一個是快速讀取數據的命令序列,可以看到每個命令序列都能以 byte 為單位分解,裡面有操作命令(0x90,0xEB 等 )、dummy、地址等 ;

回到 Flexspi 的 LUT ,它的作用就是把常用的 Flash 命令序列提前放在了 LUT 的寄存器裡面,方便後續 Flesxspi 調用,只需要給命令序列編號,就能按照裡面編輯的命令順序執行了,從晶片 RM 中可以看到 LUT 一個序列的組成:

 


1 個命令序列稱為 Sequence (對於 i.MX RT1050 來說,它的 LUT 最多可以有 16 個序列,後面會解釋為何只有 16 個);
1 個 Sequence 中包含了 8 個Instruction ;( 這個 Instruction 可以將它理解為前面說的—— 1 個 Flash 命令序列能以 byte 為單位進行拆解,1 個 Instruction 就代表了一個 byte 的命令 )

1 個 Instruction 裡面有三個參數,分別是 opcode,num_pads,operand,解釋一下這三個參數的含義:

opcode:Flexspi 外設的專有命令;
比如現在需要向 Flash 發送讀取 ID 的命令 0x90 ,那麼此時就需要告訴 Flexspi 要發送操作命令到 Flash ,Flexspi 能識別的命令就是 CMD_SDR / CMD_DDR,關於 SDR 和 DDR 的區別可自行上網查找,大部分使用的是 CMD_SDR ,所以在這裡這個參數就需要填寫 0x01

 

 

SDK 中已經很貼心的將這些參數定義好了,編寫代碼的時候只需要調用就可以

 

num_pads:這個參數應該很好理解,就是執行 opcode 需要用到多少數據線,比如剛剛的 0x90 這個命令只需要一根,那麼只要給 0x0 即可,快速讀取的命令 0xEB 就需要用到 4 根線,給 0x3 即可,同樣 SDK 中的定義如下:

 

operand:這個參數代表的是執行 opcode 這個命令所需要的參數,還是以讀取 ID 的命令為例,剛剛 opcode 給的是 CMD_SDR 的命令,這個時候 Flexspi 它只知道了要發送命令過去,但是發送什麼命令過去它還不知道,這個時候就需要 operand 告訴它,所以這裡填參數 0x90 ;


根據以上描述,這裡就完成了一個序列的其中一個命令,讓我們來看看完成的是哪個部分:




二 、 代碼編寫

接下來以 SDK 中的例程來介紹怎麼將我們熟悉的 Flash 命令序列放進 LUT 當中。

 
1. LUT 表序列號

SDK 例程中用的是板載的 Flash 是 ISSI 的 IS25WP064,這裡的命令與 Winbond 有些不一樣的,在這個基礎上修改成 Winbond 的,修改之前先解釋一下為什麼前面會有 “4 * 序列號”的操作:

 

 

1 個 Sequence 規定需要有 8 個 Instruction ,規定這麼多個是為了適配一些複雜的操作 ;可以看到 1 個 Instruction 是 16bit ,那麼2 個Instruction 就是 32bit ,1 個 Sequence 就需要 4 * 32bit ,對於 i.MX RT1050 來說, LUT 寄存器只有 64 個,1 個寄存器 32bit ,那麼 1 個 Sequence 就要 4 個寄存器,所以最多只能有 16 個 Sequence ,但是這個已經遠遠夠用了,平時用的無非就是擦數據、寫數據、讀數據。

FLEXSPI_LUT_SEQ 這個宏是將兩個 Instruction 合在一起變成 32bit 的數據,方便放進一個 LUT 寄存器當中

 

 

定義的數組是直接寫進 LUT 寄存器的,長度是 64,類型是 uint32_t 的,所以其中一個數據就是 32bit ;將 64 個 LUT 寄存器分成 16 份,1 份就是 4 個寄存器,前面說過 1 個 Sequence 就需要 4 個寄存器,所以出現了 “4 * 序列號” 這個操作,那麼接下來的 “4 * 序列號 + 1” 也很好理解了,FLEXSPI_LUT_SEQ 只能合併 2 個 Instruction ,有些 Flash 命令序列 2 個 Instruction是滿足不了的,所以需要繼續往下加,“4 * 序列號 + 1” 就是往下一個相鄰的 LUT 寄存器寫,可以自己將序列號代入進去理解,這裡不再舉例說明。

 

2.  以讀取 ID 的命令為例,下圖是 ISSI 的:

 

 

序列號的宏定義可以自行定義,這裡沿用例程的,根據文章開頭說的,Winbond 的命令如下:

(1)發送 0x90 命令

Instruction0

Opcode         = kFLEXSPI Command SDR  

num_pads      = kFLEXSPI 1PAD

operand        = 0x90



(2)等待兩個 dummy

Instruction1

Opcode         = kFLEXSPI_Command_DUMMY_SDR

num_pads      = kFLEXSPI 1PAD

operand        = 0x10 ( dummy clock 的個數)

(3)發送 0x00 命令

Instruction2

Opcode         = kFLEXSPI Command SDR  

num_pads      = kFLEXSPI 1PAD

operand        = 0x00

(4)讀取數據

Instruction3

Opcode         = kFLEXSPI_Command_READ_SDR

num_pads      = kFLEXSPI 1PAD

operand        = 0x04   (該參數無意義,非 0 即可)

(5)發送 Stop 命令

Instruction4

Opcode         = kFLEXSPI_Command_STOP

num_pads      = kFLEXSPI 1PAD

operand        = 0x00  

以上就是全部步驟,實際上第 5 個步驟不加也不會出問題,因為 LUT 表的數值默認為 0 ,其 3 個參數值都為 0 ,故不影響,為了規範建議還是加上去,該序列如下:

 

 

那麼這裡就會有人問了,讀取數據的長度不用給嗎?這個長度是在調用庫函數裡面給的:

 

 

2. 以快速讀取數據的命令為例,下圖是 ISSI 的:

 

同樣,Winbond 的修改如下:



(1)發送 0xEB 命令

Instruction0

Opcode         = kFLEXSPI Command SDR  

num_pads      = kFLEXSPI 1PAD

operand        = 0xEB

 

(2)發送 24bit 讀取地址

Instruction1

Opcode         = kFLEXSPI_Command_RADDR_SDR

num_pads      = kFLEXSPI 1PAD

operand        = 0x18  (讀取地址的長度,單位 bit, 這裡用 24bit )

 

(3)發送 M7-0 dummy

Instruction2

Opcode         = kFLEXSPI_Command_MODE8_SDR

num_pads      = kFLEXSPI 4PAD

operand        = 0xFF 

(4)等待 2 個 dummy

Instruction3

Opcode         = kFLEXSPI_Command_DUMMY_SDR

num_pads      = kFLEXSPI 4PAD

operand        = 0x04  (這裡代表發送 4 個 clock 周期)

 

(5)讀取數據

Instruction4

Opcode         = kFLEXSPI_Command_READ_SDR

num_pads      = kFLEXSPI 4PAD

operand        = 0x04  (這裡參數同樣沒有意義,非 0 即可)

 

(6)發送停止命令

Instruction5

Opcode         = kFLEXSPI_Command_STOP

num_pads      = kFLEXSPI 1PAD

operand        = 0x00

如下圖,最後一行加上去是為了體現一個完整的 Sequence ,會更規範

 


LUT 表的介紹就到這裡,這裡分別介紹了標準 SPI 和 QSPI 的命令並用一條命令舉例,其它的 Flash 命令序列也是一樣,單線、4 線主要根據命令的詳細時序編寫即可。

 

參考資料:

《IMXRT1050RM》

《W25Q128JVSIQ datasheet-20180930》


路过

雷人

握手

鲜花

鸡蛋

QQ|关于本站|小黑屋|Archiver|手机版|无线电爱好网 ( 粤ICP备15040352号 ) 无线电爱好技术交流5 无线电爱好技术交流1无线电爱好技术交流9开关电源讨论群LED照明应用、电源无线电爱好技术交流4无线电爱好技术交流8无线电爱好技术交流10无线电爱好技术交流11

粤公网安备 44030702001224号

GMT+8, 2023-12-26 10:34 , Processed in 0.109201 second(s), 18 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2020, Tencent Cloud.

返回顶部