引言
考慮到DMA是一個AHB Master設(shè)備,可以同處理器內(nèi)核一樣,主動向總線發(fā)起傳輸請求,將“小臟手”伸向各總線上掛載的各外設(shè)模塊,因此,我更愿意把DMA看做是處理器核心服務(wù)的一部分,甚至把它當成一個小核或者協(xié)處理器都不為過。
DMA可以在CPU之外,捕獲到觸發(fā)信號后,自行搬運數(shù)據(jù)從指定地址到另一個指定地址,并且還可以根據(jù)預先的配置自動計算下一次搬運的地址。使用DMA可以有效地節(jié)約CPU處理海量數(shù)據(jù)傳輸?shù)呢撦d。可以想見,如果使用中斷方式處理通過外設(shè)發(fā)送或者接收數(shù)據(jù),CPU將會在頻繁切換中斷服務(wù)之間花費大量的時間。
另外,DMA從DMAMUX獲取的觸發(fā)源,能夠?qū)崿F(xiàn)的自動讀寫的操作,若是某些讀操作或者寫操作能夠產(chǎn)生額外的觸發(fā)事件,還可以傳遞觸發(fā),形成觸發(fā)鏈,最終可實現(xiàn)一些完全不需要硬件干預的自動化任務(wù)。總之,DMA真心是一個功能豐富的模塊。
本文將介紹YTM32平臺上DMA的工作機制,對關(guān)鍵概念展開講解。
簡介
YTM32(以YTM32B1ME05為例)微控制器上集成的DMA控制器可以支持16個通道,并且搭配了一個多達128個選項的DMA MUX模塊,可以對接任何一個通道。其中多個通道是復用同一個DMA控制器的,并且共用同一個數(shù)據(jù)搬運引擎。DMA MUX管理了可以觸發(fā)DMA通道的硬件事件,每款芯片可能都不一樣(YTM32B1MD14中的DMAMUX只有64個選項),在具體使用時,需要從具體的芯片手冊中查表。
還需要特別注意的是,目前YTM32平臺上的DMA尚未支持異步時鐘模式,它使用core clock驅(qū)動,僅能在普通模式下工作,在休眠模式、深度休眠以及更低功耗的休眠模式下,均停止工作。
本DMA控制器通過多個通道的傳輸任務(wù)描述符(CTS)管理搬運數(shù)據(jù)的過程,并且還支持鏈接模式,即將多個傳輸任務(wù)描述符連鏈接在一起,形成傳輸任務(wù)鏈。
原理與機制
DMA控制器是一個AHB總線主機,但仍同普通的外設(shè)一樣,作為一個APB總線從機,被配置成合適的工作模式。DMA控制器通過DMAMUX,可以直接收集來自片上其他外設(shè)模塊發(fā)出的觸發(fā)信號,進而觸發(fā)DMA在地址空間搬運數(shù)據(jù)的過程。如圖x所示。
圖x DMA控制器的系統(tǒng)框圖
需要注意的是,DMA的搬運過程是在地址空間內(nèi)操作的,可以是從內(nèi)存到內(nèi)存,從外設(shè)到外設(shè),在內(nèi)存與外設(shè)之間等,對于DMA而言,只是搬數(shù),至于數(shù)據(jù)映射到物理設(shè)備是外設(shè)還是內(nèi)存,均由總線負責落實。
相對于有的DMA控制器將觸發(fā)信號和搬運數(shù)據(jù)源頭地址或目標地址綁定的設(shè)計,YTM32的DMA控制器將觸發(fā)信號和搬運任務(wù)所使用的地址相互獨立,例如,當某個定時器模塊產(chǎn)生的觸發(fā)信號觸發(fā)了DMA的一個搬運數(shù)據(jù)的任務(wù)(通道),這個任務(wù)可以將ADC轉(zhuǎn)換結(jié)果的數(shù)據(jù)搬運到內(nèi)存中。這其中,定時器和ADC是沒有直接關(guān)聯(lián)的。
DMA通道的傳輸任務(wù)描述符
YTM32的DMA的各個通道,可以看做是各自獨立的傳輸任務(wù),每個任務(wù)都有自己的觸發(fā)條件、對觸發(fā)條件的響應方式、搬運數(shù)據(jù)的源地址和目的地址、搬運數(shù)據(jù)的帶寬、搬運數(shù)據(jù)的數(shù)量、每次搬運完成后對搬運過程進行調(diào)整的策略等,如此看來,DMA控制器就是這些獨立任務(wù)的調(diào)度器,當多個任務(wù)被同時觸發(fā)時,以一定的調(diào)度策略安排他們依次運行。
DMA通道對應的這些獨立的搬運任務(wù),在DMA引擎的建模中,被稱為CTS(DMA Channel Transfer Structure),其結(jié)構(gòu)如圖x所示。
圖x DMA通道的傳輸任務(wù)描述符
這個結(jié)構(gòu)的內(nèi)容并不是以指針的方式存放在SRAM中,而是直接做在寄存器結(jié)構(gòu)里,可以在DMA的寄存器清單中找到與之一一對映的寄存器。如圖x所示。
圖x CTS對應的每個通道各自下轄的一組寄存器
但CTS也可以存放在RAM中,若配置了DMA_CTS_CSR[RLDEN]=1
,則在大循環(huán)完成后,直接從寄存器DMA_CTS_DTO
(原來存放的是地址偏移量)存放的指針進行索引,搬運整個CTS結(jié)構(gòu)體的內(nèi)存覆寫到CTS對應的寄存器中。
除此之外,只是借鑒CTS結(jié)構(gòu)中相關(guān)的寄存器,去配置DMA傳輸任務(wù)的參數(shù)即可,不必受限于CTS的抽象數(shù)據(jù)結(jié)構(gòu)。
DMA的觸發(fā)信號
YTM32的DMA控制器為每個DMA搬運任務(wù)設(shè)計了兩種觸發(fā)方式:軟件觸發(fā)和硬件觸發(fā)。其中,軟件觸發(fā)可由CPU直接向DMA控制器的寄存器寫數(shù)(DMA_CTSn_CSR[START]
),主動啟動傳輸過程;硬件觸發(fā)使用預設(shè)的硬件觸發(fā)信號,當來自外設(shè)的硬件觸發(fā)信號通過DMAMUX到來之時,自動啟動DMA搬運任務(wù)開始搬數(shù)。DMA的每次觸發(fā),執(zhí)行一次小循環(huán)的搬運過程,一個大循環(huán)可以包含多個小循環(huán)的,因此一個大循環(huán)的搬運任務(wù)可能會需要多次觸發(fā)才能完成。(關(guān)于大小循環(huán)的概念,可見樓下)
- 軟件觸發(fā)
DMA的軟件觸發(fā)是通過軟件寫各通道的寄存器位DMA_CTSn_CSR[START]
,或者寄存器DMA_START
中對應通道的控制位實現(xiàn)的,每寫1次就發(fā)出一個觸發(fā)信號。每次觸發(fā),執(zhí)行一次小循環(huán)(one trigger loop)的搬運過程,TCNT寄存器中的計數(shù)器減1。
特別注意,軟件觸發(fā)是直接作用于DMA控制器的,不必配置DMAMUX的那個always_on
的選項。但由此也可知,哪怕有可用的硬件觸發(fā)通過DMAMUX輸入到DMA控制器,軟件觸發(fā)也可以生效。相當于是,軟件觸發(fā)和DMAMUX導入的硬件觸發(fā)信號相或,然后統(tǒng)一輸入到DMA控制器。
- 硬件觸發(fā)
DMA的硬件觸發(fā)信號來自于DMAMUX
,而DMAMUX
則可以從眾多觸發(fā)信號的源中選擇其中一個適用于某個指定的通道(寄存器DMA_CHMUXn
)。具體選項可在芯片手冊中查閱,如圖x所示。
圖x 從手冊中查閱DMAMUX選項
DMAMUX選中的觸發(fā)信號,還需要經(jīng)過一個REQEN
的門控開關(guān)(寄存器DMA_REQEN
中對應通道的控制位),才能順利進入DMA引擎。因此,每次使用DMA開始傳輸之前,如果要使用外部的硬件觸發(fā)源,必須確保打開這個門控開關(guān)。另外,每個DMA通道的傳輸描述符中的寄存器位DMA_CTS_CSR[DREQ]=1
還可以控制在每個大循環(huán)傳輸完成之后,自動關(guān)閉這個門控開關(guān)。如果DMA_CTS_CSR[DREQ]=0
,則這個門控開關(guān)在大循環(huán)傳輸完畢后仍會保持打開。
這里提到的硬件觸發(fā)信號,是直接來自于外設(shè)的DMA觸發(fā)信號,通常會伴隨著這些外設(shè)的某些事件的發(fā)生,大多同時也可以觸發(fā)中斷。以LINFlexD為例,有對應的DMA觸發(fā)信號的開關(guān),如圖x所示。
圖x SPI外設(shè)模塊的使能DMA請求控制位
DMA的大循環(huán)和小循環(huán)
一個最完整的DMA傳輸,可以包含多次觸發(fā),而每次觸發(fā),會引起連續(xù)地搬運一塊數(shù)據(jù)(可以是連續(xù)的多個字節(jié))。以此,完整的DMA搬運有大循環(huán)(Major Loop)
和小循環(huán)(Minor Loop)
的概念,大循環(huán)包含小循環(huán)。
YTM32的手冊中使用了Transfer Loop
和Trigger Loop
的名字:
- Transfer loop means data transferred after one DMA channel trigger.
- Trigger loop means DMA channel could accept how many DMA channel triggers(include software and hardware trigger).
從手冊的描述中可以獲知,Transfer Loop
描述的是一次觸發(fā)(one trigger)執(zhí)行的包含若干個transfer的搬運過程,而Trigger Loop
可以包含多個觸發(fā)(many triggers),對應大循環(huán)和小循環(huán)。如圖x所示。
圖x DMA搬數(shù)過程中的大循環(huán)和小循環(huán)
小循環(huán)搬運的字節(jié)數(shù),由各DMA通道的BCNT
寄存器指定,它本身也是一個遞減計數(shù)器,每傳輸一個字節(jié)就減1,減到0時就停止搬運。
大循環(huán)的包含的小循環(huán)的次數(shù)(不是字節(jié)數(shù),是對觸發(fā)信號的計數(shù)),由各DMA通道的TCNT_KDDIS[TCNT]
寄存器字段指定,它本身也是一個遞減計數(shù)器,每執(zhí)行一次小循環(huán)(觸發(fā))就減1,減到0時就停止。特別注意,此處的大循環(huán)管理的僅僅是觸發(fā),而不是傳輸內(nèi)存塊,如果使用多個傳輸任務(wù)描述符鏈接起來的傳輸任務(wù)描述鏈表,則每個任務(wù)描述符(可能在不同的地址塊和傳輸模式搬運數(shù)據(jù))都對應屬于各自的觸發(fā)次數(shù)(同一個通道的觸發(fā)源仍為同一個)。
大循環(huán)執(zhí)行一半和完畢時都有對應的標志位(DMA_CHTLHDIF
和DMA_CHTLDIF
),這里有個特別的設(shè)計,只有啟用DMA傳輸通道的大循環(huán)半完成和全完成的中斷時(DMA_CTS_CSR[THDINT]=1
和DMA_CTS_CSR[TDINT]=1
),這兩個標志位才會置位,否則哪怕對應的事件到來,也不會被置位。但另一個傳輸完成標志位(DMA_DONE
和DMA_CTS_CSR[DONE]
),無論是否開啟對應的中斷(DMA_CTS_CSR[LOOPINT]
),都能置位。這里就有一點小糾結(jié)了,如果同時啟動了DMA_CTS_CSR[LOOPINT]
和DMA_CTS_CSR[TDINT]=1
,DMA_DONE
和DMA_CHTLDIF
所對應的行為將完全一樣,那么在一個大循環(huán)完成后產(chǎn)生中斷,其中的服務(wù)程序就需要同時清零這兩個標志位。(這里的設(shè)計似乎有點冗余,有似乎缺了點什么。。。)
DMA搬運任務(wù)的地址更新策略
DMA外設(shè)設(shè)計了非常靈活的搬運地址更新策略,可以覆蓋最大范圍的應用場景。但需要整理清楚其中的概念和更新時機,才能玩轉(zhuǎn)DMA,否則,一不小心產(chǎn)生了錯誤的參數(shù)配置狀態(tài),DMA也將會停止工作并報錯(DMA_ERS
)。
重申一次DMA搬數(shù)中的操作單元:
- 一次指定帶寬的總線傳輸被稱為一個搬運
Transfer
- 一次觸發(fā)可以發(fā)起一個或多個連續(xù)的
Transfer
,也可被稱為Transfer Loop
或者a loop of transfers
,這也對應文中描述的小循環(huán)Minor Loop
。 - 一組觸發(fā)可以包含一個或者多個連續(xù)的
Minor Loop
,也可被稱為Trigger Loop
或者a loop of triggers
,這對應文中描述的大循環(huán)Major Loop
。
以數(shù)據(jù)源地址指針為例(數(shù)據(jù)目標地址指針相同):
- 最初的數(shù)據(jù)地址存放在寄存器
DMA_CSR_SADDR
中。這個寄存器中的值也會隨著DMA搬運過程的執(zhí)行變化,始終指向即將要搬運數(shù)據(jù)的地址。 - 預先配置
DMA_CTS_TCNT
寄存器的值大于等于1,表示本次DMA傳輸任務(wù)至少包含1次觸發(fā)產(chǎn)生的小循環(huán)。 - 一次觸發(fā)將啟動搬數(shù)過程。先從小循環(huán)走起。
- 每次總線傳輸搬運的數(shù)據(jù)長度(寬度),由寄存器
DMA_CSR_TCR[SSIZE]
配置,可以選擇1 Byte、2 Byte、4 Byte,以及16 Byte和32 Byte,這也代表了DMA使用數(shù)據(jù)總線的數(shù)據(jù)帶寬。每次搬運都是從當前的數(shù)據(jù)地址開始搬運帶寬指定數(shù)量的字節(jié)數(shù)。搬運過后,不對當前搬運數(shù)據(jù)地址產(chǎn)生影響,指針保持不變。 - 每次搬運執(zhí)行后,可以由軟件指定一個地址偏移量,由寄存器
DMA_CSR_SOFF
配置,可以是正整數(shù),也可以是負整數(shù)(地址向前跳)。這個偏移量是作用于當前搬運數(shù)據(jù)地址指針寄存器DMA_CSR_SADDR
的,當搬運執(zhí)行后,當前地址指針將會加上這個偏移量,更新成新的地址指針。 - 如果有多次傳輸,則多次傳輸會連續(xù)執(zhí)行。
DMA_CTS_BCNT
寄存器預置了本次小循環(huán)的需要數(shù)據(jù)的總長度(以字節(jié)為單位),而不是地址范圍(切記,地址有可能是不連續(xù)地跳躍)。DMA控制器內(nèi)部會自動遞減DMA_CTS_BCNT
寄存器的數(shù),但不會覆寫到DMA_CTS_BCNT
寄存器中,因為整個小循環(huán)的搬運過程是連續(xù)執(zhí)行的,用戶看不到中間狀態(tài)。 - 當小循環(huán)完成后,可以有一個對源數(shù)據(jù)地址指針的偏移。然而,這里并沒有設(shè)計。
DMA_CTS_TCNT
寄存器的值減1,并覆寫到DMA_CTS_TCNT
寄存器中。如果值仍大于0,則說明當前的大循環(huán)任務(wù)還沒執(zhí)行完,繼續(xù)等下一個觸發(fā)啟動一次小循環(huán)。如果值被減到0,說明大循環(huán)任務(wù)完成,此時,DMA_DONE
和DMA_CHTLDIF
(若開放中斷)都會置位,同時,DMA控制器還會更新兩個計數(shù)值:- 源數(shù)據(jù)指針在加上了最后一次搬運的偏移量(由寄存器
DMA_CSR_SOFF
配置)之后,還會立即繼續(xù)疊加一個大循環(huán)完成地址偏移,由寄存器DMA_CSR_STO
配置,這也是一個可正可負的整數(shù)。計算的結(jié)果會覆寫到寄存器DMA_CSR_SADDR
中。 - 將
DMA_CTS_TCNTRV
寄存器中預存的重載值覆寫到DMA_CTS_TCNT
寄存器中,以便于啟動下次任務(wù)時無需重新配置這些計數(shù)器和地址指針。
說起來,個人覺得,如果設(shè)計小循環(huán)結(jié)束后有一個地址偏移,比實現(xiàn)大循環(huán)結(jié)束后的地址偏移更加直觀一些。大循環(huán)專門管理觸發(fā)(管理觸發(fā)的遞減和循環(huán)),小循環(huán)管理指針(地址的遞減和遞增等),分工相對更明確些。這里實現(xiàn)的大循環(huán)的一次性偏移,也可以等價實現(xiàn)為等分到每次小循環(huán)之后的地址偏移。
讀者可以自行進行實驗,觀察DMA寄存器中各計數(shù)器的變化。
圖x 利用Keil的寄存器調(diào)試界面調(diào)試
DMA控制器還支持Scatter Gather模式,將多個DMA傳輸任務(wù)串聯(lián)在一起,可以實現(xiàn)地址不規(guī)則的連續(xù)傳輸。在地址增長模式上,還有個回環(huán)遞增的模式可以用。可以在具體用到的時候再深究。手冊上的描述比較簡略,屆時仍需要用戶發(fā)揮主觀能動性,大膽猜想多做嘗試。
應用要點(軟件)
-
定時器
+關(guān)注
關(guān)注
23文章
3287瀏覽量
117160 -
協(xié)處理器
+關(guān)注
關(guān)注
0文章
83瀏覽量
18460 -
AHB總線
+關(guān)注
關(guān)注
0文章
18瀏覽量
9729 -
DMA控制器
+關(guān)注
關(guān)注
1文章
43瀏覽量
12558 -
SRAM存儲器
+關(guān)注
關(guān)注
0文章
88瀏覽量
13575
發(fā)布評論請先 登錄
YTM32的LIN通信協(xié)議引擎LinFlexD外設(shè)模塊詳解

如何利用DMA的觸發(fā)循環(huán)實現(xiàn)對eTMR的PWM周期計數(shù)呢?

YTM32的模數(shù)轉(zhuǎn)換器ADC外設(shè)模塊詳解

基于DMA控制器的UART串行通信設(shè)計

鼠標HID例程(中)簡析
基于AMBA總線的DMA控制器IP核設(shè)計

Crossbar的多通道DMA控制器設(shè)計

dma控制器芯片8257資料介紹

dma控制器由什么組成

dma控制器的組成
dma控制器是什么_dma控制器工作方式
請問DMA控制器可以減輕CPU負擔嗎?

評論