數(shù)據(jù)[快遞站]——探索FIFO與DMA
在單片機或者是嵌入式編程中,通常軟件和硬件是緊密相連的。編程者需要同時擁有硬件思維和軟件技巧,才能使程序更高效、更穩(wěn)定的運行在嵌入式系統(tǒng)中。在機器人系統(tǒng)中,各個模塊間的通信就像人的神經(jīng),往往需要很高帶寬與實時性,借助DMA和FIFO能夠極大程度的發(fā)揮出外設的性能。本文將介紹使用FIFO和DMA搭配的方式,并且詳細介紹其運作的原理。

本文所述FIFO都是軟件FIFO,不包括部分DMA控制器中自帶的FIFO功能。
FIFO
FIFO是“先進先出”的縮寫,是一種常用的數(shù)據(jù)結構和算法。它是一種隊列(Queue)的實現(xiàn)方式,即先進入隊列的數(shù)據(jù)項先被處理,后進入隊列的數(shù)據(jù)項則后被處理。
環(huán)形隊列是一種特殊的FIFO數(shù)據(jù)結構,其中隊列被表示為一個環(huán)形結構。在環(huán)形隊列中,隊列的頭部和尾部被視為相鄰的元素,因此當尾部元素到達隊列的末尾時,它會回到隊列的開頭。這樣,隊列看起來像一個環(huán),因此稱為環(huán)形隊列。環(huán)形隊列可以使用數(shù)組實現(xiàn),但需要特殊處理插入和刪除元素的操作,以確保它們在隊列頭部和尾部之間循環(huán)。

FIFO可以用于緩存數(shù)據(jù),當輸入數(shù)據(jù)的速度超過處理的速度時,F(xiàn)IFO可以作為一個緩沖區(qū),暫時存儲多余的數(shù)據(jù),以平滑數(shù)據(jù)的輸入和輸出速度。另外,當需要頻繁地訪問內(nèi)存或外設時,F(xiàn)IFO可以作為一個臨時緩存區(qū),將數(shù)據(jù)暫時存儲在隊列中,以減少對內(nèi)存或外設的頻繁訪問,提高系統(tǒng)的效率。
DMA
DMA(Direct Memory Access,直接內(nèi)存訪問)。常規(guī)情況下,我們對外設的操作都是由CPU直接處理,但面向與一些低速的傳輸手段,如:IIC、UART、SPI,為了保證時序,使用CPU操作寄存器的方法去處理無疑浪費了大量的運算時間。而DMA的出現(xiàn),可以使數(shù)據(jù)可以在主存儲器和外設之間自動傳輸,而不需要CPU的干預。這可以使CPU在數(shù)據(jù)傳輸期間執(zhí)行其他任務,提高整個系統(tǒng)的效率。

如上圖所示兩條通道中,CPU只需要和DMA進行一些指令通信,DMA就能替CPU完成對外設到內(nèi)存的數(shù)據(jù)搬運。
DMA也可完成內(nèi)存到內(nèi)存等多種方式的通信,不同的廠商的芯片通常會有一些專用的DMA控制器例如:DMA2D、MDMA等,但本質都是對內(nèi)存的直接訪問。
傳輸過程
DMA的傳輸大致分為如下三個步驟:
預處理:由CPU完成一些必要的準備工作。首先,CPU執(zhí)行幾條I/O指令,用以測試I/O設備狀態(tài),向DMA控制器的有關寄存器置初值,設置傳送方向、啟動該設備等。然后,CPU繼續(xù)執(zhí)行原來的程序,直到I/O設備準備好發(fā)送的數(shù)據(jù)(輸入情況)或接受的數(shù)據(jù)(輸出情況)時,I/O設備向DMA控制器發(fā)送DMA請求,再由DMA控制器向CPU發(fā)送總線請求(統(tǒng)稱為DMA請求),用以傳輸數(shù)據(jù)。

數(shù)據(jù)傳送:DMA的數(shù)據(jù)傳輸可以以單字節(jié)(或字)為基本單位,對于以數(shù)據(jù)塊為單位的傳送,DMA占用總線后的數(shù)據(jù)輸入和輸出操作都是通過循環(huán)來實現(xiàn)。需要特別之處的是,這一循環(huán)也是由DMA控制器(而不是通過CPU執(zhí)行程序)實現(xiàn)的,即數(shù)據(jù)傳送階段是完全由DMA(硬件)來控制的。

后處理:DMA控制器向CPU發(fā)送中斷請求,CPU執(zhí)行中斷服務程序做DMA結束處理,包括檢驗送入主存的數(shù)據(jù)是否正確,測試傳送過程中是否出錯(錯誤則轉入診斷程序)和決定是否繼續(xù)使用DMA傳送其他數(shù)據(jù)塊等。

由此可以看出,整個過程中,CPU只需要介入預處理和后處理的少量指令環(huán)節(jié)。在一些特殊情況下,例如ADC數(shù)據(jù)的DMA傳輸,只需要在初始化時進行配置,DMA設置為循環(huán)模式,后續(xù)的過程完全不需要CPU介入,極大的節(jié)約了CPU時間。
快遞員與快遞站
在實際生活中,我們隨處可見DMA和FIFO的身影,為了能更加方便的理解DMA和FIFO的作用,我們可以用快遞員和快遞站來做比喻:
FIFO(先進先出隊列)是一個快遞站,快遞員將快遞按照到達時間順序放在一個隊列中,當需要發(fā)貨時,按照隊列順序一個一個地取出快遞進行發(fā)貨,保證了快遞的順序性??爝f站如果太小,如果收發(fā)快遞數(shù)量太多,快遞站就會爆滿堵塞,快遞丟失。如果快遞站過大,則占用過多土地,得不償失。
DMA(直接內(nèi)存訪問)是一名任勞任怨的快遞員,他可以直接到發(fā)貨地點取出快遞并將其送到目的地,中間的驛站可以視為內(nèi)存或者緩存。在這個過程中,快遞員可以不停歇地工作,而不需要等待驛站的確認,同時也不需要用戶的干預,可以大大提高快遞的效率和速度。
DATA(數(shù)據(jù)),數(shù)據(jù)則是快遞,快遞的尺寸數(shù)量要考慮快遞員的能力,不能過大過多。

無論是現(xiàn)實還是嵌入式系統(tǒng),人和內(nèi)核不可能時時刻刻都帶等待快遞和數(shù)據(jù)。數(shù)據(jù)的處理和接收并不一定是同時進行的,內(nèi)核對數(shù)據(jù)的等待造成了系統(tǒng)的阻塞,但數(shù)據(jù)的不及時處理會造成了數(shù)據(jù)的丟包,以上兩個原因促使了DMA和FIFO的相互補充使用。
更高的效率
以上用具體的例子比喻了DMA和FIFO的應用場景,實際應用也當如此。以下會介紹詳細的使用方法和具體的應用場景,同時開發(fā)者也要認清,并不是所有的場景都適合使用DMA,使用時要考慮實際的穩(wěn)定性和必要性。
應用場景
下面將列舉幾種場景,分別是DMA與軟件FIFO配合、DMA以及不適合DMA場景的應用。
▌DMA-FIFO
DMA-FIFO最適合數(shù)據(jù)量大、不定長的數(shù)據(jù)包的場景,典型應用為串口通信,無論是串口的接收還是發(fā)送,使用DMA-FIFO都能極大的增加芯片的運行效率,且在絕大多數(shù)情況下都能提高串口外設的性能。PWM、GPIO操作算是DMA應用中一個比較冷門的應用,使用DMA操作此類外設,能零堵塞、高時序精度去實現(xiàn)W2812全彩燈、DSHOT協(xié)議等功能。
▌DMA
單用DMA適合數(shù)據(jù)量大、定長、定周期的場景,典型應用為SPI-LCD數(shù)據(jù)傳輸、攝像頭DCMI傳輸、ADC傳輸、內(nèi)存-內(nèi)存?zhèn)鬏?,此類傳輸特點大多數(shù)為大塊數(shù)據(jù)周期性傳輸,傳輸速度要求高,數(shù)據(jù)量比較大。例如在攝像頭數(shù)據(jù)的傳輸過程中,攝像頭數(shù)據(jù)固定以30FPS進行傳輸,配合DMA的雙緩存功能能很好的實現(xiàn)數(shù)據(jù)的傳輸與處理同時進行,此外像DMA2D這種專用的圖像顯示DMA也是相同的道理。
▌不適用場景
雖然DMA在許多情況下可以提高數(shù)據(jù)傳輸?shù)男屎退俣?,但并不是所有情況都適合使用DMA。下面是一些不適合使用DMA的場合:
數(shù)據(jù)一致性場合:DMA傳輸過程中不需要CPU干預,所以實際上CPU并不知道內(nèi)存中數(shù)據(jù)發(fā)生了變動,尤其是在啟用了cache的情況下,數(shù)據(jù)一致性問題就變得尤其嚴重。例如一些加密、解密、固件寫入等場合,對數(shù)據(jù)一致性要求較高、需要實時校驗,不建議使用DMA傳輸。
時序一致性場合:DMA也不適合對于數(shù)據(jù)包時序要求嚴格的場合,例如在SPI寫入LCD數(shù)據(jù)指令前,需要先寫入控制指令并操作DC引腳,在這種情況下,如果不能將傳輸與中斷的邏輯進行妥善處理,則會造成嚴重的數(shù)據(jù)沖突,所以SPI-LCD屏一般只有在數(shù)據(jù)階段采用DMA傳輸。還有在初始化階段,程序對于效率速度的要求不高,但時序與穩(wěn)定性要求較高的時候,不建議使用DMA傳輸。
數(shù)據(jù)傳輸量較小:由于DMA傳輸存在預處理和后處理階段,例如僅傳輸幾個字節(jié)的數(shù)據(jù),那么使用DMA可能不會帶來很大的性能提升。相反CPU可能需要反復進入中斷進行處理,增加了額外的復雜性和成本。

技巧與細節(jié)
在DMA的使用過程中,也存在很多的使用技巧,例如利用好DMA的全傳輸中斷、半傳輸中斷與雙緩存,能使DMA的傳輸性能得到進一步的提高。熟悉DMA的基本屬性,需要仔細的去閱讀相應芯片廠商的技術手冊,避免其在傳輸中發(fā)生沖突,數(shù)據(jù)發(fā)生覆蓋等問題的發(fā)生。
總結
FIFO和DMA的應用只是嵌入式系統(tǒng)中優(yōu)化的一小部分,對于開發(fā)者來說,在開發(fā)過程中,“能用”并不是調(diào)好一個外設的標準。在項目調(diào)試工程中,往往會遇到因為打印了幾行日志、變更了協(xié)議格式、更改了通信速率,就發(fā)現(xiàn)程序就不能正常運行了,不嚴謹、不規(guī)范的開發(fā)方式容易使項目陷入Bug越改越多的開發(fā)陷阱中。

本文共3208字
由西湖大學智能無人系統(tǒng)實驗室工程師馬昭原創(chuàng)
申請文章授權請聯(lián)系后臺運營人員
▌微信公眾號:空中機器人前沿
▌知乎:空中機器人前沿(本文鏈接:https://zhuanlan.zhihu.com/p/623769135)
▌Youtube:Aerial robotics @ Westlake University
▌實驗室網(wǎng)站:https://shiyuzhao.westlake.edu.cn?
