stm32—FatFs移植spi_flash(报错FR_NO_FILESYSTEM)
发布时间:2020-12-15 17:35:47 所属栏目:百科 来源:网络整理
导读:? ? ? ? SD卡的FatFs文件系统已经满大街了,可以参考的资源也有很多。 ? ? ? ? 移植FatFs文件系统主要内容在于“diskio.c”,“ffconf.h”,一个是用于定义底层接口,一个用于定义FatFs配置,百度或者google都能找得到说明,就不详细说明了。 ? ? ? ? 碰到的
? ? ? ? SD卡的FatFs文件系统已经满大街了,可以参考的资源也有很多。 ? ? ? ? 移植FatFs文件系统主要内容在于“diskio.c”,“ffconf.h”,一个是用于定义底层接口,一个用于定义FatFs配置,百度或者google都能找得到说明,就不详细说明了。 ? ? ? ? 碰到的主要问题就是f_mkfs()函数过后,Fat系统没有刷新成功,于是f_open()返回(FR_NO_FLESYSTEM),文件系统没有刷新成功。 ? ? ? ? 开始查ff.c文件 ,进入f_mkfs: FRESULT f_mkfs ( BYTE drv,/* Logical drive number */ BYTE sfd,/* Partitioning rule 0:FDISK,1:SFD */ UINT au /* Allocation unit size [bytes] */ ) { static const WORD vst[] = { 1024,512,256,128,64,32,16,8,4,2,0}; static const WORD cst[] = {32768,16384,8192,4096,2048,1024,512}; BYTE fmt,md,sys,*tbl,pdrv,part; DWORD n_clst,vs,n,wsect; UINT i; DWORD b_vol,b_fat,b_dir,b_data; /* LBA */ DWORD n_vol,n_rsv,n_fat,n_dir; /* Size */ FATFS *fs; DSTATUS stat; /* Check mounted drive and clear work area */ if (drv >= _VOLUMES) return FR_INVALID_DRIVE; if (sfd > 1) return FR_INVALID_PARAMETER; if (au & (au - 1)) return FR_INVALID_PARAMETER; fs = FatFs[drv]; if (!fs) return FR_NOT_ENABLED; fs->fs_type = 0; pdrv = LD2PD(drv); /* Physical drive */ part = LD2PT(drv); /* Partition (0:auto detect,1-4:get from partition table)*/ /* Get disk statics */ stat = disk_initialize(pdrv); if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; #if _MAX_SS != 512 /* Get disk sector size */ if (disk_ioctl(pdrv,GET_SECTOR_SIZE,&SS(fs)) != RES_OK || SS(fs) > _MAX_SS) return FR_DISK_ERR; #endif if (_MULTI_PARTITION && part) { /* Get partition information from partition table in the MBR */ if (disk_read(pdrv,fs->win,1) != RES_OK) return FR_DISK_ERR; if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; if (!tbl[4]) return FR_MKFS_ABORTED; /* No partition? */ b_vol = LD_DWORD(tbl+8); /* Volume start sector */ n_vol = LD_DWORD(tbl+12); /* Volume size */ } else { /* Create a partition in this function */ if (disk_ioctl(pdrv,GET_SECTOR_COUNT,&n_vol) != RES_OK || n_vol < 128) return FR_DISK_ERR; b_vol = (sfd) ? 0 : 63; /* Volume start sector */ n_vol -= b_vol; /* Volume size */ } if (!au) { /* AU auto selection */ vs = n_vol / (2000 / (SS(fs) / 512)); for (i = 0; vs < vst[i]; i++) ; au = cst[i]; } au /= SS(fs); /* Number of sectors per cluster */ if (au == 0) au = 1; if (au > 128) au = 128; /* Pre-compute number of clusters and FAT sub-type */ n_clst = n_vol / au; fmt = FS_FAT12; if (n_clst >= MIN_FAT16) fmt = FS_FAT16; if (n_clst >= MIN_FAT32) fmt = FS_FAT32; /* Determine offset and size of FAT structure */ if (fmt == FS_FAT32) { n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs); n_rsv = 32; n_dir = 0; } else { n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4; n_fat = (n_fat + SS(fs) - 1) / SS(fs); n_rsv = 1; n_dir = (DWORD)N_ROOTDIR * SZ_DIR / SS(fs); } b_fat = b_vol + n_rsv; /* FAT area start sector */ b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */ b_data = b_dir + n_dir; /* Data area start sector */ if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED; /* Too small volume */ /* Align data start sector to erase block boundary (for flash memory media) */ if (disk_ioctl(pdrv,GET_BLOCK_SIZE,&n) != RES_OK || !n || n > 32768) n = 1; n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */ n = (n - b_data) / N_FATS; if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */ n_rsv += n; b_fat += n; } else { /* FAT12/16: Expand FAT size */ n_fat += n; } /* Determine number of clusters and final check of validity of the FAT sub-type */ n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au; if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16) || (fmt == FS_FAT32 && n_clst < MIN_FAT32)) return FR_MKFS_ABORTED; switch (fmt) { /* Determine system ID for partition table */ case FS_FAT12: sys = 0x01; break; case FS_FAT16: sys = (n_vol < 0x10000) ? 0x04 : 0x06; break; default: sys = 0x0C; } if (_MULTI_PARTITION && part) { /* Update system ID in the partition table */ tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; tbl[4] = sys; if (disk_write(pdrv,1) != RES_OK) return FR_DISK_ERR; md = 0xF8; } else { if (sfd) { /* No partition table (SFD) */ md = 0xF0; } else { /* Create partition table (FDISK) */ mem_set(fs->win,SS(fs)); tbl = fs->win+MBR_Table; /* Create partition table for single partition in the drive */ tbl[1] = 1; /* Partition start head */ tbl[2] = 1; /* Partition start sector */ tbl[3] = 0; /* Partition start cylinder */ tbl[4] = sys; /* System type */ tbl[5] = 254; /* Partition end head */ n = (b_vol + n_vol) / 63 / 255; tbl[6] = (BYTE)((n >> 2) | 63); /* Partition end sector */ tbl[7] = (BYTE)n; /* End cylinder */ ST_DWORD(tbl+8,63); /* Partition start in LBA */ ST_DWORD(tbl+12,n_vol); /* Partition size in LBA */ ST_WORD(fs->win+BS_55AA,0xAA55); /* MBR signature */ if (disk_write(pdrv,1) != RES_OK) /* Write it to the MBR sector */ return FR_DISK_ERR; md = 0xF8; } } /* Create BPB in the VBR */ tbl = fs->win; /* Clear sector */ mem_set(tbl,SS(fs)); mem_cpy(tbl,"xEBxFEx90" "MSDOS5.0",11);/* Boot jump code,OEM name */ i = SS(fs); /* Sector size */ ST_WORD(tbl+BPB_BytsPerSec,i); tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */ ST_WORD(tbl+BPB_RsvdSecCnt,n_rsv); /* Reserved sectors */ tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */ i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR; /* Number of rootdir entries */ ST_WORD(tbl+BPB_RootEntCnt,i); if (n_vol < 0x10000) { /* Number of total sectors */ ST_WORD(tbl+BPB_TotSec16,n_vol); } else { ST_DWORD(tbl+BPB_TotSec32,n_vol); } tbl[BPB_Media] = md; /* Media descriptor */ ST_WORD(tbl+BPB_SecPerTrk,63); /* Number of sectors per track */ ST_WORD(tbl+BPB_NumHeads,255); /* Number of heads */ ST_DWORD(tbl+BPB_HiddSec,b_vol); /* Hidden sectors */ n = get_fattime(); /* Use current time as VSN */ if (fmt == FS_FAT32) { ST_DWORD(tbl+BS_VolID32,n); /* VSN */ ST_DWORD(tbl+BPB_FATSz32,n_fat); /* Number of sectors per FAT */ ST_DWORD(tbl+BPB_RootClus,2); /* Root directory start cluster (2) */ ST_WORD(tbl+BPB_FSInfo,1); /* FSInfo record offset (VBR+1) */ ST_WORD(tbl+BPB_BkBootSec,6); /* Backup boot record offset (VBR+6) */ tbl[BS_DrvNum32] = 0x80; /* Drive number */ tbl[BS_BootSig32] = 0x29; /* Extended boot signature */ mem_cpy(tbl+BS_VolLab32,"NO NAME " "FAT32 ",19); /* Volume label,FAT signature */ } else { ST_DWORD(tbl+BS_VolID,n); /* VSN */ ST_WORD(tbl+BPB_FATSz16,n_fat); /* Number of sectors per FAT */ tbl[BS_DrvNum] = 0x80; /* Drive number */ tbl[BS_BootSig] = 0x29; /* Extended boot signature */ mem_cpy(tbl+BS_VolLab,"NO NAME " "FAT ",FAT signature */ } ST_WORD(tbl+BS_55AA,0xAA55); /* Signature (Offset is fixed here regardless of sector size) */ if (disk_write(pdrv,tbl,b_vol,1) != RES_OK) /* Write it to the VBR sector */ return FR_DISK_ERR; if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR+6) */ disk_write(pdrv,b_vol + 6,1); /* Initialize FAT area */ wsect = b_fat; for (i = 0; i < N_FATS; i++) { /* Initialize each FAT copy */ mem_set(tbl,SS(fs)); /* 1st sector of the FAT */ n = md; /* Media descriptor byte */ if (fmt != FS_FAT32) { n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00; ST_DWORD(tbl+0,n); /* Reserve cluster #0-1 (FAT12/16) */ } else { n |= 0xFFFFFF00; ST_DWORD(tbl+0,n); /* Reserve cluster #0-1 (FAT32) */ ST_DWORD(tbl+4,0xFFFFFFFF); ST_DWORD(tbl+8,0x0FFFFFFF); /* Reserve cluster #2 for root dir */ } if (disk_write(pdrv,wsect++,1) != RES_OK) return FR_DISK_ERR; mem_set(tbl,SS(fs)); /* Fill following FAT entries with zero */ for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */ if (disk_write(pdrv,1) != RES_OK) return FR_DISK_ERR; } } /* Initialize root directory */ i = (fmt == FS_FAT32) ? au : n_dir; do { if (disk_write(pdrv,1) != RES_OK) return FR_DISK_ERR; } while (--i); #if _USE_ERASE /* Erase data area if needed */ { DWORD eb[2]; eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1; disk_ioctl(pdrv,CTRL_ERASE_SECTOR,eb); } #endif /* Create FSInfo if needed */ if (fmt == FS_FAT32) { ST_DWORD(tbl+FSI_LeadSig,0x41615252); ST_DWORD(tbl+FSI_StrucSig,0x61417272); ST_DWORD(tbl+FSI_Free_Count,n_clst - 1); /* Number of free clusters */ ST_DWORD(tbl+FSI_Nxt_Free,2); /* Last allocated cluster# */ ST_WORD(tbl+BS_55AA,0xAA55); disk_write(pdrv,b_vol + 1,1); /* Write original (VBR+1) */ disk_write(pdrv,b_vol + 7,1); /* Write backup (VBR+7) */ } return (disk_ioctl(pdrv,CTRL_SYNC,0) == RES_OK) ? FR_OK : FR_DISK_ERR; }在线仿真,发现函数在disk_write处存在问题,于是开始改写该底层函数 /************************************************************************************** * 名 ? ?称: disk_write * 功 ? ?能: Write Sector(s) ? * 参 ? ?数: drv:表示需要读扇区的磁盘对象 *<span style="white-space:pre"> </span> BYTE drv: Physical drive nmuber (0..)? *<span style="white-space:pre"> </span> BYTE *buff: Data buffer to store read data? *<span style="white-space:pre"> </span> DWORD sector: Sector address (LBA)? *<span style="white-space:pre"> </span> ? BYTE count: Number of sectors to read (1..128)? * 调用方式:disk_initialize(0,buff,1); * 返 回 值:<span style="white-space:pre"> </span>状态标识0:表示成功 ***************************************************************************************/ void flash_page_write_si(uint32_t sector,uint8_t *data) { <span style="white-space:pre"> </span>uint16_t i;<span style="white-space:pre"> </span> ? SPI_FLASH_WriteEnable(); ? /* Select the FLASH: Chip Select low */ ? SPI_FLASH_CS_LOW(); ? /* Send "Write to Memory " instruction */ ? SPI_FLASH_SendByte(0x02); ? /* Send WriteAddr high nibble address byte to write to */ ? SPI_FLASH_SendByte((sector & 0xFF0000) >> 16); ? /* Send WriteAddr medium nibble address byte to write to */ ? SPI_FLASH_SendByte((sector & 0xFF00) >> 8); ? /* Send WriteAddr low nibble address byte to write to */ ? SPI_FLASH_SendByte(sector & 0xFF); <span style="white-space:pre"> </span>for (i = 0; i < FLASH_SECTOR_SIZE; i++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>SPI_FLASH_SendByte(*data++); <span style="white-space:pre"> </span>} ? SPI_FLASH_CS_HIGH(); ? /* Wait the end of Flash writing */ ? SPI_FLASH_WaitForWriteEnd(); } DSTATUS disk_write (BYTE drv,const BYTE *buff,<span style="white-space:pre"> </span>DWORD sector,<span style="white-space:pre"> </span>BYTE count) { <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>flash_page_write_si(sector,(uint8_t *)buff); <span style="white-space:pre"> </span>return RES_OK; } disk_write改写完成,是对内存块进行写操作。这样子flash的初始化应该算是完成了。再次烧录程序,报错相同。 进入f_open函数,发现错误返回在chk_mounted(),进入该函数,发现check_fs()才是罪魁祸首, fmt = check_fs(fs,bsect = 0); /* Load sector 0 and check if it is an FAT-VBR (in SFD) */ if (LD2PT(vol) && !fmt) fmt = 1; /* Force non-SFD if the volume is forced partition */ if (fmt == 1) { /* Not an FAT-VBR,the physical drive can be partitioned */ /* Check the partition listed in the partition table */ pi = LD2PT(vol); if (pi) pi--; tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */ if (tbl[4]) { /* Is the partition existing? */ bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */ fmt = check_fs(fs,bsect); /* Check the partition */ } } if (fmt == 3) return FR_DISK_ERR; if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */研究了很久,还是找不到问题所在,于是请教了一个大神,说可能是flash大小问题,我使用的是2M大小,大神说fat系统的管理所占用的内存就非常大,要不就自己做小个小型的文件系统来实现这个功能。好吧,受教了。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |