痞子衡嵌入式:淺聊恩智浦i.MXRT官方SDK里關於串列Flash相關的驅動與常式資源(上篇)

来源:https://www.cnblogs.com/henjay724/p/18289104
-Advertisement-
Play Games

大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是恩智浦i.MXRT官方SDK里關於串列Flash相關的驅動與常式資源。 經常有同事以及 i.MXRT 客戶咨詢痞子衡,咱們恩智浦官方 SDK 里有哪些串列 Flash 相關的示例,每一次痞子衡都是按照詢問需求將 SDK 里相應資源路徑發 ...



  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是恩智浦i.MXRT官方SDK里關於串列Flash相關的驅動與常式資源

  經常有同事以及 i.MXRT 客戶咨詢痞子衡,咱們恩智浦官方 SDK 里有哪些串列 Flash 相關的示例,每一次痞子衡都是按照詢問需求將 SDK 里相應資源路徑發給對方。看來那句俗話說得也不盡然對,酒香也怕巷子深,今天痞子衡就給大家全面梳理一下 SDK 里和串列 Flash 相關的全部資源。

  • Note 1: 本文內容主要以 SDK_2_15_100_EVKB-IMXRT1050 軟體包里的資源為例
  • Note 2: 本文共分為上下兩篇,本篇是上篇,主要介紹 drivers 和 components

一、Flash相關驅動概覽

  首先直接開門見山,痞子衡把 SDK 里和 Flash 有關係的驅動全部羅列如下,分佈在 device driver、components、middleware、azure-rtos 里。 這四個目錄下的驅動關係簡單概括如下:

1. device driver 就是晶元底層外設的 HAL 級驅動,代碼里直接操作外設寄存器。
2. components 是基於 device driver 而設計的面向某個外圍器件/具體小功能的驅動,代碼里直接調用 devcie driver 里的 API。
3. middleware 則是面向某類具體功能的更大型的軟體庫,代碼里一般調用 components 里的 API,強調與晶元外設底層隔離,主打平臺無關的通用性。
4. azure-rtos 本身是硬體無關的 RTOS,但是其也同時包含了一些類似 middleware 功能實現,這些 middlware 會調用 components 里的 API。

二、Flash驅動解釋及常式

2.1 drivers

2.1.1 flexspi

  fsl_flexspi 驅動是晶元外設 FlexSPI 的 HAL 級驅動,其是操作 FlexSPI 寄存器以實現 1-8bit SPI 類主設備方式數據收發,其 API 本身和 Flash 晶元操作並沒有直接的聯繫,這從如下主要 API 原型可以看出來:

void FLEXSPI_Init(FLEXSPI_Type *base, const flexspi_config_t *config);
void FLEXSPI_SetFlashConfig(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port);
void FLEXSPI_UpdateLUT(FLEXSPI_Type *base, uint32_t index, const uint32_t *cmd, uint32_t count);
status_t FLEXSPI_WriteBlocking(FLEXSPI_Type *base, uint8_t *buffer, size_t size);
status_t FLEXSPI_ReadBlocking(FLEXSPI_Type *base, uint8_t *buffer, size_t size);
status_t FLEXSPI_TransferBlocking(FLEXSPI_Type *base, flexspi_transfer_t *xfer);
status_t FLEXSPI_TransferNonBlocking(FLEXSPI_Type *base, flexspi_handle_t *handle, flexspi_transfer_t *xfer);

  如下配套常式調用 fsl_flexspi 驅動里 API 實現了官方 RT1050-EVKB 板卡上的 hyperflash (S26KS512S) 和四線 nor flash (IS25WP064A) 的讀寫功能驗證。

常式路徑: \SDK_2_15_100_EVKB-IMXRT1050\boards\evkbimxrt1050\driver_examples\flexspi
  - Hyper Flash 驅動: \driver_examples\flexspi\hyper_flash\polling_transfer\flexspi_hyper_flash_ops.c
  - Nor Flash 驅動:   \driver_examples\flexspi\nor\polling_transfer\flexspi_nor_flash_ops.c

  其中常式里的 flexspi_xxx_flash_ops.c 源文件設計其實有那麼一點 components 的味道,從 API 命名來看其實現了面向 Flash 的讀寫擦功能,但是 API 里的代碼實現比較簡潔,沒有過度設計,對於不同廠商/類型的 Flash 支持,主要依賴用戶定義的 LUT 表裡的命令序列

void flexspi_nor/hyper_flash_init(FLEXSPI_Type *base);
status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address);
status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src);
status_t flexspi_nor_flash_read(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src, uint32_t length);
2.1.2 lpspi

  fsl_lpspi 驅動是晶元外設 LPSPI 的 HAL 級驅動,其是操作 LPSPI 寄存器以實現 1bit(4bit) SPI 主/從設備方式數據收發,API 本身和 Flash 晶元也沒有直接的聯繫。

void LPSPI_MasterInit(LPSPI_Type *base, const lpspi_master_config_t *masterConfig, uint32_t srcClock_Hz);
void LPSPI_SlaveInit(LPSPI_Type *base, const lpspi_slave_config_t *slaveConfig);
status_t LPSPI_MasterTransferBlocking(LPSPI_Type *base, lpspi_transfer_t *transfer);
status_t LPSPI_MasterTransferNonBlocking(LPSPI_Type *base, lpspi_master_handle_t *handle, lpspi_transfer_t *transfer);
status_t LPSPI_SlaveTransferNonBlocking(LPSPI_Type *base, lpspi_slave_handle_t *handle, lpspi_transfer_t *transfer);

  該驅動的配套常式是單純的 SPI 匯流排傳輸,並沒有針對 Flash,這裡就不展開了,但是它會在 components/flash 里被用到,後文會提及。

2.1.3 romapi

  fsl_romapi 驅動是晶元固化 BootROM 所導出的通用 Flash API,在 BootROM 里集成了基於 FlexSPI 外設驅動而寫成的通用 Flash 驅動,這個 Flash 驅動設計差不多是 components 級別,具體源代碼原則上不可見,但其實我們可以在 middleware/mcu_bootloader 里大概知道。

常式路徑: \SDK_2_15_100_EVKB-IMXRT1050\boards\evkbimxrt1050\driver_examples\fsl_romapi

  該驅動的 API 比較有意思,既有面向 Flash 的寫擦功能,也有偏 FlexSPI 外設 HAL 級別的介面。前者相比 flexspi 驅動配套的常式里對於 Flash 的支持就強大多了,用戶完全可以僅靠 API 定義的簡化參數來支持不同廠商/類型的 Flash;而後者存在的意義是為了讓用戶能夠進一步設計面向 Flash 的功能函數

status_t ROM_FLEXSPI_NorFlash_Init(uint32_t instance, flexspi_nor_config_t *config);
status_t ROM_FLEXSPI_NorFlash_ProgramPage(uint32_t instance, flexspi_nor_config_t *config, uint32_t dstAddr, const uint32_t *src);
status_t ROM_FLEXSPI_NorFlash_EraseSector(uint32_t instance, flexspi_nor_config_t *config, uint32_t address);
status_t ROM_FLEXSPI_NorFlash_CommandXfer(uint32_t instance, flexspi_xfer_t *xfer);
status_t ROM_FLEXSPI_NorFlash_UpdateLut(uint32_t instance, uint32_t seqIndex, const uint32_t *lutBase, uint32_t seqNumber);

  總結一下,使用 fsl_romapi 常式相比 fsl_flexspi 常式去操作 Flash,好處是省代碼空間且不需要考慮 Read-While-Write 限制(僅對驅動本身執行而言,無需代碼重定向,但是全局中斷問題仍要考慮),壞處是源代碼是個黑盒子,出問題不容易定位。

2.2 components

2.2.1 mx25r_flash

  mx25r_flash 組件其實是為 LPC54114 板卡上的旺巨集寬電壓四線 NOR Flash MX25R 系列而設計的,其在 \SDK_2_xxx_LPCXpresso54114\boards\lpcxpresso54114\driver_examples\spi\polling_flash 常式里有被調用,而在 i.MXRT 系列 SDK 里並沒有相關常式使用它(不要疑問為啥會出現在軟體包里,多就是好)。這個組件設計得挺有意思,其代碼實現完全與晶元具體外設隔離,外設介面傳輸函數是通過 callback 形式傳入的,充滿了代碼抽象(面向對象)的味道,有興趣可以查看源碼。

mx25r_err_t mx25r_init(struct mx25r_instance *instance, transfer_cb_t callback, void *callback_prv);
mx25r_err_t mx25r_cmd_read(struct mx25r_instance *instance, uint32_t address, uint8_t *buffer, uint32_t size);
mx25r_err_t mx25r_cmd_write(struct mx25r_instance *instance, uint32_t address_256_align, uint8_t *buffer, uint32_t size_256_max);
mx25r_err_t mx25r_cmd_sector_erase(struct mx25r_instance *instance, uint32_t address);
2.2.2 internal_flash

  internal_flash 組件從名字上看像是為片內 Flash 而設計的,但是 i.MXRT 系列並無片內 Flash(RT1024/1064 只是 SIP 了串列 NOR Flash,本質上還是片外)。大家不要被這個名字騙了,這個組件最早確實是用於恩智浦 Kinetis/LPC 系列片內 Flash 的,但是在 i.MX RT 上因為配套 EVK 上有支持 XIP 的外置 NOR Flash,所以這個組件也沿用給這些外置 NOR Flash 了,因此其是基於 flexspi 驅動的組件。

  在 \components\internal_flash\fsl_adapter_flash.h 文件里一共定義了 10 個 API 介面,其中如下 4 個是必須要實現的,其餘 6 個可以不用實現(跟 Kinetis/LPC 片內 Flash 特性緊相關)。因為 RT1050-EVKB 預設連接的 hyperflash,所以該組件也僅為其做了相應實現 \components\internal_flash\hyper_flash。這個組件代碼實現跟 flexspi 驅動配套常式里對於 Flash 的支持差不多。

hal_flash_status_t HAL_FlashInit(void);
hal_flash_status_t HAL_FlashProgram(uint32_t dest, uint32_t size, uint8_t *pData);
hal_flash_status_t HAL_FlashEraseSector(uint32_t dest, uint32_t size);
hal_flash_status_t HAL_FlashRead(uint32_t src, uint32_t size, uint8_t *pData);

  internal_flash 組件設計的意義在於 SDK 其它常式中如果有 IAP 操作或者存儲運行參數需求,均可以調用這個統一介面來實現,當然客戶應用有相應需求,也一樣可以使用

2.2.3 flash

  flash 組件里一共有三個: nornandmflash,咱們一個個來說:

2.2.3.1 nor

  先來介紹 nor 組件,從 \components\flash\nor\fsl_nor_flash 文件里的 API 命名來看,肯定是面向 NOR Flash 的讀寫擦功能,介面設計上對於底層外設採用了輕度抽象的方法,形參不涉及具體外設,但是函數實現里不同外設需要不同的實現,這也是為什麼我們能看到 \nor\flexspi 和 \nor\lpspi 兩個文件夾里的源代碼。雖然底層外設不同,但是它們要操作的均是相同的串列 NOR Flash。

status_t Nor_Flash_Init(nor_config_t *config, nor_handle_t *handle);
status_t Nor_Flash_Read(nor_handle_t *handle, uint32_t address, uint8_t *buffer, uint32_t length);
status_t Nor_Flash_Page_Program(nor_handle_t *handle, uint32_t address, uint8_t *buffer);
status_t Nor_Flash_Erase_Sector(nor_handle_t *handle, uint32_t address);
status_t Nor_Flash_Is_Busy(nor_handle_t *handle, bool *isBusy);

  \nor\flexspi 里的代碼實現跟 romapi 驅動實現方式有點像,其會從 Flash 里讀取 SFDP 表進行解析從而自動獲取所需操作命令,不依賴用戶填充 LUT 命令

常式路徑: \SDK_2_15_000_EVKB-IMXRT1050\boards\evkbimxrt1050\component_examples\flash_component\flexspi_nor

  \nor\lpspi 里的代碼實現則比較簡單,因為 LPSPI 外設本身主要支持 1bit SPI 傳輸,所以其也僅實現了一線方式對 Flash 進行讀寫擦,這部分命令是通用的,也無需用戶填充 LUT。

2.2.3.2 nand

  再來介紹 nand 組件,從 \components\flash\nand\fsl_nand_flash.h 文件里的 API 命名來看,肯定是面向 NAND Flash 的讀寫擦功能,介面設計上對於底層外設同樣採用了輕度抽象的方法,形參不涉及具體外設,但是函數實現里不同外設需要不同的實現,這也是為什麼我們能看到 \nand\flexspi 和 \nor\semc 兩個文件夾里的源代碼。不過 flexspi 外設和 semc 外設所支持的 NAND 不是一個產品,前者是串列 NAND,後者是並行 NAND,完全是兩類不同的存儲器標準。

  \nand\flexspi 里的代碼實現則比較簡潔,因為串列 NAND 發展不如串列 NOR 那樣豐富多樣,所以其使用了固定 LUT 里的預設命令序列,基本能夠支持華邦等主流四線串列 NAND 產品。

status_t Nand_Flash_Init(nand_config_t *config, nand_handle_t *handle);
status_t Nand_Flash_Read_Page(nand_handle_t *handle, uint32_t pageIndex, uint8_t *buffer, uint32_t length);
status_t Nand_Flash_Page_Program(nand_handle_t *handle, uint32_t pageIndex, const uint8_t *src, uint32_t length);
status_t Nand_Flash_Erase_Block(nand_handle_t *handle, uint32_t blockIndex);
2.2.3.3 mflash

  最後要重點介紹 mflash 組件,其分為 drv 層和 file 層兩種不同類型的 API,drv 層提供基於晶元外設的底層 Flash 操作(詳見 \mflash\mimxrt1052 文件夾下代碼),file 層則是基於 drv 層里的 API 而設計的輕量級靜態文件系統,簡單理解就是將 Flash 虛擬成一個由具有固定最大長度的預定義命名文件集組成的存儲空間,我們可以將小數據以文件名索引的方式寫入 Flash,適用於需要存儲運行參數或者設備配置數據的場合

// 來自 \components\flash\mflash\mflash_file.h
bool mflash_is_initialized(void);
status_t mflash_init(const mflash_file_t *dir_template, bool init_drv);
status_t mflash_file_save(char *path, uint8_t *data, uint32_t size);
status_t mflash_file_mmap(char *path, uint8_t **pdata, uint32_t *psize);

// 來自 \components\flash\mflash\mflash_common.h
int32_t mflash_drv_init(void);
int32_t mflash_drv_sector_erase(uint32_t sector_addr);
int32_t mflash_drv_page_program(uint32_t page_addr, uint32_t *data);
int32_t mflash_drv_read(uint32_t addr, uint32_t *buffer, uint32_t len);
void *mflash_drv_phys2log(uint32_t addr, uint32_t len);
uint32_t mflash_drv_log2phys(void *ptr, uint32_t len);

  mflash 組件會在 middleware 以及 rtos 里被廣泛使用,這個痞子衡將會在下篇里再具體介紹。

  至此,恩智浦i.MXRT官方SDK里關於串列Flash相關的驅動與常式資源痞子衡便介紹完畢了,掌聲在哪裡~~~

歡迎訂閱

文章會同時發佈到我的 博客園主頁CSDN主頁知乎主頁微信公眾號 平臺上。

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

  最後歡迎關註痞子衡個人微信公眾號【痞子衡嵌入式】,一個專註嵌入式技術的公眾號,跟著痞子衡一起玩轉嵌入式。

痞子衡嵌入式-微信二維碼 痞子衡嵌入式-微信收款二維碼 痞子衡嵌入式-支付寶收款二維碼

  衡傑(痞子衡),目前就職於某全球頂級半導體原廠MCU系統部門,擔任高級嵌入式系統應用工程師。

  專欄內所有文章的轉載請註明出處:http://www.cnblogs.com/henjay724/

  與痞子衡進一步交流或咨詢業務合作請發郵件至 [email protected]

  可以關註痞子衡的Github主頁 https://github.com/JayHeng,有很多好玩的嵌入式項目。

  關於專欄文章有任何疑問請直接在博客下麵留言,痞子衡會及時回覆免費(劃重點)答疑。

  痞子衡郵箱已被私信擠爆,技術問題不推薦私信,堅持私信請先掃碼付款(5元起步)再發。



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 單元測試 前言 時隔多個月,終於抽空學習了點新知識,那麼這次來記錄一下C#怎麼進行單元測試,單元測試是做什麼的。 我相信大部分剛畢業的都很疑惑單元測試是乾什麼的?在小廠實習了6個月後,我發現每天除了寫CRUD就是寫CRUD,幾乎用不到單元測試。寫完一個功能直接上手去測,當然這隻是我個人感受,僅供參考 ...
  • 在人生的重要時刻,我站在了畢業的門檻上,望著前方的道路,心中涌動著對未來的無限憧憬與些許忐忑。面前,兩條道路蜿蜒伸展:一是繼續在職場中尋求穩定,一是勇敢地走出一條屬於自己的創新之路。儘管面臨年齡和現實的挑戰,我仍舊選擇勇往直前,用技術這把鑰匙,開啟新的人生篇章。 迴首過去,我深知時間寶貴,精力有限。 ...
  • 相信很多.NETer看了標題,都會忍不住好奇,點進來看看,並且順便準備要噴作者! 這裡,首先要申明一下,作者本人也非常喜歡Linq,也在各個項目中常用Linq。 我愛Linq,Linq優雅萬歲!!!(PS:順便吐槽一下,隔壁Java從8.0版本推出的Streams API,抄了個四不像,一點都不優雅 ...
  • 首先下載centos07鏡像,建議使用阿裡雲推薦的地址: https://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/?spm=a2c6h.25603864.0.0.59b5f5ad5Nfr0X 其實這裡就已經出現第一個坑了 centos 07 /u ...
  • 問題 有很多應用程式在驗證JSON數據的時候用到了JSON Schema。 在微服務架構下,有時候各個微服務由於各種歷史原因,它們所生成的數據對JSON Object屬性名的大小寫規則可能並不統一,它們需要消費的JSON數據的屬性名可能需要大小寫無關。 遺憾的是,目前的JSON Schema沒有這方 ...
  • 第十章 板卡信息實驗 1)實驗平臺:正點原子DNK210開發板 2)章節摘自【正點原子】DNK210使用指南 - CanMV版 V1.0 3)購買鏈接:https://detail.tmall.com/item.htm?&id=782801398750 4)全套實驗源碼+手冊+視頻下載地址:http ...
  • 前言 由於個人學習測試需要,想要在debian11環境下,使用podman搭建一個簡單的單節點rocketmq,搭建過程比較繁瑣,所以記錄下來留作後續參考。 由於對rocketmq鏡像不熟悉,有些配置可能存在錯誤,會在後續有能力優化時繼續更新此文檔。 後續可能會補充podman-compose實現方 ...
  • 在開發過程中,我們偶爾會用到跨架構Linux容器。 ruri全稱“輕量型,用戶友好的Linux容器實現”,是一個1M左右大小的Linux容器實現,提供了一系列功能選項,致力於成為更加強大且安全的chroot命令替換。 我們以在x86_64系統下運行arm64的Ubuntu容器為例: 確認binfmt ...
一周排行
    -Advertisement-
    Play Games
  • 通過WPF的按鈕、文本輸入框實現了一個簡單的SpinBox數字輸入用戶組件並可以通過數據綁定數值和步長。本文中介紹了通過Xaml代碼實現自定義組件的佈局,依賴屬性的定義和使用等知識點。 ...
  • 以前,我看到一個朋友在對一個系統做初始化的時候,通過一組魔幻般的按鍵,調出來一個隱藏的系統設置界面,這個界面在常規的菜單或者工具欄是看不到的,因為它是一個後臺設置的關鍵界面,不公開,同時避免常規用戶的誤操作,它是作為一個超級管理員的入口功能,這個是很不錯的思路。其實Winform做這樣的處理也是很容... ...
  • 一:背景 1. 講故事 前些天有位朋友找到我,說他的程式每次關閉時就會自動崩潰,一直找不到原因讓我幫忙看一下怎麼回事,這位朋友應該是第二次找我了,分析了下 dump 還是挺經典的,拿出來給大家分享一下吧。 二:WinDbg 分析 1. 為什麼會崩潰 找崩潰原因比較簡單,用 !analyze -v 命 ...
  • 在一些報表模塊中,需要我們根據用戶操作的名稱,來動態根據人員姓名,更新報表的簽名圖片,也就是電子手寫簽名效果,本篇隨筆介紹一下使用FastReport報表動態更新人員簽名圖片。 ...
  • 最新內容優先發佈於個人博客:小虎技術分享站,隨後逐步搬運到博客園。 創作不易,如果覺得有用請在Github上為博主點亮一顆小星星吧! 博主開始學習編程於11年前,年少時還只會使用cin 和cout ,給單片機點點燈。那時候,類似async/await 和future/promise 模型的認知還不是 ...
  • 之前在阿裡雲ECS 99元/年的活動實例上搭建了一個測試用的MINIO服務,以前都是直接當基礎設施來使用的,這次準備自己學一下S3相容API相關的對象存儲開發,因此有了這個小工具。目前僅包含上傳功能,後續計劃開發一個類似圖床的對象存儲應用。 ...
  • 目錄簡介快速入門安裝 NuGet 包實體類User資料庫類DbFactory增刪改查InsertSelectUpdateDelete總結 簡介 NPoco 是 PetaPoco 的一個分支,具有一些額外的功能,截至現在 github 星數 839。NPoco 中文資料沒多少,我是被博客園群友推薦的, ...
  • 前言 前面使用 Admin.Core 的代碼生成器生成了通用代碼生成器的基礎模塊 分組,模板,項目,項目模型,項目欄位的基礎功能,本篇繼續完善,實現最核心的模板生成功能,並提供生成預覽及代碼文件壓縮下載 準備 首先清楚幾個模塊的關係,如何使用,簡單畫一個流程圖 前面完成了基礎的模板組,模板管理,項目 ...
  • 假設需要實現一個圖標和文本結合的按鈕 ,普通做法是 直接重寫該按鈕的模板; 如果想作為通用的呢? 兩種做法: 附加屬性 自定義控制項 推薦使用附加屬性的形式 第一種:附加屬性 創建Button的附加屬性 ButtonExtensions 1 public static class ButtonExte ...
  • 在C#中,委托是一種引用類型的數據類型,允許我們封裝方法的引用。通過使用委托,我們可以將方法作為參數傳遞給其他方法,或者將多個方法組合在一起,從而實現更靈活的編程模式。委托類似於函數指針,但提供了類型安全和垃圾回收等現代語言特性。 基本概念 定義委托 定義委托需要指定它所代表的方法的原型,包括返回類 ...