一文掌握 DMA 技術原理

DMA,全稱 Direct Memory Access,即直接存儲器訪問。

DMA 傳輸將數據從一個地址空間複製到另一個地址空間,提供在外設和存儲器之間或者存儲器和存儲器之間的高速數據傳輸

我們知道 CPU 有轉移數據、計算、控制程序轉移等很多功能,系統運作的核心就是 CPU

CPU 無時不刻的在處理着大量的事務,但有些事情卻沒有那麼重要,比方說數據的複製和存儲數據,如果我們把這部分的 CPU 資源拿出來,讓 CPU 去處理其他的複雜計算事務,是不是能夠更好的利用 CPU 的資源呢?

因此:轉移數據(尤其是轉移大量數據)是可以不需要 CPU 參與。比如希望外設 A 的數據拷貝到外設 B,只要給兩種外設提供一條數據通路,直接讓數據由 A 拷貝到 B 不經過 CPU 的處理

DMA 就是基於以上設想設計的,它的作用就是解決大量數據轉移過度消耗 CPU 資源的問題。有了 DMA 使 CPU 更專注於更加實用的操作–計算、控制等。

DMA 定義:

DMA 用來提供在外設和存儲器之間或者存儲器和存儲器之間的高速數據傳輸。無須 CPU 的干預,通過 DMA 數據可以快速地移動。這就節省了 CPU 的資源來做其他操作。

DMA 傳輸方式

DMA 的作用就是實現數據的直接傳輸,而去掉了傳統數據傳輸需要 CPU 寄存器參與的環節,主要涉及四種情況的數據傳輸,但本質上是一樣的,都是從內存的某一區域傳輸到內存的另一區域(外設的數據寄存器本質上就是內存的一個存儲單元)。四種情況的數據傳輸如下:

DMA 傳輸參數

我們知道,數據傳輸,首先需要的是 1 數據的源地址 2 數據傳輸位置的目標地址 ,3 傳遞數據多少的數據傳輸量 ,4 進行多少次傳輸的傳輸模式 DMA 所需要的核心參數,便是這四個

當用戶將參數設置好,主要涉及源地址、目標地址、傳輸數據量這三個,DMA 控制器就會啓動數據傳輸,當剩餘傳輸數據量爲 0 時 達到傳輸終點,結束 DMA 傳輸 ,當然,DMA 還有循環傳輸模式 當到達傳輸終點時會重新啓動 DMA 傳輸。 也就是說只要剩餘傳輸數據量不是 0,而且 DMA 是啓動狀態,那麼就會發生數據傳輸。  

DMA 的主要特徵

每個通道都直接連接專用的硬件 DMA 請求,每個通道都同樣支持軟件觸發。這些功能通過軟件來配置;

STM32 少個 DMA 資源?

對於大容量的 STM32 芯片有 2 個 DMA 控制器 兩個 DMA 控制器,DMA1 有 7 個通道,DMA2 有 5 個通道。每個通道都可以配置一些外設的地址。

①DMA1 controller

從外設(TIMx[x=1、2、3、4]、ADC1、SPI1、SPI/I2S2、I2Cx[x=1、2] 和 USARTx[x=1、2、3])產生的 7 個 DMA 請求,通過邏輯或輸入到 DMA1 控制器 其中每個通道都對應着具體的外設:② DMA2 controller

從外設(TIMx[5、6、7、8]、ADC3、SPI/I2S3、UART4、DAC 通道 1、2 和 SDIO)產生的 5 個請求,經邏輯或輸入到 DMA2 控制器,其中每個通道都對應着具體的外設:

這些在下方系統框圖中也可以清晰地看到

DMA 工作系統框圖

上方的框圖,我們可以看到 STM32 內核,存儲器,外設及 DMA 的連接,這些硬件最終通過各種各樣的線連接到總線矩陣中,硬件結構之間的數據轉移都經過總線矩陣的協調,使各個外設和諧的使用總線來傳輸數據。我們對他來進行一點一點的分析:

下面看有與沒有 DMA 的情況下,ADC 採集的數據是怎樣存放到 SRAM 中的?

沒有 DMA

  1. 如果沒有 DMA,CPU 傳輸數據還要以內核作爲中轉站,比如要將 ADC 採集的數據轉移到到 SRAM 中,這個過程是這樣的:

內核通過 DCode 經過總線矩陣協調,從獲取 AHB 存儲的外設 ADC 採集的數據,

然後內核再通過 DCode 經過總線矩陣協調把數據存放到內存 SRAM 中。

在這裏插入圖片描述

有 DMA 傳輸

有 DMA 的話,

  1. DMA 傳輸時外設對 DMA 控制器發出請求。

  2. DMA 控制器收到請求,觸發 DMA 工作。

  3. DMA 控制器從 AHB 外設獲取 ADC 採集的數據,存儲到 DMA 通道中

  4. DMA 控制器的 DMA 總線與總線矩陣協調,使用 AHB 把外設 ADC 採集的數據經由 DMA 通道存放到 SRAM 中,這個數據的傳輸過程中,完全不需要內核的參與,也就是不需要 CPU 的參與,

在這裏插入圖片描述

我們把上面的步驟專業一點介紹:

在發生一個事件後,外設向 DMA 控制器發送一個請求信號。DMA 控制器根據通道的優先權處理請求。當 DMA 控制器開始訪問發出請求的外設時,DMA 控制器立即發送給它一個應答信號。當從 DMA 控制器得到應答信號時,外設立即釋放它的請求。一旦外設釋放了這個請求,DMA 控制器同時撤銷應答信號。DMA 傳輸結束,如果有更多的請求時,外設可以啓動下一個週期。

總之,每次 DMA 傳送由 3 個操作組成:

DMA 傳輸方式

方法 1:DMA_Mode_Normal正常模式,

當一次 DMA 數據傳輸完後,停止 DMA 傳送 ,也就是隻傳輸一次    方法 2:DMA_Mode_Circular ,循環傳輸模式

當傳輸結束時,硬件自動會將傳輸數據量寄存器進行重裝,進行下一輪的數據傳輸。也就是多次傳輸模式

仲裁器

仲裁器的作用是確定各個 DMA 傳輸的優先級

仲裁器根據通道請求的優先級來啓動外設 / 存儲器的訪問。

優先權管理分 2 個階段:

軟件:每個通道的優先權可以在 DMA_CCRx 寄存器中設置,有 4 個等級

硬件:如果 2 個請求有相同的軟件優先級,則較低編號的通道比較高編號的通道有較高的優先權。比如:如果軟件優先級相同,通道 2 優先於通道 4。

注意:在大容量產品和互聯型產品中,DMA1 控制器擁有高於 DMA2 控制器的優先級。

DMA 數據流(僅存在於 STM32F4 /M4 內核上)

在設置了 DMA 的通道之後,還要選擇通道對應外設的數據流

8 個 DMA 控制器數據流都能夠提供源和目標之間的單向傳輸鏈路。每個數據流配置後都可以執行:● 常規類型事務:存儲器到外設、外設到存儲器或存儲器到存儲器的傳輸。● 雙緩衝區類型事務:使用存儲器的兩個存儲器指針的雙緩衝區傳輸(當 DMA 正在進行自 / 至緩衝區的讀 / 寫操作時,應用程序可以進行至 / 自其它緩衝區的寫 / 讀操作)。要傳輸的數據量(多達 65535)可以編程,並與連接到外設 AHB 端口的外設(請求 DMA 傳輸)的源寬度相關。每個事務完成後,包含要傳輸的數據項總量的寄存器都會遞減。

DMA_SxCR 寄存器控制數據流到底使用哪一個通道,每個數據流有 8 個通道可 供選擇,每次只能選擇其中一個通道進行 DMA 傳輸。接下來,我們看看 DMA2 的各數據流通 道映射表,如表 28.1.1 所示:

DMA 傳輸通道

每個通道都可以在有固定地址的外設寄存器和存儲器地址之間執行 DMA 傳輸。DMA 傳輸的數據 量是可編程的,大達到 65535。包含要傳輸的數據項數量的寄存器,在每次傳輸後遞減。

可編程的數據量:外設和存儲器的傳輸數據量可以通過 DMA_CCRx 寄存器中的 PSIZE 和 MSIZE 位編程。

指針遞增模式

根據 DMA_SxCR 寄存器中 PINC 和 MINC 位的狀態,外設和存儲器指針在每次傳輸後可以自動向後遞增或保持常量。當設置爲增量模式時,下一個要傳輸的地址將是前一個地址加上增量值

通過單個寄存器訪問外設源或目標數據時,禁止遞增模式十分有用。

如果使能了遞增模式,則根據在 DMA_SxCR 寄存器 PSIZE 或 MSIZE 位中編程的數據寬度,下一次傳輸的地址將是前一次傳輸的地址遞增 1 個數據寬度、2 個數據寬度或 4 個數據寬度。

存儲器到存儲器模式

DMA 通道的操作可以在沒有外設請求的情況下進行,這種操作就是存儲器到存儲器模式。

當設置了 DMA_CCRx 寄存器中的 MEM2MEM 位之後,在軟件設置了 DMA_CCRx 寄存器中的 EN 位啓動 DMA 通道時,DMA 傳輸將馬上開始。當 DMA_CNDTRx 寄存器變爲 0 時,DMA 傳輸結束。存儲器到存儲器模式不能與循環模式同時使用。

這裏要注意僅 DMA2 的外設接口可以訪問存儲器,所以僅 DMA2 控制器支持存儲器到存儲器的傳輸,DMA1 不支持。

存儲器到存儲器模式不能與循環模式同時使用。

DMA 中斷

每個 DMA 通道都可以在 DMA 傳輸過半、傳輸完成和傳輸錯誤時產生中斷。爲應用的靈活性考慮,通過設置寄存器的不同位來打開這些中斷。

使沒開啓,我們也可以通過查詢這些位來獲得當前 DMA 傳輸的狀態。這裏我們常用的是 TCIFx 位,即數據流 x 的 DMA 傳輸完成與否標誌。

可編程的數據傳輸寬度、對齊方式和數據大小端 當 PSIZE 和 MSIZE 不相同時,DMA 模塊按照下圖進行數據對齊。

注意:在大容量產品中, DMA2 通道 4 和 DMA2 通道 5 的中斷被映射在同一個中斷向量上。在互聯型產品 中, DMA2 通道 4 和 DMA2 通道 5 的中斷分別有獨立的中斷向量。所有其他的 DMA 通道都有自己的 中斷向量

DMA 的內存佔用

在 STM32 控制器中,芯片採用 Cortex-MX 架構,總線結構有了很大的優化,DMA 佔用另外的地址總線,並不會與 CPU 的系統總線發生衝突。也就是說,DMA 的使用不會影響 CPU 的運行速度

但是要注意:DMA 控制器和 Cortex-M3 核共享系統數據總線執行直接存儲器數據傳輸。當 CPU 和 DMA 同時訪問相同的目標 (RAM 或外設) 時,DMA 請求可能會停止 CPU 訪問系統總線達若干個週期,總線仲裁器執行循環調度,以保證 CPU 至少可以得到一半的系統總線 (存儲器或外設) 帶寬。

DMA 配置部分

此部分我們分爲 DMA 寄存器和 DMA 庫函數分別介紹:

DMA 寄存器

DMA 配置參數包括:通道地址、優先級、數據傳輸方向、存儲器 / 外設數據寬度、存儲器 / 外設地址是否增量、循環模式、數據傳輸量。

DMA 中斷狀態寄存器 (DMA_ISR)

我們如果開啓了 DMA_ISR 中這些中斷,在達到條件後就會跳到中斷服務函數里面去,即使 沒開啓,我們也可以通過查詢這些位來獲得當前 DMA 傳輸的狀態。這裏我們常用的是 TCIFx, 即通道 DMA 傳輸完成與否的標誌。

注意此寄存器爲只讀寄存器,所以在這些位被置位之後,只 能通過其他的操作來清除。

DMA 中斷標誌清除寄存器 (DMA_IFCR)

DMA_IFCR 的各位就是用來清除 DMA_ISR 的對應位的,通過寫 0 清除。在 DMA_ISR 被置位後, 我們必須通過向該位寄存器對應的位寫入 0 來清除。

DMA 通道 x 配置寄存器 (DMA_CCRx)

該寄存器控制着 DMA 的很多相關 信息,包括數據寬度、外設及存儲器的寬度、通道優先級、增量模式、傳輸方向、中斷允許、 使能等都是通過該寄存器來設置的。所以 DMA_CCRx 是 DMA 傳輸的核心控制寄存器

DMA 通道 x 傳輸數量寄存器 (DMA_CNDTRx)(x = 1…7)

這個寄存器控制 DMA 通道 x 的每次 傳輸所要傳輸的數據量。其設置範圍爲 0~65535。並且該寄存器的值會隨着傳輸的進行而減少, 當該寄存器的值爲 0 的時候就代表此次數據傳輸已經全部發送完成了。所以可以通過這個寄存 器的值來知道當前 DMA 傳輸的進度

DMA 通道 x 外設地址寄存器 (DMA_CPARx)(x = 1…7)

該寄存器用來存儲 STM32 外設的地 址,比如我們使用串口 1,那麼該寄存器必須寫入 0x40013804(其實就是 & USART1_DR)。如果使 用其他外設,就修改成相應外設的地址就行了。

DMA 通道 x 配置寄存器(DMA_CMARx)

該寄存器和 DMA_CPARx 差不多, 但是是用來放存儲器的地址的。比如我們使用 SendBuf[5200] 數組來做存儲器,那麼我們在 DMA_CMARx 中寫入 & SendBuff 就可以了。

DMA 寄存器配置流程

通道配置過程 下面是配置 DMA 通道 x 的過程 (x 代表通道號):

  1. 在 DMA_CPARx 寄存器中設置外設寄存器的地址。發生外設數據傳輸請求時,這個地址將 是數據傳輸的源或目標。

  2. 在 DMA_CMARx 寄存器中設置數據存儲器的地址。發生外設數據傳輸請求時,傳輸的數 據將從這個地址讀出或寫入這個地址。

  3. 在 DMA_CNDTRx 寄存器中設置要傳輸的數據量。在每個數據傳輸後,這個數值遞減。

  4. 在 DMA_CCRx 寄存器的 PL[1:0] 位中設置通道的優先級。

  5. 在 DMA_CCRx 寄存器中設置數據傳輸的方向、循環模式、外設和存儲器的增量模式、外 設和存儲器的數據寬度、傳輸一半產生中斷或傳輸完成產生中斷。

  6. 設置 DMA_CCRx 寄存器的 ENABLE 位,啓動該通道。

一旦啓動了 DMA 通道,它既可響應連到該通道上的外設的 DMA 請求。當傳輸一半的數據後,半傳輸標誌 (HTIF) 被置 1,當設置了允許半傳輸中斷位 (HTIE) 時,將產生 一箇中斷請求。在數據傳輸結束後,傳輸完成標誌 (TCIF) 被置 1,當設置了允許傳輸完成中斷位 (TCIE)時,將產生一箇中斷請求。

轉載鏈接:

https://mp.weixin.qq.com/s/NmCniA3a5_3FxgZSB-EryQ

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/oklRhqwLLBNhHTWzyMw8KA