目前STM32家族中有些系列支持DMA的雙緩沖模式,比如STM32F2/STM32F4/STM32F7等系列。尤其隨著人們對(duì)STM32F4/F7系列應(yīng)用不斷拓寬和加深,在設(shè)計(jì)中運(yùn)用到DMA雙緩沖的場(chǎng)合也越來越多。STM32芯片中的DMA又可分為兩大類,一類是通用DMA,一類是專用DMA,比如用于USB,TFT LCD,ETHERNET等外設(shè)應(yīng)用上的DMA。這里要談的是基于通用DMA的話題,不妨以STM32F4系列芯片為例。
關(guān)于STM32F4的DMA雙緩沖傳輸在STM32F4系列的參考手冊(cè)里做了簡(jiǎn)單描述。因?yàn)樗腔诮榻B了單緩沖模式的DMA介紹之后接著介紹的,稍顯言簡(jiǎn)意賅。
相比單緩沖的數(shù)據(jù)流,雙緩沖多了一個(gè)DMA存儲(chǔ)區(qū)和相應(yīng)的存儲(chǔ)指針;
如果使能DMA雙緩沖,硬件會(huì)自動(dòng)使能DMA的循環(huán)傳輸模式;
每一批數(shù)據(jù)傳輸結(jié)束,或者說每次傳輸事務(wù)結(jié)束時(shí)通過交換存儲(chǔ)指針實(shí)現(xiàn)更換存儲(chǔ)區(qū)的目的。
4.DMA雙緩沖模式僅在外設(shè)與存儲(chǔ)器間進(jìn)行,不支持memoryto Memory間的傳輸。
基于DMA雙緩沖模式的的特點(diǎn),不難理解在應(yīng)用中必須開辟兩個(gè)存儲(chǔ)區(qū)以及存放兩個(gè)存儲(chǔ)區(qū)首地址的存儲(chǔ)寄存器,DMA_SxM0AR和DMA_SxM1AR。
DMA_SxM0AR:指向存儲(chǔ)區(qū)0,單緩沖模式下默認(rèn)使用該寄存器做存儲(chǔ)區(qū)指針。
DMA_SxM1AR:指向存儲(chǔ)區(qū)1,僅在DMA雙緩沖模式下才能使用。
DMA正在訪問的當(dāng)前存儲(chǔ)區(qū)由CT@DMA_SxCR位表示
?CT = 0:DMA正在訪問存儲(chǔ)區(qū)0,CPU可以訪問存儲(chǔ)區(qū)1
?CT = 1:DMA正在訪問存儲(chǔ)區(qū)1,CPU可以訪問存儲(chǔ)區(qū)0
使用DMA雙緩沖傳輸,既可以減少CPU的負(fù)荷,又能最大程度地實(shí)現(xiàn)DMA數(shù)據(jù)傳輸和CPU數(shù)據(jù)處理互不打擾又互不耽擱,同時(shí)也給應(yīng)用開發(fā)也帶來方便。比如,假設(shè)你使用DMA單存儲(chǔ)緩沖,有些情況下可能是等待DMA搬完了數(shù)據(jù),CPU才過來處理;有些情況下可能是DMA一邊傳輸,CPU也一邊來訪問,這時(shí)往往會(huì)使用到環(huán)形存放和讀取,代碼實(shí)現(xiàn)起來稍顯繁瑣也容易出紕漏。如果改為DMA雙緩沖模式,應(yīng)用上實(shí)現(xiàn)起來也就簡(jiǎn)潔很多。再加上DMA雙緩沖模式的循環(huán)特性,使用它對(duì)存儲(chǔ)區(qū)的空間容量要求也會(huì)大大降低。尤其在大批量數(shù)據(jù)傳送時(shí),你只需開辟兩個(gè)合適大小的存儲(chǔ)區(qū),能滿足DMA在切換存儲(chǔ)區(qū)時(shí)的當(dāng)前新存儲(chǔ)區(qū)空出來就好,并不一定要開辟多大多深的存儲(chǔ)空間。有過這方面應(yīng)用經(jīng)驗(yàn)的工程師可能就有體會(huì),單純一味地加大雙緩沖區(qū)的深度并不明顯改善數(shù)據(jù)傳輸狀況。
關(guān)于這點(diǎn)不妨打個(gè)比方,某茶館有倆芳名分別為CPU和DMA的伺茶MM,,每人手里有個(gè)同樣茶壺。DMA負(fù)責(zé)把她手里的茶壺裝滿茶水就好,CPU就負(fù)責(zé)用從DMA手里接過裝滿茶水的壺給客人倒茶,倒完了用空壺與DMA交換裝滿茶水的壺繼續(xù)工作。顯然,只要保證CPU妹妹茶壺里總有茶水,至于那兩個(gè)茶壺選多大容積并不是很重要。倒是那個(gè)茶壺進(jìn)出口徑對(duì)整個(gè)事情的效率有影響。
關(guān)于DMA雙緩沖話題,我們也不妨看看一個(gè)具體的案例加深下印象。案例來自網(wǎng)絡(luò),為了盡量壓縮篇幅,我省卻了部分配置代碼,留下需要交流的關(guān)鍵語句。
&&&&&&&&&&&&&&&&&
F407 DMA的double Buffer mode上卡了好久了!大家看看配置哪里出問題了?
uint8_tBuffer0[] = {0x11,0x22,0x33,0x44}; //無符號(hào)的8位整型數(shù)
uint8_tBuffer1[] = {0xaa,0xbb,0xcc,0xdd}; //無符號(hào)的8位整型數(shù)
voidUSART3_DMA1_Configuration(void)
{
......
DMA_InitStructure.DMA_PeripheralBaseAddr= USART3_DR_Addr; //外設(shè)首地
DMA_InitStructure.DMA_Memory0BaseAddr= (uint32_t)Buffer0; //內(nèi)存區(qū)首地址(1)
DMA_InitStructure.DMA_DIR= DMA_DIR_MemoryToPeripheral; //內(nèi)存->外設(shè)
DMA_InitStructure.DMA_BufferSize= 8; //*****傳輸數(shù)據(jù)個(gè)數(shù)為8 *****(2)
DMA_InitStructure.DMA_PeripheralInc= DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc= DMA_MemoryInc_Enable; //
DMA_InitStructure.DMA_PeripheralDataSize= DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize= DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode= DMA_Mode_Circular; //循環(huán)傳輸
……
DMA_DoubleBufferModeConfig(DMA1_Stream3,(uint32_t)Buffer1, DMA_Memory_1);//(3)
DMA_DoubleBufferModeCmd(DMA1_Stream3,ENABLE);//(4)enable double buffle
DMA_Init(DMA1_Stream3,&DMA_InitStructure);
DMA_Cmd(DMA1_Stream3,ENABLE); //使能 DMA1_Stream3通道
DMA_ClearITPendingBit(DMA1_Stream3,DMA_IT_TCIF3);
DMA_ITConfig(DMA1_Stream3,DMA_IT_TC, ENABLE);
}
&&&&&&&&&&&&&&&&&
發(fā)帖者述說,如果將藍(lán)色語句(3)的DMA_Memory_1改成DMA_Memory_0的話,就能正常打印出 11 22 33 44 aa bb cc dd,如果換成DMA_Memory_1的話,現(xiàn)象就不對(duì)了!輸出的結(jié)果卻是aa bb cc dd 15 00 08 52。請(qǐng)問是怎么回事?
顯然發(fā)帖者使用STM32F4系列芯片DMA的雙緩沖功能,應(yīng)該只是做做實(shí)驗(yàn)而已。他開辟了兩個(gè)長(zhǎng)度均為4字節(jié)的緩沖存儲(chǔ)區(qū)BUFFER0和BUFFER1。從基于ST固件庫(kù)函數(shù)代碼配置角度看,雙緩沖模式相比單緩沖模式,就是多了(3)(4)兩句,其它都一樣。這里我們特別留意下其中(1)(2)(3)句配置代碼。
綠色語句(1)配置了存儲(chǔ)區(qū)0指針指向的地址;
紅色代碼語句(2)處給出了DMA每輪的傳輸數(shù)據(jù)個(gè)數(shù)8;
藍(lán)色代碼語句(3)處配置存儲(chǔ)區(qū)1的地址和選擇第一個(gè)當(dāng)前存儲(chǔ)區(qū);
整體上看,該配置都配置了。結(jié)合我們上面的原理介紹,可以看出紅色代碼語句(2)配置每輪DMA傳輸個(gè)數(shù)為8有點(diǎn)問題,傳輸?shù)臄?shù)據(jù)寬度為BYTE,兩個(gè)緩沖區(qū)各自空間大小為4 BYTE。也就是說每傳輸4個(gè)BYTE數(shù)據(jù)就輪換存儲(chǔ)區(qū)重開下一輪傳輸,每輪DMA傳輸?shù)臄?shù)據(jù)個(gè)數(shù)應(yīng)該是4而不是8。
現(xiàn)在發(fā)帖者反饋的是調(diào)整語句(3)便會(huì)呈現(xiàn)不同的結(jié)果,當(dāng)把第(3)句的當(dāng)前存儲(chǔ)區(qū)改為Memory0時(shí)就會(huì)呈現(xiàn)貌似正確的結(jié)果。那是為什么呢?
其實(shí)這個(gè)貌似正確的結(jié)果是種巧合的假象。巧合的是在定義BUFFER0和BUFFER1時(shí),因?yàn)槎呔o鄰在一起定義,編譯器剛好把二者安排在連續(xù)的8個(gè)字節(jié)存儲(chǔ)單元。而發(fā)帖者又剛好將每輪DMA傳輸數(shù)據(jù)個(gè)數(shù)定義為8個(gè)緩沖單元,這意味著每傳輸8個(gè)緩沖單元數(shù)據(jù)才切換緩沖區(qū)。當(dāng)從Memory0即BUFFER0開始傳輸時(shí),連續(xù)的8個(gè)數(shù)據(jù)在第一輪就讀了出來,也就是說這8個(gè)數(shù)據(jù)并未經(jīng)過緩沖區(qū)的切換就讀出來了。而當(dāng)發(fā)帖者把第(3)句的第一次使用的當(dāng)前存儲(chǔ)區(qū)改為Memory1時(shí)就沒那么幸運(yùn)了。因?yàn)檫@次DMA從BUFFER1開始連續(xù)讀取8個(gè)數(shù)據(jù)單元,讀完BUFFER1內(nèi)的4個(gè)單元后,后面的4個(gè)緩存單元就是些不確定的數(shù)據(jù),自然一眼就看出結(jié)果不對(duì)了。
實(shí)際上,當(dāng)把上面紅色代碼語句(2)處的DMA傳輸數(shù)據(jù)個(gè)數(shù)調(diào)整為4時(shí)就結(jié)果正常了,至于第(3)句的起始當(dāng)前緩沖區(qū)的選擇無關(guān)緊要。
有人在使用DMA雙緩沖模式時(shí),經(jīng)常為這個(gè)傳輸個(gè)數(shù)糾結(jié),尤其從單緩沖模式轉(zhuǎn)為雙緩沖模式時(shí)。其實(shí),不管單緩沖還是雙緩沖模式,對(duì)于整體需要傳輸?shù)臄?shù)據(jù)個(gè)數(shù)是不會(huì)增減的,只是雙緩沖模式由之前的單緩沖模式變成雙緩沖循環(huán)。一般來講對(duì)于那些無需循環(huán)的小數(shù)量數(shù)據(jù)傳輸沒必要使用DMA雙緩沖模式。
相比單緩沖DMA傳輸,雙緩沖模式在設(shè)置DMA傳輸數(shù)據(jù)個(gè)數(shù)時(shí)應(yīng)更為靈活。比方之前單緩沖DMA傳輸時(shí),每輪傳輸數(shù)據(jù)個(gè)數(shù)假設(shè)為1024。當(dāng)改為雙緩沖循環(huán)模式時(shí),對(duì)應(yīng)每個(gè)緩沖區(qū)的DMA傳輸數(shù)據(jù)個(gè)數(shù)并不一定要設(shè)置為1024,可能設(shè)置50、100就能滿足要求,因?yàn)檫@里有兩個(gè)存儲(chǔ)區(qū)且是不停輪換的。不過,對(duì)于這個(gè)DMA傳輸數(shù)據(jù)個(gè)數(shù)的設(shè)置和使用要注意幾點(diǎn):
1.該數(shù)據(jù)不要太小,因?yàn)镈MA傳輸過程中往往伴隨DMA傳輸完成中斷,如果過小會(huì)導(dǎo)致中斷頻繁和切換頻繁,并非好事。
2.該數(shù)據(jù)也不必過大,上面也提過,一味加大緩沖容量對(duì)提升傳輸速度并無實(shí)質(zhì)改善。同時(shí)也得考慮芯片內(nèi)存容量的限制與合理使用。
3.盡管DMA雙緩沖模式基于循環(huán)傳輸,但實(shí)際應(yīng)用中DMA傳輸請(qǐng)求總有中止或停止的時(shí)候。比如,一副圖像數(shù)據(jù),完全可能不是剛好結(jié)束在事先設(shè)置的DMA傳輸數(shù)據(jù)個(gè)數(shù)的整數(shù)倍的位置點(diǎn)。那么,最后的這批緩沖數(shù)據(jù)因?yàn)槲礉M而不會(huì)發(fā)生緩沖交換請(qǐng)求或傳輸完成請(qǐng)求。此時(shí)如果不做適當(dāng)?shù)奶幚恚@批緩沖數(shù)據(jù)就可能被無意中丟棄掉。所以,我們?cè)诔绦蛑行枰O(shè)計(jì)些基于兩次緩沖切換的超時(shí)機(jī)制,及時(shí)收取最后一批緩沖區(qū)的數(shù)據(jù),以防因不能產(chǎn)生傳輸完成或緩沖切換事件而導(dǎo)致數(shù)據(jù)丟失的現(xiàn)象。
-
STM32
+關(guān)注
關(guān)注
2270文章
10895瀏覽量
355728 -
dma
+關(guān)注
關(guān)注
3文章
560瀏覽量
100544
原文標(biāo)題:一個(gè)關(guān)于STM32 DMA雙緩沖的話題
文章出處:【微信號(hào):stmcu832,微信公眾號(hào):茶話MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論