痞子衡嵌入式:探討i.MXRT下FlexSPI driver實現Flash編程時對於中斷支持問題

来源:https://www.cnblogs.com/henjay724/archive/2023/01/02/17020882.html
-Advertisement-
Play Games

大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是i.MXRT下FlexSPI driver實現Flash編程時對於中斷支持問題。 前段時間有客戶在官方社區反映 i.MXRT1170 下使用官方 SDK 里 FlexSPI 驅動去擦寫 Flash 時不能很好地支持全局中斷。客戶項目里用 ...



  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是i.MXRT下FlexSPI driver實現Flash編程時對於中斷支持問題

  前段時間有客戶在官方社區反映 i.MXRT1170 下使用官方 SDK 里 FlexSPI 驅動去擦寫 Flash 時不能很好地支持全局中斷。客戶項目里用了兩塊 NOR Flash,分別掛在不同的 FlexSPI 上,一塊 Flash 用於存儲 XIP 代碼(FlexSPI1),另一塊 Flash 用於存儲項目資源數據(FlexSPI2),顯然這樣的設計原理上是沒有問題的,那為什麼使能了中斷會出問題呢?今天痞子衡來分析下這個問題:

  • Note: 客戶測試的 SDK 版本為 2.12.1,對應的 FlexSPI driver 版本為 2.3.6

一、為什麼擦寫Flash時經常需要關全局中斷?

  在具體分析客戶問題之前,我們先來聊聊嵌入式應用里應對 NOR Flash 的擦寫為何大部分情況下都是要關閉全局中斷(這裡假設執行代碼空間與擦寫操作空間在同一個 Flash 上,當然是在不同區域),這其實跟如下兩個特性有關:

1.1 RWW特性(Read-While-Write)

  RWW 特性的意思是在 Flash 執行擦寫命令進入 Busy 狀態期間(Flash 內部狀態寄存器 WIP 位變狀態 1)還能否繼續響應非操作區域的讀訪問。如果 SR[WIP] = 1 時還能夠支持讀訪問,則該 Flash 支持 RWW,反之則不支持 RWW。

  絕大部分 Flash 都是不支持 RWW 特性的,這就是為什麼 Flash 擦寫操作代碼本身是需要重定向到 RAM 里去執行(尤其是回讀 SR[WIP] 狀態的代碼)。對於支持 RWW 特性的 Flash,一般是以 Block 為單位,Flash 擦寫操作代碼放在 BlockX 里執行,則可以操作 BlockX 以外的其它 Block 區域,且不需要做代碼重定向。

  現在你應該知道對於不支持 RWW 的 Flash 為什麼擦寫時需要關閉全局中斷了,因為無法保證中斷響應相關代碼全都重定向到 RAM 里了,所以乾脆在 Flash 擦寫期間不響應任何中斷。

1.2 SCLK Stop特性

  SCLK Stop 特性的意思是在 Flash 執行寫入命令接受主設備傳輸過來的 Page 數據期間,如果匯流排上 SCLK 停止(一般情況是 FlexSPI 這一端的 TXFIFO 為空或者觸發空條件),則 Flash 能否也暫停接受當前 Page 數據直到 SCLK 繼續輸出從而繼續處理剩下的 Page 數據。

  絕大部分 Flash 是不支持 SCLK Stop 特性的,因此在 MCU 端如果傳輸 Page 數據,需要一次性連續傳輸完成,一旦中途被打斷,則兩次不連續的 Page 數據傳輸可能無法得到想要的 Page 寫入結果。這也是為何 Flash 寫入期間我們需要關閉中斷。

二、FlexSPI外設寫操作設計

  關於 i.MXRT 上的 FlexSPI 外設基本情況,痞子衡有兩篇舊文 《FlexSPI支持在Flash XIP原理》《FlexSPI支持AHB方式寫入Flash》,大家先讀一下有個初步瞭解。這裡痞子衡想重點說一下 FlexSPI 關於 IPG 方式寫操作的設計,下圖為 FlexSPI 外設的模塊框圖,痞子衡用綠色線標出了 IPG 方式寫入的通路,這裡大家可以看出其中 IP_TX_FIFO 模塊起了重要的數據緩衝作用,驅動里往 FLEXSPI->TFDRx 寄存器寫入的 Page 數據會先被裝載進 IP_TX_FIFO 里,然後再傳輸出去。

  不同 i.MXRT 型號上 IP_TX_FIFO 大小不一樣,目前有三種大小: 128/256/1024 Bytes。對於 QuadSPI/OctalSPI NOR Flash 來說,Page 大小一般是 256 Bytes;對於 HyperBus Flash,Page 大小一般是 512 Bytes。所以在 i.MXRT10xx 上 IP_TX_FIFO 是不足以緩衝整個 Page 的,i.MXRT117x 上可以緩衝 QuadSPI/OctalSPI NOR 類型的 Page,i.MXRT118x/5xx/6xx 上則可以緩衝全部 NOR Flash 類型的 Page。對於 Page 數據不能全部緩衝的情況,則需要一邊傳輸一邊緩衝。

型號 FlexSPI外設 IP TX FIFO大小
i.MXRT118x 2 x dual-channel /16-bit 1024 Bytes
i.MXRT117x
i.MXRT116x
1 x dual-channel /8-bit
1 x dual-channel /16-bit
256 Bytes
i.MXRT106x
i.MXRT1042
2 x dual-channel /8-bit 128 Bytes
i.MXRT105x 1 x dual-channel /8-bit 128 Bytes
i.MXRT1024 2 x dual-channel /8-bit 128 Bytes
i.MXRT1021
i.MXRT1015
1 x dual-channel /8-bit 128 Bytes
i.MXRT1011 1 x dual-channel /8-bit 128 Bytes
i.MXRT6xx 1 x dual-channel /8-bit 1024 Bytes
i.MXRT5xx 2 x dual-channel /8-bit 1024 Bytes

  在具體裝載數據進 IP_TX_FIFO 時,主要涉及如下三個 FLEXSPI 寄存器,IP_TX_FIFO 一次只能被填入 watermark level 大小的數據,想要把全部 Page 數據填進 IP_TX_FIFO,需要分多次裝載。只要 FLEXSPI->INTR[IPTXWE] 標誌為 0, 即代表 IP_TX_FIFO 剩餘空間大於等於 watermark level,那麼就可以繼續裝載。

FLEXSPI->IPTXFCR[TXWMRK]  -- 設置一次裝載進 IP_TX_FIFO 的數據長度(即 watermark level),8 Bytes為單位
FLEXSPI->TFDRx            -- 按 watermark level 長度填入 IP_TX_FIFO 裝載數據
FLEXSPI->INTR[IPTXWE]     -- 觸發 IP_TX_FIFO 的一次裝載

三、客戶問題及FlexSPI driver寫操作流程

  前面鋪墊了這麼多,終於來到客戶遇到的 FlexSPI 驅動對於中斷不支持的問題了。因為客戶使用了兩片 Flash,所以不存在 RWW 限制問題,那剩下的原因就跟 SCLK Stop 特性有關,即 IP_TX_FIFO 並沒有緩衝全部的 Page,導致 Page 傳輸過程被中斷打斷了,然後 IP_TX_FIFO 因為緩衝數據全部發完而使 FlexSPI 模塊進入了 SCLK Stop 狀態。

  我們直接打開 fsl_flexspi.c 驅動文件,找到跟寫操作相關的 FLEXSPI_TransferBlocking() 函數,在函數實現里可以發現,啟動寫傳輸時序的控制位 FLEXSPI->IPCMD[TRG] 是在 IP_TX_FIFO 填充動作 FLEXSPI_WriteBlocking() 函數之前被開啟的,那這樣的實現確實是不能夠很好地支持中斷的。

四、如何改進FlexSPI driver支持中斷?

  知道了原因所在,改起來也很簡單。如果是 QuadSPI/OctalSPI NOR Flash 類型(Page=256 Bytes),在 i.MXRT117x 上,其 IP_TX_FIFO 大小為 256 Bytes,能夠緩衝全部的 Page 大小,則可以先調用 FLEXSPI_WriteBlocking() 裝載全部的 Page 數據,然後再開啟 FLEXSPI->IPCMD[TRG] 去觸發寫傳輸時序,這時候就不怕被中斷打斷了,如下代碼所示。

  當然下麵代碼只是一個 workaround 式的實現示例,不是一個完整的解決方案,畢竟 FlexSPI 驅動要適配全部 i.MXRT 型號以及全部類型的 NOR Flash,此外還適用 NAND 型 Flash(Page 一般是 2KB),這時候需要根據情況拆分調用多次 FLEXSPI_WriteBlocking() 函數(不管怎樣要保證啟動寫傳輸時序前,把 IP_TX_FIFO 先裝滿)。

status_t FLEXSPI_TransferBlocking(FLEXSPI_Type *base, flexspi_transfer_t *xfer)
{
    // 代碼略去

    /* Start Transfer. */
    if ((xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
    {
        result = FLEXSPI_WriteBlocking(base, xfer->data, xfer->dataSize);
        base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
    }
    else if (xfer->cmdType == kFLEXSPI_Read)
    {
        base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
        result = FLEXSPI_ReadBlocking(base, xfer->data, xfer->dataSize);
    }
    else
    {
        base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
    }

    // 代碼略去
}

  至此,i.MXRT下FlexSPI driver實現Flash編程時對於中斷支持問題痞子衡便介紹完畢了,掌聲在哪裡~~~

歡迎訂閱

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

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

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

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

  衡傑(痞子衡),目前就職於某知名外企半導體公司MCU系統部門,擔任嵌入式系統應用工程師。

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

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

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

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

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



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

-Advertisement-
Play Games
更多相關文章
  • 力扣104 求二叉樹的最大深度 題目: 給定一個二叉樹,找出其最大深度。 二叉樹的深度為根節點到最遠葉子節點的最長路徑上的節點數。 說明: 葉子節點是指沒有子節點的節點。 示例 給定二叉樹 [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 返回它的最大深度 3 ...
  • 力扣100 相同的樹 題目: 給你兩棵二叉樹的根節點 p 和 q ,編寫一個函數來檢驗這兩棵樹是否相同。 如果兩個樹在結構上相同,並且節點具有相同的值,則認為它們是相同的。 示例 1: 輸入:p = [1,2,3], q = [1,2,3] 輸出:true 示例 2: 輸入:p = [1,2], q ...
  • RequestMappingHandlerAdapter是Spring Web MVC中針對@Controller和@RequestMapping體系的處理器適配器,本文對RequestMappingHandlerAdapter的組成、初始化以及同步請求處理流程進行詳細梳理和總結。 ...
  • 家居網購項目實現012 以下皆為部分代碼,詳見 https://github.com/liyuelian/furniture_mall.git 29.功能27-Ajax檢驗註冊名 29.1需求分析/圖解 用戶註冊時,後端通過驗證,提示用戶當前輸入的用戶名是否可用。 29.2思路分析 29.3代碼實現 ...
  • JZ76 刪除鏈表中重覆的結點 題目 在一個排序的鏈表中,存在重覆的結點,請刪除該鏈表中重覆的結點,重覆的結點不保留,返回鏈表頭指針。 例如,鏈表 1->2->3->3->4->4->5 處理後為 1->2->5 方法1 哈希表進行刪除 思路 演算法實現 LinkedHashMap實現順序插入,不過查 ...
  • C++中有左值和右值的概念。其實,左值和右值的區分也同樣適用於類對象,本文中將左值的類對象稱為左值對象,將右值的類對象稱為右值對象。 1. C++11:引用限定符 預設情況下,對於類中用 public 修飾的成員函數,既可以被左值對象調用,也可以被右值對象調用。舉個例子: #include <ios ...
  • 目前項目當中存有 .NET Framework 和 .NET Core 兩種類型的項目,但是都需要進行容器化將其分別部署在 Windows 集群和 Linux 集群當中。在 WCF 進行容器化的時候,遇到了以下幾個問題: 1. 某些服務使用到了 WSHttpBinding 保護服務安全,要在容器里... ...
  • 今天在寫一個通訊錄實現程式的時候,遇到個讓我突然卡殼的問題,不知道怎麼進行兩個結構體之間的成員互換......結構體成員有“姓名”,“性別”,“年齡”,“地址”,“電話”,目的就是實現一個通過年齡進行sort排序的功能,作為一個努力學習的編程小白來說,有太多的東西需要學習了..........代碼如 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...