问题提出:
测试MP3过程中,发现用小容量(32M)的的SD卡能正常工作,换上一个2G的SD卡,测试时发现无**常播放。哈哈,朋友开玩笑说,穷苦人家吃上一顿大鱼大肉还会消化不良的,肯定是虫子在里面作怪。
问题分析:
根据故障现象,可以断定软件的基本流程是可行了,小容量与大容量的区别就在于某些变量的取值的不一样,于是查找软件定义的全局变量是否符合规范。打开FAT文档对照全局变量进行检查
//文件系统用全局变量
UINT32 BootSector; /* 逻辑盘的起始绝对扇区号LBA */
UINT8 SecPerClus; /* 逻辑盘的每簇扇区数 */
UINT8 RsvdSecCnt; /* 逻辑盘的保留扇区数 */
UINT16 FATSz16; /* FAT16逻辑盘的FAT表占用的扇区数 */
UINT32 FATStartSecotr; /*FAT表起始扇区号*/
UINT32 BootDirStart; //根目录的起始扇区号
UINT32 DiskDataStart; /*存放数据的起始扇区号*/
还真找到了一个变量定义的不符合规范,立马仿真调试跟踪,发现高兴得太早,这个BUG不是致命BUG,是个良性的BUG。
变量检查完了,开始查找功能函数,从前往后扫了一遍。发现如下函数
/* 将簇号转换为绝对LBA扇区地址 */
UINT32 mClusterToLba( UINT16 iCluster )
{
return( DiskDataStart + (( iCluster - 2 ) * SecPerClus ); /* 将簇号转换为LBA,得当前操作的起始LBA */
}
根据过去的经验,数据类型转换是个危险地带,此函数表面上看似乎能用,但是是短整型数X字节再加长整型数,最后的结果是长整形数。十有**就是在这儿碰上地雷了。
问题解决:
采用如下写法,编译链接下载后,插2G的卡验证是否能正常使用
/* 将簇号转换为绝对LBA扇区地址 */
UINT32 mClusterToLba( UINT16 iCluster )
{
return( DiskDataStart + ((UINT32)( iCluster - 2 )) * SecPerClus ); /* 将簇号转换为LBA,得当前操作的起始LBA */
}
一切正常,哈哈,穷苦人吃鱼的确得小心,鱼刺有时不容易发现的。
小结:
此类BUG的根本原因是Keil c51开发系统中短整型数(UINT16)相乘时不会自动转换成长整型。所以要先进行类型转换,也可以在数值后面加L来指时,以前在使用AT45DB161D进行地址计算时也出过错。此次软件因为是从其它地方找来改的,所以存在BUG也是很正常的,但利用过去的经验很快就排雷成功。
所以大家在写软件时,遇到此类运算,务必提前作好强制类型转换的声明,就能避免犯错。 |