最近在开发一个类似数码像框类的东西,不过需要播放mp3.在开发mp3模块的时候出现了不少问题,特此记录.
首先说明下大致的思路.os使用了uc/os-II(v2.52),如果要量产,还要考虑换到免费的liunx.芯片使用了
arm7核的LPC2210,mp3模块使用了VS1003,存储模块使用了sd卡.之所以不用一些集成了图象与mp3解码
的芯片,是因为想在该次开发中多用到一些东西,多练下手,如果最后要出货,为了成本考虑,可能还是要大改.
调整好sd卡模块后,经过1个星期左右的努力,正玄测试mp3模块终于能够发出声音了,迫不及待的把sd卡部分合进来,编译,通过,调试,然后发现没有声音.
调试了近1天,才发现是自己的spi初始化程序与vs1003的reset顺序反了.因为我的sd卡与vs1003模块
使用了同一个spi接口,sd卡的读写是一个任务,vs1003的操作是另外一个任务,spi的初始化是放在sd卡任务中的
vs1003的reset是放在自己的任务中.
修改后,顺利的播放出了音乐.此时,问题也就来了,播放192kbs的mp3时候还算顺畅,但是播放320kbps的时候
极其的卡,根本无法听.
原因主要是sd 卡的读写速度以及vs1003的通信速度跟不上,所以系统需要优化.
1.首先,把vs1003的spi口与sd卡的spi口分开.LPC2210正好有2个spi口.这一步很关键,不然后面的优化
手段无从说起.
该项改动花了1天半的时间,测试后发现情况差不多,并没有好转,这也在意料之中.
2.提高spi的通信速度,也就是尽量提高spi接口的sck,提高了最大极限.这个和vs1003和LPC2210都有关系,
该项优化并不是主要的手段,提升效果也有限.但是至少要保证速度慢不是这里的问题.我现在的spi的通信
速度都在6Mhz以上.
3.buff的调整,该项优化是重头戏.开始使用了一种双buff的手段,是在网络上看来的,也就是2块buffer,
一块被用在vs1003通信的时候,另一块就可以用在sd卡读了.vs1003数据发送完了,直接取另一块来发送,不用
读好一块发一块,有一种并行的思想在里面.
但是,如果想要这样的效果,必须在vs1003的发送过程中有空闲的时间并切换到sd任务上去读取.vs1003发送的
过程中唯一可能有空闲的时候是DREQ为低的时候.所以必须保证在DREQ为低不能发送数据的时候有任务切换.
这里的手段很多,用中断,或则uc/os中的OSTimeDlyHMSM,OSTimeDly都行.
需要特别注意的是OSTimeDlyHMSM函数,如果你的时间片是一秒200次,那使用OSTimeDlyHMSM等待一毫秒是
没有用的,因为等待的最小单位就是1000/200=5ms了.
对一个320kbps的mp3来说,0.5k的数据可以支持0.5/(320/8)=1/80=12.5ms,所以等待1个tick是可以的.
所以,根据这些分析的结果对程序进行了修改,每块buff都取4k,正好是fat32的一个簇大小.sd卡与
vs1003发送两个任务使用邮箱通信.
该项修改花了近半天的时间,结果失败,呵呵.不过效果好点了,卡的不是那么厉害了.
4.这时,注意力转向了sd卡的读写速度.如果文件系统使用的是zlg/fs,那么速度会非常慢.
主要是开放出来的zlg/fs是学习版的,高速版的是要卖钱的.不想买就只有自己动手.
我在这里主要增加了一个一次读取多块的函数,最大可以到一次读取一个簇.这样速度都有几十
K每秒了.速度虽然还是不好,不过对付下现在的问题也该够了.
5.第二次的buff调整.仔细考虑后,发现要提高现有的速度,buff的设计并不合理,vs1003的发送与
sd卡的读写最好相互完全独立,不需要相互通信.这里可以借鉴tcp/ip协议里的数据报文.
所以,这次我把buff设计为1k左右,把数量提高到8个(这里的大小和数量最好要设计为可以调节的,
方便在数量和大小之间找到平衡点).并记录每个buff的读取序号,不然发送的时候不知道先发哪个了.
该种方法获得很大的成功,在1k大小,4个buff的时候,320kbps的播放已经非常流畅.
6.虽然已经可以播放320kbps的mp3,但是心里还是很悬,因为整个系统要做的事情除了mp3播放,还有很多
事情要做.所以系统还需要优化.
下面的方向就是spi中断的使用.在spi通信中,没有使用中断,而是使用了一个循环等待
发送完毕,每一个byte的发送和接收,有5到7us的时间被浪费了,如果能使用中断的话,
配合数量够多的buff,整体速度会有很大的提高(但是单次读取的速度说不定更慢了).
该项优化还没有完全实现.
首先说明下大致的思路.os使用了uc/os-II(v2.52),如果要量产,还要考虑换到免费的liunx.芯片使用了
arm7核的LPC2210,mp3模块使用了VS1003,存储模块使用了sd卡.之所以不用一些集成了图象与mp3解码
的芯片,是因为想在该次开发中多用到一些东西,多练下手,如果最后要出货,为了成本考虑,可能还是要大改.
调整好sd卡模块后,经过1个星期左右的努力,正玄测试mp3模块终于能够发出声音了,迫不及待的把sd卡部分合进来,编译,通过,调试,然后发现没有声音.
调试了近1天,才发现是自己的spi初始化程序与vs1003的reset顺序反了.因为我的sd卡与vs1003模块
使用了同一个spi接口,sd卡的读写是一个任务,vs1003的操作是另外一个任务,spi的初始化是放在sd卡任务中的
vs1003的reset是放在自己的任务中.
修改后,顺利的播放出了音乐.此时,问题也就来了,播放192kbs的mp3时候还算顺畅,但是播放320kbps的时候
极其的卡,根本无法听.
原因主要是sd 卡的读写速度以及vs1003的通信速度跟不上,所以系统需要优化.
1.首先,把vs1003的spi口与sd卡的spi口分开.LPC2210正好有2个spi口.这一步很关键,不然后面的优化
手段无从说起.
该项改动花了1天半的时间,测试后发现情况差不多,并没有好转,这也在意料之中.
2.提高spi的通信速度,也就是尽量提高spi接口的sck,提高了最大极限.这个和vs1003和LPC2210都有关系,
该项优化并不是主要的手段,提升效果也有限.但是至少要保证速度慢不是这里的问题.我现在的spi的通信
速度都在6Mhz以上.
3.buff的调整,该项优化是重头戏.开始使用了一种双buff的手段,是在网络上看来的,也就是2块buffer,
一块被用在vs1003通信的时候,另一块就可以用在sd卡读了.vs1003数据发送完了,直接取另一块来发送,不用
读好一块发一块,有一种并行的思想在里面.
但是,如果想要这样的效果,必须在vs1003的发送过程中有空闲的时间并切换到sd任务上去读取.vs1003发送的
过程中唯一可能有空闲的时候是DREQ为低的时候.所以必须保证在DREQ为低不能发送数据的时候有任务切换.
这里的手段很多,用中断,或则uc/os中的OSTimeDlyHMSM,OSTimeDly都行.
需要特别注意的是OSTimeDlyHMSM函数,如果你的时间片是一秒200次,那使用OSTimeDlyHMSM等待一毫秒是
没有用的,因为等待的最小单位就是1000/200=5ms了.
对一个320kbps的mp3来说,0.5k的数据可以支持0.5/(320/8)=1/80=12.5ms,所以等待1个tick是可以的.
所以,根据这些分析的结果对程序进行了修改,每块buff都取4k,正好是fat32的一个簇大小.sd卡与
vs1003发送两个任务使用邮箱通信.
该项修改花了近半天的时间,结果失败,呵呵.不过效果好点了,卡的不是那么厉害了.
4.这时,注意力转向了sd卡的读写速度.如果文件系统使用的是zlg/fs,那么速度会非常慢.
主要是开放出来的zlg/fs是学习版的,高速版的是要卖钱的.不想买就只有自己动手.
我在这里主要增加了一个一次读取多块的函数,最大可以到一次读取一个簇.这样速度都有几十
K每秒了.速度虽然还是不好,不过对付下现在的问题也该够了.
5.第二次的buff调整.仔细考虑后,发现要提高现有的速度,buff的设计并不合理,vs1003的发送与
sd卡的读写最好相互完全独立,不需要相互通信.这里可以借鉴tcp/ip协议里的数据报文.
所以,这次我把buff设计为1k左右,把数量提高到8个(这里的大小和数量最好要设计为可以调节的,
方便在数量和大小之间找到平衡点).并记录每个buff的读取序号,不然发送的时候不知道先发哪个了.
该种方法获得很大的成功,在1k大小,4个buff的时候,320kbps的播放已经非常流畅.
6.虽然已经可以播放320kbps的mp3,但是心里还是很悬,因为整个系统要做的事情除了mp3播放,还有很多
事情要做.所以系统还需要优化.
下面的方向就是spi中断的使用.在spi通信中,没有使用中断,而是使用了一个循环等待
发送完毕,每一个byte的发送和接收,有5到7us的时间被浪费了,如果能使用中断的话,
配合数量够多的buff,整体速度会有很大的提高(但是单次读取的速度说不定更慢了).
该项优化还没有完全实现.