首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

FatFs源码剖析(3)

FatFs源码剖析(3)

http://www.openedv.com/posts/list/27427.htm
  •     //计算根目录起始扇区、数据起始扇区(物理扇区地址)
  •     fatend = fs->sects_fat * fs->n_fats + fs->fatbase;
  •     if (fat == FS_FAT32) {
  •         fs->dirbase = LD_DWORD(&(fs->win[0x2C])); /* Directory start cluster */
  •         fs->database = fatend;                       /* Data start sector (physical) */
  •     } else {
  •         fs->dirbase = fatend;                        /* Directory start sector (physical) */
  •         fs->database = fs->n_rootdir / 16 + fatend;   /* Data start sector (physical) */
  •     }
  •     //最大簇号
  •     fs->max_clust =                              /* Maximum cluster number */
  •         (LD_DWORD(&(fs->win[0x20])) - fs->database + sect) / fs->sects_clust + 2;
  •     return FR_OK;
  • }
  • /*-----------------------*/
  • /* Open or Create a File */
  • FRESULT f_open (
  •     FIL *fp,            /* ointer to the buffer of new file object to create */
  •     const char *path,   /* ointer to the file path */
  •     BYTE mode           /* Access mode and file open mode flags */
  • )
  • {
  •     FRESULT res;
  •     BYTE *dir;
  •     DIR dirscan;
  •     char fn[8+3+1];         //8.3 DOS文件名
  •     FATFS *fs = FatFs;
  •     /*首先初始化SD卡,检测文件系统类型,初始化FATFS对象*/
  •     if ((res = check_mounted()) != FR_OK) return res;
  • #ifndef _FS_READONLY
  •     //如果磁盘设置为写保护,则返回错误码:FR_WRITE_PROTECTED
  •     if ((mode & (FA_WRITE|FA_CREATE_ALWAYS)) && (disk_status() & STA_PROTECT))
  •         return FR_WRITE_PROTECTED;
  • #endif
  •     //根据用户提供的文件路径path,将文件名对应的目录项及其整个扇区读取到win[]中,
  •     //并填充目录项dirscan、标准格式的文件名fn,以及目录项在win[]中的字节偏移量dir
  •     res = trace_path(&dirscan, fn, path, &dir); /* Trace the file path */
  • #ifndef _FS_READONLY
  •     /* Create or Open a File */
  •     if (mode & (FA_CREATE_ALWAYS|FA_OPEN_ALWAYS)) {
  •         DWORD dw;
  •         //如果文件不存在,则强制新建文件
  •         if (res != FR_OK) {     /* No file, create new */
  •             mode |= FA_CREATE_ALWAYS;
  •             if (res != FR_NO_FILE) return res;
  •             dir = reserve_direntry(&dirscan);   /* Reserve a directory entry */
  •             if (dir == NULL) return FR_DENIED;
  •             memcpy(dir, fn, 8+3);       /* Initialize the new entry */
  •             *(dir+12) = fn[11];
  •             memset(dir+13, 0, 32-13);
  •         }
  •         else {              /* File already exists */
  •             if ((dir == NULL) || (*(dir+11) & (AM_RDO|AM_DIR))) /* Could not overwrite (R/O or DIR) */
  •                 return FR_DENIED;
  •             //如果文件存在,但又以FA_CREATE_ALWAYS方式打开文件,则重写文件
  •             if (mode & FA_CREATE_ALWAYS) {  /* Resize it to zero */
  •                 dw = fs->winsect;            /* Remove the cluster chain */
  •                 if (!remove_chain(((DWORD)LD_WORD(dir+20) << 16) | LD_WORD(dir+26))
  •                     || !move_window(dw) )
  •                     return FR_RW_ERROR;
  •                 ST_WORD(dir+20, 0); ST_WORD(dir+26, 0); /* cluster = 0 */
  •                 ST_DWORD(dir+28, 0);                    /* size = 0 */
  •             }
  •         }
  •         //如果是强制新建文件操作,则还需更新时间和日期
  •         if (mode & FA_CREATE_ALWAYS) {
  •             *(dir+11) = AM_ARC;
  •             dw = get_fattime();
  •             ST_DWORD(dir+14, dw);   /* Created time */
  •             ST_DWORD(dir+22, dw);   /* Updated time */
  •             fs->dirtyflag = 1;
  •         }
  •     }
  •     /* Open a File */
  •     else {
  • #endif
  •         if (res != FR_OK) return res;       /* Trace failed */
  •         //如果打开的是一个目录文件,则返回错误码:FR_NO_FILE
  •         if ((dir == NULL) || (*(dir+11) & AM_DIR))  /* It is a directory */
  •             return FR_NO_FILE;
  • #ifndef _FS_READONLY
  •         //如果以FA_WRITE方式打开Read-Only属性的文件,则返回错误码:FR_DENIED
  •         if ((mode & FA_WRITE) && (*(dir+11) & AM_RDO)) /* R/O violation */
  •             return FR_DENIED;
  •     }
  • #endif
  •     //填充FIL文件结构体参数
  • #ifdef _FS_READONLY
  •     fp->flag = mode & (FA_UNBUFFERED|FA_READ);
  • #else
  •     fp->flag = mode & (FA_UNBUFFERED|FA_WRITE|FA_READ);
  •     fp->dir_sect = fs->winsect;               /* ointer to the directory entry */
  •     fp->dir_ptr = dir;
  • #endif
  •     fp->org_clust =  ((DWORD)LD_WORD(dir+20) << 16) | LD_WORD(dir+26); /* File start cluster */
  •     fp->fsize = LD_DWORD(dir+28);        /* File size */
  •     fp->fptr = 0;                        /* File ptr */
  •     //这一步很重要,它将直接导致f_read和f_write操作中的逻辑顺序
  •     fp->sect_clust = 1;                  /* Sector counter */
  •     fs->files++;
  •     return FR_OK;
  • }
继承事业,薪火相传
很好的代码分享,感谢楼主分享
返回列表