電子產(chǎn)業(yè)一站式賦能平臺

PCB聯(lián)盟網(wǎng)

搜索
查看: 24|回復: 0
收起左側(cè)

SPI方式讀寫SD卡速度有多快?

[復制鏈接]

451

主題

451

帖子

2461

積分

三級會員

Rank: 3Rank: 3

積分
2461
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2023-3-10 11:50:00 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
很久沒有寫公眾號了,一方面忙,另一方面也不知道寫些什么內(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é)果如下:         

    可以看到,單次寫入數(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方式傳輸。下面是部分程序:

    我們進行了兩種測試:只使能DMA寫扇區(qū)數(shù)據(jù),以及使能DMA寫扇區(qū)數(shù)據(jù)和發(fā)送指令。都是按照單次寫入16KB進行測試,測試結(jié)果如下:

    可以看到,速度提升非常明顯。數(shù)據(jù)和指令都用DMA傳輸時,速度最快。如果再進行一些底層函數(shù)的優(yōu)化,速度還會有提升。
    最后我們對讀取速度也進行了測試,使用DMA方式,使能DMA讀扇區(qū)數(shù)據(jù)和發(fā)送指令,測試結(jié)果如下,讀取速度可以達到1.1MB~1.2MB/S。

    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ā)",大家可以后臺給我留言溝通交流。如果覺得該公眾號對你有所幫助,也歡迎推薦分享給其他人。
  • 回復

    使用道具 舉報

    發(fā)表回復

    您需要登錄后才可以回帖 登錄 | 立即注冊

    本版積分規(guī)則

    關(guān)閉

    站長推薦上一條 /1 下一條


    聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表