zoukankan      html  css  js  c++  java
  • 基于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的为2GB~32GB、SDXC的为32GB~2TB。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
    ",Res);
    
            while(1);
    
        }
    
        */
    
        PRINTF("Writing test.bin, file sise10MB
    ");
    
        Res= f_open(&file, "4:test.bin", FA_WRITE | FA_CREATE_ALWAYS);
    
        if (Res != RES_OK) {
    
            PRINTF("Createfile failed
    ");
    
            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
    ");
    
               while(1){
    
                   GPIO_TogglePinsOutput(GPIO,0, 1u << 15);
    
                   Delay_ms(300);
    
               }
    
            }
    
        }
    
        f_close(&file);
    
        PRINTF("Sd write speed %dKB/s
    ", 10*1024*1024/(timer_get_current_milliseconds()-TimeCount));
    
           
    
        PRINTF("Reading test.bin, file sise10MB
    ");
    
        Res = f_open(&file, "4:test.bin", FA_READ | FA_OPEN_EXISTING);
    
        if (Res != RES_OK) {
    
            PRINTF("Openfile failed
    ");
    
            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
    ");
    
               while(1){
    
                   GPIO_TogglePinsOutput(GPIO,0, 1u << 15);
    
                   Delay_ms(300);
               }
            }
        }
    
        f_close(&file);
    
        PRINTF("Sd read speed %dKB/s
    ", 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卡读写速度测试应用例程。

    附录:参考文档

  • 相关阅读:
    C#线程类Thread初步
    无限级分类存储过程版
    C#多线程编程实例实战
    数据库里阻塞和死锁情况 看那里死锁的存储过程
    预防按钮的多次点击 恶意刷新
    .net2.0文件压缩/解压缩
    HttpHandler和HttpModule入门
    反射,枚举,绑定下拉框
    在C#里关于定时器类
    判断上传的图片文件格式是否合法不是用后缀做的判断
  • 原文地址:https://www.cnblogs.com/schips/p/12556875.html
Copyright © 2011-2022 走看看