在單片機或者是嵌入式編程中,通常軟件和硬件是緊密相連的。編程者需要同時擁有硬件思維和軟件技巧,才能使程序更高效、更穩定的運行在嵌入式系統中。在機器人系統中,各個模塊間的通信就像人的神經,往往需要很高帶寬與實時性,借助DMA和FIFO能夠極大程度的發揮出外設的性能。本文將介紹使用FIFO和DMA搭配的方式,并且詳細介紹其運作的原理。
? ? ? ??
作業無人機的通鏈路 ▌本文所述FIFO都是軟件FIFO,不包括部分DMA控制器中自帶的FIFO功能。
FIFO
FIFO是“先進先出”的縮寫,是一種常用的數據結構和算法。它是一種隊列(Queue)的實現方式,即先進入隊列的數據項先被處理,后進入隊列的數據項則后被處理。 環形隊列是一種特殊的FIFO數據結構,其中隊列被表示為一個環形結構。在環形隊列中,隊列的頭部和尾部被視為相鄰的元素,因此當尾部元素到達隊列的末尾時,它會回到隊列的開頭。這樣,隊列看起來像一個環,因此稱為環形隊列。環形隊列可以使用數組實現,但需要特殊處理插入和刪除元素的操作,以確保它們在隊列頭部和尾部之間循環。
FIFO可以用于緩存數據,當輸入數據的速度超過處理的速度時,FIFO可以作為一個緩沖區,暫時存儲多余的數據,以平滑數據的輸入和輸出速度。另外,當需要頻繁地訪問內存或外設時,FIFO可以作為一個臨時緩存區,將數據暫時存儲在隊列中,以減少對內存或外設的頻繁訪問,提高系統的效率。
DMA
DMA(Direct Memory Access,直接內存訪問)。常規情況下,我們對外設的操作都是由CPU直接處理,但面向與一些低速的傳輸手段,如:IIC、UART、SPI,為了保證時序,使用CPU操作寄存器的方法去處理無疑浪費了大量的運算時間。而DMA的出現,可以使數據可以在主存儲器和外設之間自動傳輸,而不需要CPU的干預。這可以使CPU在數據傳輸期間執行其他任務,提高整個系統的效率。
如上圖所示兩條通道中,CPU只需要和DMA進行一些指令通信,DMA就能替CPU完成對外設到內存的數據搬運。 ▌DMA也可完成內存到內存等多種方式的通信,不同的廠商的芯片通常會有一些專用的DMA控制器例如:DMA2D、MDMA等,但本質都是對內存的直接訪問。
傳輸過程
DMA的傳輸大致分為如下三個步驟:
預處理:由CPU完成一些必要的準備工作。首先,CPU執行幾條I/O指令,用以測試I/O設備狀態,向DMA控制器的有關寄存器置初值,設置傳送方向、啟動該設備等。然后,CPU繼續執行原來的程序,直到I/O設備準備好發送的數據(輸入情況)或接受的數據(輸出情況)時,I/O設備向DMA控制器發送DMA請求,再由DMA控制器向CPU發送總線請求(統稱為DMA請求),用以傳輸數據。
數據傳送:DMA的數據傳輸可以以單字節(或字)為基本單位,對于以數據塊為單位的傳送,DMA占用總線后的數據輸入和輸出操作都是通過循環來實現。需要特別之處的是,這一循環也是由DMA控制器(而不是通過CPU執行程序)實現的,即數據傳送階段是完全由DMA(硬件)來控制的。
后處理:DMA控制器向CPU發送中斷請求,CPU執行中斷服務程序做DMA結束處理,包括檢驗送入主存的數據是否正確,測試傳送過程中是否出錯(錯誤則轉入診斷程序)和決定是否繼續使用DMA傳送其他數據塊等。
由此可以看出,整個過程中,CPU只需要介入預處理和后處理的少量指令環節。在一些特殊情況下,例如ADC數據的DMA傳輸,只需要在初始化時進行配置,DMA設置為循環模式,后續的過程完全不需要CPU介入,極大的節約了CPU時間。
快遞員與快遞站
在實際生活中,我們隨處可見DMA和FIFO的身影,為了能更加方便的理解DMA和FIFO的作用,我們可以用快遞員和快遞站來做比喻:
FIFO(先進先出隊列)是一個快遞站,快遞員將快遞按照到達時間順序放在一個隊列中,當需要發貨時,按照隊列順序一個一個地取出快遞進行發貨,保證了快遞的順序性。快遞站如果太小,如果收發快遞數量太多,快遞站就會爆滿堵塞,快遞丟失。如果快遞站過大,則占用過多土地,得不償失。
DMA(直接內存訪問)是一名任勞任怨的快遞員,他可以直接到發貨地點取出快遞并將其送到目的地,中間的驛站可以視為內存或者緩存。在這個過程中,快遞員可以不停歇地工作,而不需要等待驛站的確認,同時也不需要用戶的干預,可以大大提高快遞的效率和速度。
DATA(數據),數據則是快遞,快遞的尺寸數量要考慮快遞員的能力,不能過大過多。
無論是現實還是嵌入式系統,人和內核不可能時時刻刻都帶等待快遞和數據。數據的處理和接收并不一定是同時進行的,內核對數據的等待造成了系統的阻塞,但數據的不及時處理會造成了數據的丟包,以上兩個原因促使了DMA和FIFO的相互補充使用。
更高的效率
以上用具體的例子比喻了DMA和FIFO的應用場景,實際應用也當如此。以下會介紹詳細的使用方法和具體的應用場景,同時開發者也要認清,并不是所有的場景都適合使用DMA,使用時要考慮實際的穩定性和必要性。
應用場景
下面將列舉幾種場景,分別是DMA與軟件FIFO配合、DMA以及不適合DMA場景的應用。
▌DMA-FIFO
DMA-FIFO最適合數據量大、不定長的數據包的場景,典型應用為串口通信,無論是串口的接收還是發送,使用DMA-FIFO都能極大的增加芯片的運行效率,且在絕大多數情況下都能提高串口外設的性能。PWM、GPIO操作算是DMA應用中一個比較冷門的應用,使用DMA操作此類外設,能零堵塞、高時序精度去實現W2812全彩燈、DSHOT協議等功能。
▌DMA
單用DMA適合數據量大、定長、定周期的場景,典型應用為SPI-LCD數據傳輸、攝像頭DCMI傳輸、ADC傳輸、內存-內存傳輸,此類傳輸特點大多數為大塊數據周期性傳輸,傳輸速度要求高,數據量比較大。例如在攝像頭數據的傳輸過程中,攝像頭數據固定以30FPS進行傳輸,配合DMA的雙緩存功能能很好的實現數據的傳輸與處理同時進行,此外像DMA2D這種專用的圖像顯示DMA也是相同的道理。
▌不適用場景
雖然DMA在許多情況下可以提高數據傳輸的效率和速度,但并不是所有情況都適合使用DMA。下面是一些不適合使用DMA的場合:
數據一致性場合:DMA傳輸過程中不需要CPU干預,所以實際上CPU并不知道內存中數據發生了變動,尤其是在啟用了cache的情況下,數據一致性問題就變得尤其嚴重。例如一些加密、解密、固件寫入等場合,對數據一致性要求較高、需要實時校驗,不建議使用DMA傳輸。
時序一致性場合:DMA也不適合對于數據包時序要求嚴格的場合,例如在SPI寫入LCD數據指令前,需要先寫入控制指令并操作DC引腳,在這種情況下,如果不能將傳輸與中斷的邏輯進行妥善處理,則會造成嚴重的數據沖突,所以SPI-LCD屏一般只有在數據階段采用DMA傳輸。還有在初始化階段,程序對于效率速度的要求不高,但時序與穩定性要求較高的時候,不建議使用DMA傳輸。
數據傳輸量較小:由于DMA傳輸存在預處理和后處理階段,例如僅傳輸幾個字節的數據,那么使用DMA可能不會帶來很大的性能提升。相反CPU可能需要反復進入中斷進行處理,增加了額外的復雜性和成本。
技巧與細節
在DMA的使用過程中,也存在很多的使用技巧,例如利用好DMA的全傳輸中斷、半傳輸中斷與雙緩存,能使DMA的傳輸性能得到進一步的提高。熟悉DMA的基本屬性,需要仔細的去閱讀相應芯片廠商的技術手冊,避免其在傳輸中發生沖突,數據發生覆蓋等問題的發生。
總結
FIFO和DMA的應用只是嵌入式系統中優化的一小部分,對于開發者來說,在開發過程中,“能用”并不是調好一個外設的標準。在項目調試工程中,往往會遇到因為打印了幾行日志、變更了協議格式、更改了通信速率,就發現程序就不能正常運行了,不嚴謹、不規范的開發方式容易使項目陷入Bug越改越多的開發陷阱中。
審核編輯:劉清
-
單片機
+關注
關注
6037文章
44568瀏覽量
636042 -
嵌入式
+關注
關注
5086文章
19140瀏覽量
305865 -
fifo
+關注
關注
3文章
389瀏覽量
43711 -
uart
+關注
關注
22文章
1238瀏覽量
101458 -
dma
+關注
關注
3文章
562瀏覽量
100636
原文標題:數據[快遞站]——探索FIFO與DMA
文章出處:【微信號:雨飛工作室,微信公眾號:雨飛工作室】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論