提高SD读写速度的若干建议

目前市面上面买的SD卡(也叫TF卡)大多都是高速Class 10,它的体积很小,内部包括了一个主控mcu和Nand Flash,主机侧(Host,SD controller)通过发送cmd的方式对SD卡进行控制,并通过数据线(DAT0~DAT3)和SD卡进行数据的读写交互。对于SD卡的初始化、读写驱动,网络上已经有大量的资料,SD Spec里也有很清楚的阐述。本篇博文主要是从软件驱动的角度,探讨如何提高SD卡的读写速度。


1 SD Spec里定义了SD模式和SPI模式,SPI的读和写分别只有一根线,毫无疑问,如果支持SD模式的话,尽量使用SD 4线模式,在时钟相同的情况下,它的传输速度是1线模式的4倍。
2 尽量使用DMA完成数据从Ram和SPI/SDMMC controller的FIFO直接的双向通信,解放CPU的同时,DMA的传输速度往往也较快
3 提高时钟频率。提高DMA的时钟可以加快从Ram到SD host的FIFO的速度;提高SD clk,则可以加快给SD卡传输的速度,使用SD模式时,一般都建议将SD CLK设置到50MHz,这是SD卡高速模式下所支持的最高频率,此时理论上最高传输速度为25MB/s
4 前面提到,目前市面上能买到的SD卡基本上都是支持高速模式的卡,所以软件驱动在初始化卡完成后(初始化期间时钟频率最大为400K,数据来自SD Spec 6.8节。在初始阶段,如果时钟快的话会很容易失败),应该使用cmd6将sd卡切换到高速模式,让card端可以支持25M以上的SD clk。
5 读写SD数据都有单个扇区和连续多个扇区两种模式,cmd 17/18是读,cmd 24/25是写,在大多数情况下,多个扇区读写的平均速度都会比单个扇区要快。在调试一个新的硬件平台时,建议将多个block的速度都测试一下,找到一个最快的平衡点,例如可能读的时候,一次读32个block的平均速度最快,而在写的时候,可能一次写16个block的平均速度最快。
6 前面提到,尽量使用DMA,而使用DMA就会带了一个问题是cache一致性,一般的方法是写SD之前先flush一下要写的区域,而读的时候需要invalidate一下要读的区域,这里建议要尽量避免使用cache操作函数,尤其是flush的函数,它会cache里已存的相关地址区域里的数据以cache line为单位,一条一条的送到数据总线上,再发送到ram里,往往非常耗时。正确的方法应该是使用uncache内存方式进行DMA传输目的或者源地址。
7 SD Spec的4.3节里定义了一个ACMD23,它是用于多个block写的时候进行预擦除,即pre-erase命令,据说可以加快写的速度。Spec里的原话是:It is recommended using this command preceding CMD25,some of the cards will be faster for Multiple Write Block operation。楼主对这个cmd使用多张卡做过测试,并没有看出来对于写的速度能有什么改善,或许我手上的几张卡都不符合some of the cards?如果有高手知道其中的原因,欢迎指点一下。
8 写SD卡时,往往都是以文件的形式,这涉及到文件系统的内容。如果要写的数据文件大小是可以提前预知的,在创建文件时,建议将文件的大小和所占用的扇区设置好,类似于迅雷下载那样的方法,在写的时候可以直接对其扇区操作,bypass掉文件系统里大量弯弯绕绕的逻辑代码。
9 如果要写的扇区和数据大小都是可以预知的,可使用cmd32/33/38将需要写的扇区预先擦除,card端收到cmd38后,会把DAT0拉低,进入programing状态,直到完成擦除动作才会重新将DAT0放开。需要注意的是,不要一次擦除大片的区域,那样可能会等待很长时间,会达到秒级。如果要检测擦除是否生效,可以使用winhex软件查看被擦除的扇区,被擦除后的数据内容可能为1和0,取决于SD卡的SCR寄存器的DATA_STAT_AFTER_ERASE (bit 55)

你可能感兴趣的:(Linux驱动,嵌入式杂谈)