STM32F1和STM32F4系列DMA的不同之處——對STM32的DMA的工作機制和場景的一些理解[原創www.cnblogs.com/helesheng]

喜歡用STM32的DMA功能。一方面STM32的DMA和MPU的DMA一樣,可以提高數據傳輸效率。另一方面,作爲一種MCU上的DMA,它可以提高針對外設(peripheral)的數據傳輸的實時性,改變了傳統MCU只能用定時中斷實現實時控制的方法。

比較STM32F4和STM32F1系列的DMA控制器,可以發現區別主要有三:1)增加了DMA流(Stream)的概念;2)限制了兩個DMA控制器的數據流向;3)爲每個數據流添加了可配置的FIFO緩衝區。

本文逐一比較了以上三種硬件上的改變帶來的功能方面的升級和不同。另外,還大膽猜測了STM32的芯片設計者對DMA的工作機制和場景的構想。以下原創內容歡迎網友轉載,但請註明出處: https://www.cnblogs.com/helesheng 

1. 增加DMA流(Stream)的概念

 1.1 不同之處

 我認爲STM32F4的DMA控制器的流(Stream)雖然是新增的,但可以理解爲只是對原有通道(Channel)概念的細化和擴展,新增的只是“概念”而非實體。請大家對比兩個系列數據手冊中的DMA1傳輸請求表。

圖1 STMF1系列DMA1控制器的外設傳輸請求表

圖2 STMF4系列DMA1控制器的外設傳輸請求表

 可以發現,兩個系列DMA1可以響應的外設的傳輸請求,都是可以表示爲二維的矩形表格。由於外設種類和路數也相差不大,可以想象STM32F1和STM32F4兩類控制器的DMA1和DMA2所能管理的外設傳輸請求種類和總數數也相差不大。不同點在於:STM32F4將原來STM32F1中以方式存在的“通道x”傳輸請求轉換成了的方式,替代了STM32F1表格中每行所對應的某種具體外設;STM32F4的表格中同時還將現在的每一列取了一個新的名字流(stream)。由於兩個表格中沒有增加“實體”,所以我才認爲新增的只是流這個“概念”本身。

流”這個概念的增加,卻使得STM32F4程序員可以通過軟件指定流和通道的具體編號,定位表格中的某一個確切的傳輸請求。而不像STM32F1只能指定某一通道,而無法進一步在圖1表格中定位傳輸請求來一列中的那個具體外設。也就是說在STM32F1中,每當發生外設引發的DMA傳輸請求時,程序員只能確定該傳輸請求來自圖1表格中某一列中的任何一個外設,而無法像在STM32F4中一樣定位到表格中的任意具體位置的外設。這意味着,STM32F1的程序員無法同時使用表格一列中的兩種以上外設傳輸請求,而STM32F4卻可以。 

1.2 對STM32外設DMA工作機制理解的深化

1)對比的兩種DMA 外設請求組織的形式,給我個人最大的啓示在於進一步深刻的意識到:圖1、圖2格中的外設只是DMA的傳輸“請求”(require),而非傳輸數據源(source)或目標(destination)。DMA外設數據的傳輸是由表格指定的外設動作“引發”,但傳輸數據源或目標可以和產生傳輸請求的外設完全無關

例如,需要用STM32F4的DMA控制SPI1持續地間隔1ms發送數據,就需要選擇能夠定時1ms的某個定時器(此處不妨選擇TMR3)作爲DMA的外設傳輸請求,查看圖2得到對應的通道和流爲DMA1_STREAM2_CH5。但在對DMA1_STREAM2_CH5的傳輸參數進行配置的時候,卻需要指定以SPI1的數據寄存器地址作爲傳輸目標,待發送數據存儲區地址號作爲傳輸數據源。

這種“傳輸請求”和“傳輸源和目標”分離的DMA工作機制其實在STM32F1中就一直存在,但手冊中圖1表格每行開始的“外設”一列很容易讓人產生“傳輸源”和“傳輸源/目標”只能是一種外設的誤解。

 2)傳輸模式中可以選擇“外設到內存/內存到外設”或“存儲器到存儲器”兩種類型的區別,僅僅在於DMA控制器啓動一次數據傳輸,是需要等到下一次外設的傳輸(require)請求到來(“外設到內存/內存到外設”模式);還是可以在一次傳輸完成之後不用等待指定外設的傳輸請求,直接啓動DMA傳輸(“存儲器到存儲器”模式)

例如,當用FSMC接口擴展了一個高速並行接口DAC,需要定時地向FSMC並行接口寫入數據,以產生指定波形。該應用需要定時用DMA向FSMC擴展DAC的地址傳輸數據。雖然DMA數據源和目標都是存儲器地址(內存和FSMC),但配置DMA時還必須選擇“內存到外設”或“外設到內存模式”。應爲如果配置爲“存儲器到存儲器”模式,則會導致DMA用自己最快的速度完成數據的傳輸,而不會等到定時器到採樣間隔後再輸出數據。

根據我自己對上述DMA工作機制的加深理解,我“解鎖”了GPIO高速同步數據傳輸的“新技能”,將在下一篇博文中展示用DMA 和STM32F4的高速GPIO(AHB總線)實現對獨立10MSPS ADC的控制方法和代碼,歡迎大家捧場!

2. 分別限制了兩個DMA控制器的數據流向

2.1 不同之處

STM32F1系列除了在圖1的表格中指定了每個通道的DMA請求外設之外,並沒有限制兩個DMA控制器的數據源和目標源種類。但STM32F4卻通過下圖指定了兩個DMA控制器的數據源和目標源的種類。

圖3 STM32F4系列兩個DMA控制器端口(源和目標)連接的外設/存儲器種類

 我自己初次看到這張圖並沒有什麼太深的感觸,但隨着對STM32F4的DMA使用經驗的增加,會發現這張圖對於DMA1和DMA2兩個控制器的選擇,有着重要的影響。

例如,要想實現片上SRAM存儲器到片上SRAM存儲器的數據搬運,你會發現STM32F4只能使用DMA2控制器——因爲DMA1靠下的端口被固定連接到APB1的數據端口上,無法實現SRAM到SRAM的數據傳輸。

又如,要實現上文提到的片上SRAM和GPIO之間的高速數據同步傳輸,由於STM32F4的GPIO被連接到AHB1上,而連接到AHB1的數據端口只被連接到了DMA2的兩個端口,所以也只能選用DMA2控制器來實現SRAM和GPIO之間的高速數據同步傳輸。

2.2 怎樣選擇STM32F4中的DMA控制器、流和通道

 在實際使用STM32F4中的DMA時,需要根據具體應用的要求的傳輸源和目標的硬件類型和種類,查詢圖3來確定DMA1或DMA2,舉例說明:

要將Flash中的100字節數據通過USART2(串口2)發送出去。由於USART屬於慢速設備,發送速率遠低於Flash存儲器的讀取速度。用DMA匹配二者“產生”和“消費”數據的速度,實現速度匹配的方法一般有兩種:

連續發送法:USART2並在其每發送完一個字節後,由USART2發送完成事件觸發下一次DMA數據傳輸。此時只能選擇“存儲器到外設”的工作模式,而DMA傳輸請求爲“USART2發送完成”,在圖2表格中找到USART2_TX在DMA1控制器數據流6通道4。反過來在圖3中核查一下DMA1是否有能力實現所需的數據傳輸:USART2屬於APB1總線上的外設(參加下圖4中的STM32F40x內部總線結構),可以使用圖3中DMA1靠下的端口,而DMA1另一靠上的端口的灰色連線可以連接到Flash的DCODE總線。因此使用DMA1_STREAM6_CH4可以實現這種要求的數據傳輸。

 

 圖4 STM32F40x內部結構框圖 

定時發送法:每間隔一段時間t(長於USART2發送一個字節的時間,如10ms)USART2向外發送一個字節,發送完成後USART2空閒,一直等到下一個t開始在向外發送下一個字節。也就是DMA向USART2的發送數據寄存器傳輸數據的動作由其他定時器TMR來觸發。此時可以選擇“存儲器到外設”或“外設到存儲器”模式,但不能選擇“存儲器到存儲器”模式。DMA傳輸請求可以是任意TMR的計數器更新事件。當然在啓動DMA之前,還需要將TMR3的時基配置爲10ms溢出一次。最後,在圖1或下圖5所示的STM32F4的DMA2外設傳輸請求表中選擇任意空閒的TMR更新事件。不失一般性,我選擇圖1中DMA1_STREAM2_CH5中的TMR3更新作爲DMA傳輸請求。最後,同樣需要在圖3中核查一下DMA1是否有能力實現所需的數據傳輸,器過程和上一種同步方法相同,這裏不再贅述。

圖5 STMF4系列DMA2控制器的外設傳輸請求表

3. 每個數據流(STREAM)增添了先進先出的緩衝FIFO

3.1 DMA FIFO的作用

STM32F4爲每個DMA數據流添加了獨立的四級,每級32位的先進先出緩衝區FIFO。可以看到有網文介紹DMA FIFO能夠提升DMA數據傳輸的帶寬,防止外設數據由於總線繁忙造成丟失——理由是外設數據的傳輸需求,只受DMA傳輸請求控制,傳輸請求到來時,由於系統總線繁忙,理論上有可能造成外設數據的丟失。但我個人認爲,STM32F4屬於微控制器MCU,一般常見應用不會涉及高帶寬的純數據傳輸;而外設的DMA數據傳輸帶寬都不會太大,因此需要用FIFO提升DMA帶寬和可靠性的情況很少。在搜索引擎和大模型中搜索基本很少看到DMA FIFO的應用實例,就是這一結論的旁證。

我個人認爲STM32F4的DMA FIFO的作用主要在於實現DMA源和目標數據寬度不等情況下的轉換和傳輸,以及DMA的突發傳輸(burst transfers)。而這兩個功能都是STM32F1系列DMA不具備的。

3.2 實現數據寬度不同的源與目標間的緩衝和轉換

DMA的源和目的是不同的外設和存儲器,當二者的數據寬度不同時,對於DMA控制器而言就會出現數據“生產”和“消費”速度不等的問題。爲使二者相等,數據寬度較小的一側所需的傳輸次數就必須多於數據較寬的一側。DMA控制器就需要暫時緩衝數據寬度較窄一側前幾次傳輸來的數據,DMA FIFO就可以用於實現對這些數據的緩衝。

下圖6所示的就是兩側數據寬度不同時,FIFO中存放數據的順序。

圖6 數據寬度不同時,DMA FIFO中存放數據的結構

注意:左側數據寫入的順序是B0 -> B1 -> B2 -> B3 -> B4 -> B5 -> B6……     H0 -> H1 -> H2 -> H3  …… ;

而右側讀出數據的順序是W0 -> W1 -> W2 -> W3……    H0 -> H1 -> H2 -> H3  …… 。

可以看到數據在矩形的FIFO中存儲後,以列的形式從右側讀出,而兩側的數據傳輸次數都不相等。

當然FIFO還可以被設置爲1-4的不同深度,從而使用圖5矩形中的1-4列存儲器。 

3.3 實現DMA數據突發傳輸

所謂“突發傳輸”是指,一個DMA請求引發多次數據傳輸。當源和目標的數據寬度相等,源和目標的突發傳輸次數也相同時,DMA傳輸中數據“生產”和“消費”速度也相同,理論上就不需要FIFO來參與DMA的數據緩衝和傳輸。但源和目標的數據寬度,或突發傳輸次數只要有不同,就有可能造成數據“生產”和“消費”速度不相等,此時就必須有FIFO緩衝數據。STM32F4系列要求:只有當DMA FIFO開啓時,才允許數據突發傳輸。當然,兩側數據的寬度和兩側突發傳輸的次數的關係,必須滿足數據“生產”和“消費”速度相等的基本要求

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章