打印
[ZLG-ARM]

曾经用过和正在用ZLG/FS的朋友请进来小憩

[复制链接]
2104|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
dsoyy|  楼主 | 2008-12-12 10:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在ZLG/FS下面我只想快速的读出SD里面的文件。

用卡块方式写进SD,再根据写的位置读出来还是比较快速的,但和实际用起来有悖;
但是ZLG/FS文件系统在读文件的时候接口函数只提供字节方式,这样速度很慢,我想修改成卡块方式,目前思路如下:
计算得到文件的扇区,把扇区转化成卡块位置,直接调用读卡块函数,并且用文件大小计算卡块数量。
我的思路应该可以实现吧。
1、
遇到问题如下:
ZLG/FS如此定义:
#ifndef DISK_CACHE_SIZE
#define DISK_CACHE_SIZE             512         //文件系统Cache大小(字节),应当是最大的扇区所占字节数
而在SD里面一个扇区包含128卡块,一个卡块512字节,而上面的宏定义  扇区大小就是卡块大小。注释说“最大扇区”,扇区不是统一大小的吗?

2、我已经根据文件名计算出文件所在逻辑盘的扇区,读扇区数据到cache(ReadSec(uint8 drive ,uint32 Index)),没看太懂的是这个函数读取的好像不是整个扇区数据,而是一个字节,是这样吗?如果是这样,我改成把逻辑盘数据到cache按照块(512)搬运速度就快了。

3、把cache中的数据读出来,目前是字节方式,我按照卡块就可以了。关键我难题是我如何获取已知文件的卡块位置?

请大家分析指教。

相关帖子

沙发
tedden| | 2008-12-12 10:37 | 只看该作者

这个我貌似修改过

你好,周工的这段代码我修改过,我是要写大量数据的时候直接写扇区,不通过cache。不当之处有很多,还请各位老鸟指点。
下面贴出我修改后的函数,我用过写数据应该没问题。
/*********************************************************************************************************
** 函数名称: FileWrite
** 功能描述: 写文件
**
** 输 入: Buf:要写的数据
**        Size:要写的字节数
**        Handle:文件句柄
** 输 出: 实际写的字节数
**         
** 全局变量: 无
** 调用模块: 无
**
** 作 者: 陈明计
** 日 期: 2003年6月5日
**-------------------------------------------------------------------------------------------------------
** 修改人: tedden
** 日 期: 2007年10月13日
**
** 修改说明: 以循环写字节的方式写文件速度很慢,尤其在写大量数据的时候该方案效率很低。
**           修改后采用直接写扇区的方式直接操作逻辑盘,以加快数据传输速度。
**                
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
        uint32 FileWrite(void *Buf, uint32 Size, HANDLE Handle)
{

/********************************************************************************************************
************************************ removed by HMF *****************************************************
************************************ remove  start  *****************************************************
    uint8 *temp;
    uint32 i;
    
    temp = (uint8 *)Buf;
    for (i = 0; i < Size; i++)
    {
        if (FilePutCh(*temp, Handle) != RETURN_OK)
        {
            break;
        }
        temp++;
    }
    return i;
************************************ remove   end    ****************************************************/

/*********************************************************************************************************
************************************ Added by tedden ********************************************************
************************************ add start    *******************************************************/
unsigned int         i, j, SecIndex,buf_point,Offset_temp,new_clus;
//unsigned short       NextClusSecIndex, NextClusByteIndex;
Disk_RW_Parameter    Pa;
MY_FILE            * fp;
Disk_Info          * DiskInfo;
unsigned char        Rt;       
unsigned char      * temp;

    temp = (unsigned char *)Buf;                
    Rt = PARAMETER_ERR;
    fp = FileInfo + Handle;                          /* 获取打开文件列表描述符 */
    if (Handle >= 0 && Handle < MAX_OPEN_FILES)      /* Handle是否有效 */
    
    if (((fp->Flags) & FILE_FLAGS_WRITE) != 0)       /* 对应的打开文件信息表是否已使用,条件成立文件可写 */
    {
        Rt = FILE_EOF;
        if (fp->Offset <= fp->FileSize)              /* 文件指针指在文件内部 */
        {
            Rt = NOT_FIND_DISK;
                
            DiskInfo = GetDiskInfo(fp->Drive);       /* 获取文件所在逻辑盘信息 */
            
            if (DiskInfo != NULL)                    /* 逻辑盘存在 */         
            {
                
                /* 调整文件指针 */
                j = (fp->Offset) % (DiskInfo->SecPerClus * DiskInfo->BytsPerSec);     
                /* 偏移量j=描述符内偏移量%(每簇扇区数×每扇区字节数) */
                if (j == 0)          /* 余数为0,说明偏移在簇的末尾 */  
                
                {
                    if (fp->Offset < fp->FileSize)    /* 偏移在文件内 */
                    {
                        fp->Clus = FATGetNextClus(fp->Drive, fp->Clus);  /* 获取下一个簇 */
                    }
                    else            /* 偏移在文件尾,这个时候要添加一个新簇 */
                    {
                        i = FATAddClus(fp->Drive, fp->Clus);    /* 申请添加新的簇 */
                        if (i >= BAD_CLUS)                      /* 磁盘空间满,申请失败 */
                        {
                            return DISK_FULL;
                        }
                        fp->Clus = i;                          /* 修改文件描述符的簇指针 */
                        if (fp->FstClus == EMPTY_CLUS)         /* 如果是新建的文件,初始化文件的起始簇 */ 
                        {
                            fp->FstClus = i;
                        }
                    }
                }
                
                /* 计算数据所在扇区,j在前面已经和簇取余 */
                i = j / DiskInfo->BytsPerSec;      /* 数据所在的扇区 */
                j = j % DiskInfo->BytsPerSec;      /* 数据在扇区的字节序号 */
                SecIndex = (fp->Clus - 2) * DiskInfo->SecPerClus + DiskInfo->DataStartSec + i;
                
                Rt = SECTOR_READ_ERR;
                buf_point = 0;         /* 要写入数据的指针初始化 */
                
                /* 从下面开始调用底层驱动读写数据 */
                /* 初始化好底层驱动使用的结构体 */
                Pa.Drive = fp->Drive;
                   Pa.SectorIndex = SecIndex;
                Pa.RsvdForLow = DiskInfo->RsvdForLow;
                Pa.Buf = CacheBuf;
                
                if (DiskInfo->DiakCommand != NULL)
                {
                    while(1)  /* 等待直到所有的数据写完 */
                    {

                        if (DiskInfo->DiakCommand(DISK_READ_SECTOR, &Pa) != DISK_READ_OK)     /* 扇区读取失败,直接返回 */
                        {
                            return Rt;
                        }
                        Offset_temp = fp->Offset;  /* 记录偏移 */
                        /* 读取成功,下面开始修改缓冲区的数据 */
                        while(j < DISK_CACHE_SIZE )       /* 从j开始修改扇区数据 */
                        {
                            fp->Offset++ ;   /* 修该偏移指针 */
                            CacheBuf[j] = *temp;
                            temp++;
                            j++;            
                            buf_point++ ;
                            if( buf_point == Size)   /* 所有数据都已写入,跳出循环 */
                                break;
                        }
                        /* 修改完成,将修改好的数据写回 */
                        if (DiskInfo->DiakCommand(DISK_WRITE_SECTOR, &Pa) != DISK_WRITE_OK)     /* 扇区写入失败,直接返回 */
                        {
                            fp->Offset = Offset_temp;   /* 写入失败,写回偏移 */
                            return Rt;
                        }
                        if (fp->Offset > fp->FileSize)
                        {
                            fp->FileSize = fp->Offset;         /* 修改文件大小 */
                        }
                        j = 0;                          /* 缓冲指针归0 */
                        
                        /* 判断是否写完 */
                        if( buf_point == Size)    /* 已经写完 */
                        {
                            Rt = RETURN_OK;
                            break;
                        }
                        else                        /* 没有写完,判断是否需要申请新的簇 */
                        {
                            if(fp->Offset < fp->FileSize)     /* 偏移还没有到文件尾 */
                            {
                                if((fp->Offset) % (DiskInfo->SecPerClus * DiskInfo->BytsPerSec) != 0)    /* 当前簇还没有写完 */
                                {
                                    i++;
                                    SecIndex++;
                                    Pa.SectorIndex = SecIndex;  /* 修改索引 */
                                }
                                else                             /* 当前簇已经写满 */
                                {
                                    fp->Clus = FATGetNextClus(fp->Drive, fp->Clus); /* 获取下一个簇 */
                                    i = 0;              /* 第一个扇区 */
                                    SecIndex = (fp->Clus - 2) * DiskInfo->SecPerClus + DiskInfo->DataStartSec + i;  /* 重新计算索引 */
                                    Pa.SectorIndex = SecIndex;    /* 修改结构体参数 */
                                }
                            }
                            else                              /* 偏移到达文件尾 */
                            {
                                if((fp->Offset) % (DiskInfo->SecPerClus * DiskInfo->BytsPerSec) != 0)    /* 当前簇还没有写完 */
                                {
                                    i++;
                                    SecIndex++;
                                    Pa.SectorIndex = SecIndex;  /* 修改索引 */
                                }
                                else                             /* 当前簇已经写满,要申请新的簇 */
                                {
                                    new_clus = FATAddClus(fp->Drive, fp->Clus);
                                    if(new_clus >= BAD_CLUS)  /* 获取新簇失败 */
                                    {
                                        Rt = DISK_FULL;
                                        return Rt;
                                    }
                                    fp->Clus = new_clus;
                                    i = 0;              /* 第一个扇区 */
                                    SecIndex = (fp->Clus - 2) * DiskInfo->SecPerClus + DiskInfo->DataStartSec + i;  /* 重新计算索引 */
                                    Pa.SectorIndex = SecIndex;    /* 修改结构体参数 */
                                }
                            }
                        }
                    }
                }      
            }
        }
    }
    return buf_point;

/************************************ add end      *******************************************************/
}

使用特权

评论回复
板凳
dsoyy|  楼主 | 2008-12-12 11:01 | 只看该作者

感谢楼上

请问你修改后速率是多少了?

使用特权

评论回复
地板
dsoyy|  楼主 | 2009-6-2 09:54 | 只看该作者

建议加精

使用特权

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

本版积分规则

144

主题

566

帖子

3

粉丝