基於MCU的SD卡fat文件系統讀寫移植


背景

https://blog.csdn.net/huang20083200056/article/details/78508490

SD卡(Secure Digital Memory Card)具有體積小、容量大、數據傳輸快、可插拔、安全性好等優點,被廣泛應用於便攜式設備上。例如作為數碼相機的存儲卡,作為手機、平板多媒體擴展卡用的TF卡(micro sd)等等。

SD卡概述

SD卡技術是在MMC卡的基礎上發展起來的,其尺寸與MMC卡一樣,只是比MMC卡厚了0.7mm,因此SD主機可以識別並存取MMC卡。SD卡接口除了保留MMC卡的7針外,還在兩邊加了2針,作為數據線,目的是通過把傳輸方式由串行變成並行,以提高傳輸速率。此時的規范為SD1.0版本,最高容量只能到4GB。

為了跟進產品的更新換代,SD聯合協會在06年發布了容量更大、存儲更快的下一代SD卡規范SD2.0。該規范重新定義了SD卡的速度等級,分為三檔:Class 2、4、6,分別對應寫入速度2MB/S、4MB/S、6MB/S。根據卡容量又分為標准卡(小於2GB)和高容量卡(2GB~32GB),目前市面上應用的SD卡絕大部分都是SD2.0版本的卡。

為了讓儲存卡更加迷你,通過SD卡規范標准,又衍生了MiniSD卡和Micro SD卡,這些卡均比標准SD卡尺寸小,通過SD轉接套可以當作一般的SD卡使用。尤其是Micro SD卡,可以算是最小的存儲卡了,超小的體積可以極大的節省消費電子產品內部設計的空間,基本目前的Android手機均是選用Micro SD卡作為多媒體擴展儲存卡。隨着科技的進步,SD2.0規范SD卡也漸漸無法滿足應用的需求,在10年SD聯合協會又發布了新的SD3.0規范,該規范定義了sdxc和uhs,並增加了Class10,容量范圍為32GB~2TB。

MMC,SD,SDIO等之間的關系,如下圖所示。

MMC卡(MultiMediaCard): 是一種快閃存儲器卡標准。技術基於東芝的NAND閃存技術。比早期基於Inter NOR快閃技術的記憶卡(如CF卡)體積更小。

eMMC(Embedded MultiMediaCard):將NAND flash+主控IC封裝在一起的IC芯片,一般是BGA封裝。主要針對手機等產品的內嵌式存儲器標准規格。

SD卡(Secure Digital Memory Card):數據傳送和物理規范等在MMC的基礎上發展而來,強調安全,速度比2.11版的MMC卡更快。SDSC卡容量<=2GB,SDHC的為2GB32GB、**SDXC**的為32GB2TB。miniSD卡體積比SD卡小,而microSD卡則更小。

SDIO:SD卡接口的基礎上發展起來的外設接口,不止科技SD卡,還可以接藍牙、wifi、電視卡等。

TF卡(Trans-flash Card):2004年正式更名為Micro SD卡。

在sdxc卡仍需進一步坐等其價格下降的情況下,SD4.0規范已經開始在緊張的制訂中,這已超出本文的討論范圍內了。

SD卡驅動方式

SD卡共支持三種傳輸模式:SPI模式、1位SD模式、4位SD模式。所有的SD卡都必須支持較老的SPI/MMC模式,這個模式支持慢速的四線SPI接口,使很多微控制器都可以通過SPI或模擬SPI接口來讀寫SD卡。萬利的LPC5411x開發板通過SPI接口擴展了一個TF卡槽,可以用SPI接口讀寫TF卡。

SD2.0標准定義了物理層相關規范以及主機控制器規范,SD卡驅動的編寫必須參考這兩個規范,遵循標准的SD卡均可以采用統一的軟件驅動實現數據訪問。NXP對於其全系列的芯片提供了sdmmc庫中間件用於支持SD/MMC卡的讀寫,可以在官網下載相應的BSP,里面包含sdmmc庫,fsl_sdspi.h/fsl_sdspi.c即為SPI模式訪問SD卡的標准驅動,可以直接應用到LPC5411x開發環境中。SD卡驅動最主要實現三個接口,分別是SD卡的識別初始化、SD卡的塊讀、SD卡的塊寫,具體實現可以參考fsl_sdspi.h/fsl_sdspi.c驅動文件。

3. Fatfs

數據往往以文件的形式保存在儲存設備中,對於SD卡,一般采用的是Fat32文件系統,Fatfs由於其開源免費,支持Fat32,受到了廣泛的應用。

Fatfs是由日本工程師ChaN所編寫的Fat文件系統模塊,從06年發布第一個Fatfs版本開始,作者就從未停止維護和更新。Fatfs的編寫遵循ANSI C,並且完全與磁盤I/O層分開。它不依賴於硬件架構,代碼和工作區占用空間小,使之可以嵌入到各個低成本的微控制器中,如AVR、8051、PIC、ARM、Z80、68K等。由於SD卡一般使用Fat32文件系統,在使用到SD卡的系統中移植Fatfs,將很好地實現對SD卡文件的管理。

Fatfs模塊完全獨立於磁盤I/O層,因此底層磁盤I/O訪問並不屬於Fatfs的模塊部分,用戶必須自己實現這部分用來訪問存儲設備。通常在diskio.c中實現這幾個函數disk_initialize()disk_status()disk_read()disk_wirte()disk_ioctl()即可,如果使能了OS相關的特性,則還需額外實現進程/內存函數。其中disk_initialize()對應SD卡驅動中的卡識別初始化接口,disk_read()對應SD卡的塊讀接口,disk_wirte()對應SD卡的塊寫接口。NXP對於其全系列的芯片提供了Fatfs中間件的支持,Fatfs對應SD卡驅動接口的具體實現可以參考BSP中已移植好的Fatfs中間件。

4. 讀寫測試

移植好SD卡驅動以及Fatfs底層對應接口后,就可以用Fatfs應用編程接口讀寫SD卡里面的文件。應用以2KB大小為讀寫單位,測試讀寫10MB大小文件的平均讀寫速度。

uint8_t TestBuffer[2048];

int main() {

    uint32_t i;

    FATFS fs;

    FIL file;

    FRESULT Res;   

    uint32_t TimeCount;

    uint32_t ByteWrite, ByteRead;

     

    /* Board pin, clock, debug console init */

    /*attach 12 MHz clock to FLEXCOMM0 (debug console) */

    CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);

    /* enable clock for GPIO*/

    CLOCK_EnableClock(kCLOCK_Gpio0);
    CLOCK_EnableClock(kCLOCK_Gpio1);

     

    BOARD_InitPins();
    BOARD_BootClockFROHF96M();
    BOARD_InitDebugConsole();       

    Gpio_Init();
    

    f_mount(&fs, "4:" , 0);   

    /*

    Res = f_mkfs("", 0, 4096);

    if (Res != RES_OK) {

        PRINTF("f_mkfs error %d\r\n",Res);

        while(1);

    }

    */

    PRINTF("Writing test.bin, file sise10MB\r\n");

    Res= f_open(&file, "4:test.bin", FA_WRITE | FA_CREATE_ALWAYS);

    if (Res != RES_OK) {

        PRINTF("Createfile failed\r\n");

        while(1){

           GPIO_TogglePinsOutput(GPIO,0, 1u << 15);

           Delay_ms(300);        

        }

    }

    for (i=0; i<sizeof(TestBuffer); i++) {

        TestBuffer[i]= i;

    }

    TimeCount =timer_get_current_milliseconds();

    for (i=0;i<10*1024*1024/sizeof(TestBuffer); i++) {

        Res= f_write(&file, &TestBuffer, sizeof(TestBuffer), &ByteWrite);

        if(Res != RES_OK) {

           f_close(&file);

           PRINTF("Writefile error\r\n");

           while(1){

               GPIO_TogglePinsOutput(GPIO,0, 1u << 15);

               Delay_ms(300);

           }

        }

    }

    f_close(&file);

    PRINTF("Sd write speed %dKB/s\r\n", 10*1024*1024/(timer_get_current_milliseconds()-TimeCount));

       

    PRINTF("Reading test.bin, file sise10MB\r\n");

    Res = f_open(&file, "4:test.bin", FA_READ | FA_OPEN_EXISTING);

    if (Res != RES_OK) {

        PRINTF("Openfile failed\r\n");

        while(1){

           GPIO_TogglePinsOutput(GPIO,0, 1u << 15);

           Delay_ms(300);

        }

    }

    TimeCount = timer_get_current_milliseconds();

    for (i=0;i<10*1024*1024/sizeof(TestBuffer); i++) {

        Res= f_read(&file, (unsigned char *)&TestBuffer, sizeof(TestBuffer),&ByteRead);

        if(Res != RES_OK) {

           f_close(&file);

           PRINTF("Readfile error\r\n");

           while(1){

               GPIO_TogglePinsOutput(GPIO,0, 1u << 15);

               Delay_ms(300);
           }
        }
    }

    f_close(&file);

    PRINTF("Sd read speed %dKB/s\r\n", 10*1024*1024/(timer_get_current_milliseconds()-TimeCount));

    while(1) {

        GPIO_TogglePinsOutput(GPIO,0, 1u << 15);

        Delay_ms(1000);
    }

}

讀寫速度測試結果如下:

Writing test.bin, file size 10MB
Sd write speed 872 KB/S
Reading test.bin, file size 10MB
Sd read speed 1169 KB/S

SD卡寫速度為872 KB/S,讀速度為1169 KB/S,SD卡通過SPI接口讀寫,SPI時鍾采用FRO 12M時鍾,因此這個讀寫速度是合適的。SD卡讀寫速度跟卡速度等級、數據傳輸速率有關,讀寫多塊要比一塊一塊分多次讀寫快,此處測試一次性讀取8塊(512字節/塊),2048字節,讀寫速度主要受限於SPI的傳輸速率,LPC5411x的SPI接口最高支持48M的時鍾,SPI可以通過采用PLL時鍾、內部高速時鍾,進一步提高SPI的傳輸速率,從而進一步提高SD卡的讀寫速度。

附錄:例程

sd_card_driver.zip

MDK工程,包含SPI模式的SD驅動,Fatfs文件系統模塊,SD卡讀寫速度測試應用例程。

附錄:參考文檔


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM