|
很久沒有寫公眾號了,一方面忙,另一方面也不知道寫些什么內(nèi)容,大家如果有想了解的(前提是我也懂),可以后臺發(fā)送給我。
今天主要來測試一下SPI讀寫SD卡的速度。SD卡是一個嵌入式中非常常用的外設(shè),可以用于存儲一些大容量的數(shù)據(jù)。但用單片機讀寫SD卡速度一般都有限(對于高速SD卡,主要是受限于單片機本身的接口速度),在高速、實時數(shù)據(jù)存儲時可能會有影響。但具體速度可以達到多少呢,今天就來實際測試一下。
SD卡一般有兩種常用的接口SPI和SDIO,SDIO又有1線和4線之分。很多單片機沒有SDIO接口,但SPI接口就比較常用,今天主要來測試一下SPI接口讀寫SD卡的速度,主要是寫入速度。
測試條件:單片機:STM32L433CCT6編譯環(huán)境:MDK 5.30+HAL庫SD卡:32Gbit SDNAND,型號:米客方德MKDV32GCL-STH文件系統(tǒng):FatFS R0.12c 1.單純SPI接口測試(非DMA)
我們知道,像SD卡之類的Flash存儲器,一般都是按扇區(qū)擦除整塊數(shù)據(jù)。因此每次寫入字節(jié)數(shù)是扇區(qū)整數(shù)倍時,效率會比較高。同時,每次寫入數(shù)據(jù)時,都需要先發(fā)送一些SD卡的指令,所以單次寫入數(shù)據(jù)量越大,平均速度也就越快。了解了這些,我們就知道如何進行測試了。
首先,SD卡底層驅(qū)動使用的是HAL庫函數(shù),單字節(jié)讀寫,沒有任何改動和優(yōu)化:
uint8_t SPI_ReadWriteByte(uint8_t TxData){ uint8_t RxData = 0;HAL_SPI_TransmitReceive(&hspi3,&TxData,&RxData,1,100); return RxData;}
接下來,我們先確定SPI和時鐘頻率多少合適,經(jīng)過測試,發(fā)現(xiàn)20MHz的時鐘頻率比較合適,10MHz時讀寫速度會降低,再高的時鐘頻率對速度的提升也很小。因此我們這里用20MHz的時鐘。
然后我們分別測試單次寫入4KB、8KB、16KB時的速度為多少,測試結(jié)果如下:
rqtu1ngpqsx64014212404.png (44.87 KB, 下載次數(shù): 0)
下載附件
保存到相冊
rqtu1ngpqsx64014212404.png
2024-9-18 10:34 上傳
可以看到,單次寫入數(shù)據(jù)量越大,平均速度就越快。當單次寫入數(shù)據(jù)達到32KB時,速度提升不明顯。而且一般單片機內(nèi)部RAM緩存也有限,單次寫入16KB是一個比較合適的選擇。
看到這個不到100KB/S速度,我還是有的不敢相信的,畢竟20MHz的時鐘,理論上速度可以達到2MB/S左右,考慮到一些文件系統(tǒng)等協(xié)議的消耗,能到1/3差不多,那也得600多KB,現(xiàn)在的速度差距有點大。
當然,這個使用的HAL庫函數(shù)有關(guān),HAL_SPI_TransmitReceive函數(shù)效率比較低,內(nèi)部做了大量的判斷等操作,而且單字節(jié)傳輸也嚴重影響效率。如果自己優(yōu)化一下,相信效率會有很大的提升。有興趣的小伙伴可以試試。我們這次其實主要是測試SPI+DMA的速度,所以就不在這里糾結(jié)了。
2.SPI+DMA接口測試
DMA可以在外設(shè)和內(nèi)存之間搬運數(shù)據(jù),而不需要CPU的參與。其優(yōu)勢在于大量數(shù)據(jù)傳輸時,比如SD卡讀寫、SPI接口的液晶屏刷屏等。如果只是讀寫幾個字節(jié)的數(shù)據(jù),比如一些SPI接口的AD、DA等,DMA的優(yōu)勢就不明顯。
因為SPI接口的設(shè)備一般都不是純數(shù)據(jù)傳輸,都要配合一些指令等。所以即使使用DMA,也是要等待DMA傳輸完成再進行其它操作。當然這期間CPU可以通過中斷方式去處理一些其它事情。
SPI+DMA寫數(shù)據(jù)函數(shù)如下,使用的也是HAL庫,沒有進行優(yōu)化。
int8_t SD_WriteBuffer_DMA(const uint8_t *TxData, uint16_t Size){ uint32_t i = 0; // 循環(huán)變量
SPI3_DMA_Flag = 0; SPI_TransmitReceive_DMA(&HSPI_TF, (uint8_t*)TxData, txrxdata, Size);
/* 等待DMA傳輸完成 */ while (1) { if(SPI3_DMA_Flag == 1) break; i++; if (i > 0xFFFFFF) { return 1; /* 超時退出 */ } } return 0;}
以向SD卡寫數(shù)據(jù)為例,需要改為DMA的地方有2處:寫命令和寫扇區(qū)數(shù)據(jù),因為這兩處發(fā)送的字節(jié)數(shù)比較多。一些SD卡的起始、結(jié)束、應(yīng)答等單字節(jié)的數(shù)據(jù)傳輸使用的還是非DMA方式傳輸。下面是部分程序:
nbpsnxy3mjl64014212504.png (205.78 KB, 下載次數(shù): 0)
下載附件
保存到相冊
nbpsnxy3mjl64014212504.png
2024-9-18 10:34 上傳
我們進行了兩種測試:只使能DMA寫扇區(qū)數(shù)據(jù),以及使能DMA寫扇區(qū)數(shù)據(jù)和發(fā)送指令。都是按照單次寫入16KB進行測試,測試結(jié)果如下:
q0ikvvfd1kx64014212604.png (71.38 KB, 下載次數(shù): 0)
下載附件
保存到相冊
q0ikvvfd1kx64014212604.png
2024-9-18 10:34 上傳
可以看到,速度提升非常明顯。數(shù)據(jù)和指令都用DMA傳輸時,速度最快。如果再進行一些底層函數(shù)的優(yōu)化,速度還會有提升。
最后我們對讀取速度也進行了測試,使用DMA方式,使能DMA讀扇區(qū)數(shù)據(jù)和發(fā)送指令,測試結(jié)果如下,讀取速度可以達到1.1MB~1.2MB/S。
bsujd5diwbf64014212704.png (44.37 KB, 下載次數(shù): 0)
下載附件
保存到相冊
bsujd5diwbf64014212704.png
2024-9-18 10:34 上傳
3.總結(jié)
SPI+DMA的方式讀寫SD卡速度優(yōu)勢明顯,推薦使用。當然,這跟非DMA方式的底層函數(shù)效率低下有很大的關(guān)系。
但DMA的另一個更重要的優(yōu)勢在于,讀寫數(shù)據(jù)時可以大部分釋放CPU資源。比如我之前的一個應(yīng)用,需要以1KHz的頻率在外部中斷中去讀取一些數(shù)據(jù),每次大約需要幾十uS。如果使用非DMA方式,頻繁的中斷,且?guī)资畊S時間也不短,會導致SD卡寫入出錯。而使用DMA方式則不會有這個問題。
最后,附上底層驅(qū)動程序:鏈接:https://pan.baidu.com/s/1RnMCw5EAm_xMjT-UkUKoMA?pwd=98sb提取碼:98sb
推薦閱讀:STM32CubeMX系列教程
單片機通過WIFI模塊(ESP8266)獲取網(wǎng)絡(luò)時間與天氣預(yù)報
串口接收不定長數(shù)據(jù)的幾種方法
不會寫B(tài)ootloader?看這里,現(xiàn)成的!
UART波特率對時鐘精度的要求有多高?
Keil調(diào)試時設(shè)置斷點的高級用法
歡迎關(guān)注公眾號"嵌入式技術(shù)開發(fā)",大家可以后臺給我留言溝通交流。如果覺得該公眾號對你有所幫助,也歡迎推薦分享給其他人。 |
|