打印
[STM32]

振南ZN-X开发板【STM32M3版】模块实验之 SD卡DMA高性能驱动方式

[复制链接]
2031|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
znmcu|  楼主 | 2014-10-10 13:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 znmcu 于 2014-10-10 14:16 编辑

振南网站还在继续美化改进,暂时提供一个平台来发布振南的实验和相关资料!
http://www.znmcu.cn/znx_m3_exp_sd_dma_speed_test.html
振南QQ:987582714  群:198521880
SD卡物理扇区读写硬件SPI与高性能(SPI+DMA)方式
两种驱动方式速度性能比较【STM32 M3版】
实验说明:
SD卡物理扇区读写实验》中我们使用了两种SPI接口方式,即IO模拟SPI方式与硬件SPI方式,随后我们又对它们的速度性能差异进行了比较与评估。但是它们的扇区读写速度仍然不够理想。借助于STM32内置的DMA控制器,我们可以实现高性能的SD卡物理扇区驱动【关于高性能SD卡驱动,请详见《振南znFAT》一书下册第11章《性能提升,底层突破--高性能SD卡物理驱动》】。
此实验将对高性能SD卡驱动与前面实现的使用硬件SPI方式的SD卡驱动进行速度和性能上的比较。
所需硬件:
此实验中需要的硬件有:
ZN-X开发板基板(STM32 M3)【也可使用自己的开发板,需要将SD卡模块与开发板通过导线相连,还需要在IO上加10K上拉电阻】
ARM-OBJLINK仿真器(用于仿真与程序下载)
USB转串口模块(用于串口通信与程序下载)
SD卡读写模块与SD
【注:此实验中使用的是SD2接口SD1连接的STM32IO,没有硬件SPI功能,因此SD1只能使用IO模拟SPI方式。】
电路原理图及详解:
同《SD卡物理扇区读写实验》。
实验方法与流程:
主要代码如下:读写SD卡的连续10000个扇区,同时使用定时器记录所花费的时间,最终分别计算得到它们的数据读写速度。
unsigned char pbuf[512]; //数据缓冲区
extern unsigned int counter;

int main(void)
{         
int i=0,res=0,cnt=0;
u32 tt_sec=0;
delay_init();
uart_init(9600);                 //串口初始化为9600
printf("串口设置完毕\r\n");
SD2_IOSPI_Init();
TIM3_Int_Init(10000,7200);
while(SD2_Init())
{
cnt++;
printf("SD卡2初始化已尝试%d次\r\n",cnt);
if(cnt>=3) printf("振南ZN-X开发板SD卡2初始化失败\r\n");while(1);
  }
printf("振南ZN-X开发板SD卡2初始化成功\r\n");
tt_sec = SD2_GetTotalSec();
printf("SD卡2总扇区:%d\r\n",tt_sec);
printf("SD卡2总容量(MB):%d\r\n",tt_sec>>11);

for(i=0;i<512;i++) pbuf=i;

printf("开始计时....\r\n");
counter=0;
TIM_Cmd(TIM3, ENABLE);
for(i=0;i<10000;i++)
{
SD2_Write_Sector(1000+i,pbuf);
}
TIM_Cmd(TIM3, DISABLE);
printf("停止计时....\r\n");
printf("SD卡2写扇区完成,共花费%d秒\r\n",counter);
printf("扇区数据写速度约为%dKBps\r\n",5120/counter);

printf("开始计时....\r\n");
  counter=0;
TIM_Cmd(TIM3, ENABLE);
for(i=0;i<10000;i++)
{
SD2_Read_Sector(1000+i,pbuf);
}
TIM_Cmd(TIM3, DISABLE);
printf("停止计时....\r\n");
printf("SD卡2读扇区完成,共花费%d秒\r\n",counter);
printf("扇区数据读速度约为%dKBps\r\n",5120/counter);

while(1);            
}  
实验结果如下图所示:
图中左边是硬件SPI方式,右边是高性能驱动(硬件SPI+DMA方式),显然右边比左边速率要高得多。
《振南znFAT》之《高性能SD卡驱动(DMA方式)》内容节选:
DMA为数据传输提速:
SD卡驱动效率不高的根本原因就在于数据传输上。请看下图,大家是否能够领会其中含意。
有人可能会说:“为什么会产生非连续的问题?这个所谓的‘间隔’是如何产生的?程序里每次调用SPI读写函数的时候并没有加延时啊。”这个间隔实际上来自于CPU本身。函数的调用、代码的执行、变量的访存等操作都会耗费时间。可以说,在CPU控制SPI接口进行大量数据的收发时,它所作的其实就是一种纯粹的数据搬移。CPU在作这种工作的时候效率是比较低的。请看下图所示。
如果我们能够将这些“间隔”去掉,那就可以实现“连续数据传输”了。但只要有CPU的存在,就势必会产生这个“间隔”,这似乎是一对矛盾。所以我们引入了DMA(直接内存存取),它可以在几乎不需要CPU干预的情况下,完成内存与内存、内存与外设接口之间的直接数据传输。如果把CPU作数据搬移比喻成满是沟壑的乡间小路的话,那么DMA俨然就是平坦的高速公路,甚至是城际特快。因为DMA数据传输基本上是纯粹的硬件行为,它的效率只取决于内存的访问速度、外设接口的通信速度以及硬件时钟频率。DMA的工作流程大体是这样的,如下图所示。
但是DMA是依赖于硬件的,如果我们所使用的CPU芯片没有DMA控制器的话,那自然也就无法实现DMA数据传输功能了。振南的ZN-X开发板上的STM32芯片是支持DMA的,而且它所集成的DMA控制器还远比我们想像得要强大。它有7个完全独立的DMA通道,这就如同在内存与内存或者内存与外设之间同时架起了7座跨海大桥,而且还能同时高速运行。所以振南认为,DMA机制在提高计算机系统的整体性能与数据吞吐量方面功不可没。其实它在现代计算机体系结构中也一直扮演着绝对重要的角色。

高性能SD卡驱动的实现
既然DMA的性能如此优越,那我们就把它融入到SD卡的驱动中,用它来代替冗长而低效的数据搬移过程。至于DMA的具体代码,其实与上面大同小异,只不过要把目的地址修改为SPI收发器的数据寄存器地址,再对数据传输方向、数据量以及自增方式等参数进行设置即可。我原以为STM32DMA使用起来是简单而随意的:任何一个DMA通道都可以完成内存与外设接口之间的双向数据传输。导致我花费了大量的时间和精力来与之纠缠。后来我才知道并非如此,在内存与外设接口之间进行DMA传输时,每一个DMA通道都有其特定的传输对象与方向。比如只有通道5才能用于内存到SPI2DMA传输,即数据的发送;反之则必须使用通道4,即接收来自SPI2的数据(此文中使用STM32芯片的SPI2SD卡进行驱动)。
【注:完整内容请详见正版图书】

源代码下载:




相关帖子

沙发
卢台长| | 2014-10-10 18:18 | 只看该作者
前排站位,好东西,学习了。

使用特权

评论回复
板凳
旭日东起| | 2014-10-11 09:58 | 只看该作者
关注一下,南哥的东西还是不错的

使用特权

评论回复
地板
jxw82284134| | 2014-10-11 12:43 | 只看该作者
来学习一下

使用特权

评论回复
5
hwl1023| | 2014-10-14 07:30 | 只看该作者
支持南哥!

使用特权

评论回复
6
凤凰息梧桐123| | 2014-10-14 08:52 | 只看该作者
支持一下

使用特权

评论回复
7
18806541688| | 2015-7-3 11:22 | 只看该作者
速度提升好大,读速度 从341KB/s提升到1280KB/s,好诱惑。
有个产品也有SPI驱动SD卡,看帖后我也加了DMA,感觉速度并没有提升明显。(没有实际通过串口测试)
也许是我们的应用一次读的扇区太少(最大不超过12扇区)

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:振南的znFAT -- 单片机上上的FAT32文件系统 www.znmcu.cn

4474

主题

5195

帖子

33

粉丝