STM32F103RC,FATFS,w25x16移植笔记
来源:互联网 发布:ubuntu 移动宽带 编辑:程序博客网 时间:2024/06/06 00:25
这些天移植了FatFS文件系统到STM32F103RC板上,使用STM32的SPI_FLASH库,出现了一些问题现在记录下来。
接下来说一下移植的过程:
移植的最新版本为FatFS 0.12版本版本中主要包含以下几个文件:diskio.c diskio.h ff.c ff.h ffconf.h integer.h。
其中,ff相关的文件为FatFS的核心文件系统文件,diskio相关的文件为文件系统与底层硬件交互的接口文件,ffconf.h是用来配置文件系统配置的一些参数,integer.h是对不同平台变量类型的定义。
1.修改ffconf.h
_FS_READONLY //文件系统只读_FS_MINIMIZE //移除一些函数,定义最小文件系统_USE_STRFUNC //允许使用一些字符串函数_USE_FIND //开启一些查询函数_USE_MKFS //f_mkfs,可以格式化Flash_USE_FASTSEEK //开启一些快速定位函数_USE_EXPAND //开启一些扩展函数_USE_CHMOD //开启权限相关的函数_USE_LABEL //开启卷标相关函数_USE_FORWARD //开启使用数据流而不用缓冲区_CODE_PAGE //代码页格式_USE_LFN //开启长文件名模式_MAX_LFN //设置最长文件名长度_LFN_UNICODE //设置长文件名编码格式_STRF_ENCODE //长命名文件中字符串编码格式_FS_RPATH //支持目录更改_VOLUMES //支持硬盘个数_STR_VOLUME_ID //允许字符串模式的ID_VOLUME_STRS //字符串模式的具体字符串_MULTI_PARTITION //允许新建多个分区_MIN_SS //所支持最小的扇区大小_MAX_SS //所支持最大的扇区大小_USE_TRIM //支持空闲区域回收_FS_NOFSINFO //支持查询文件系统信息_FS_TINY //支持微型文件系统_FS_EXFAT //支持扩展性文件系统_FS_NORTC //支持不使用RTC的文件系统_NORTC_MON //不使用RTC时的月份_NORTC_MDAY //不使用RTC时的日_NORTC_YEAR //不使用RTC时的年_FS_LOCK //支持文件上锁功能_FS_REENTRANT //支持文件重入,多线程访问_FS_TIMEOUT //重入模式下超时周期我的设置如下:#define _USE_MKFS 1#define _CODE_PAGE 936#define _VOLUMES 1#define _MIN_SS 512#define _MAX_SS 512其余均为0或默认值
2.diskio.c
disk_initialize 增加SPI_FLASH_Init()以及SPI_FLASH_ReadID()函数进行SPI_FLASH的初始化操作
DSTATUS disk_initialize ( BYTE pdrv /* Physical drive nmuber to identify the drive */){ DSTATUS stat; u32 FlashID; switch (pdrv) { case SPI_FLASH : SPI_FLASH_Init(); FlashID = SPI_FLASH_ReadID(); stat = 0; return stat; } return STA_NOINIT;}
disk_read 增加SPI_FLASH_BufferRead,该函数是从指定地址读取指定字节数。
DRESULT disk_read ( BYTE pdrv, /* Physical drive nmuber to identify the drive */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector address in LBA */ UINT count /* Number of sectors to read */){ DRESULT res; switch (pdrv) { case SPI_FLASH : SPI_FLASH_BufferRead(buff,sector * SPI_FLASH_SECTOR,count * SPI_FLASH_SECTOR); res = RES_OK; return res; } return RES_PARERR;}
disk_write 增加相对应的Flash写入函数,Flash在写入的时候需要先擦除后写入。使用的Flash芯片为w25x16的16MB Flash芯片,此芯片的最小擦除单位为4k字节的一个扇区,因此在写入的时候,不考虑增加缓存的情况下即及时写入时,需要先将所写入的区域部分所占的扇区数据读取出来,并将对应的扇区擦除,然后将写入的区域与刚刚读取数据的区域合并后,再次写入对应的几个扇区中。
DRESULT disk_write ( BYTE pdrv, /* Physical drive nmuber to identify the drive */ const BYTE *buff, /* Data to be written */ DWORD sector, /* Sector address in LBA */ UINT count /* Number of sectors to write */){ DRESULT res; UINT i = 0; UINT SectorWriteTotal = 0; //写入数据总共占用的扇区个数 UINT SectorWriteLeft = 0; //写入数据占用剩余不到一个扇区的字节个数 UINT SectorPhyLocation = 0; //芯片上物理扇区的标号 u32 AddrStart = sector * SPI_FLASH_SECTOR; //写入数据的起始地址 UINT WriteLeftBytes = count * SPI_FLASH_SECTOR; //写入数据的剩余字节个数 UINT CurrenSectorLeft = 0; //当前扇区未被占用的剩余字节个数 UINT SectorPhyLocationAddr = 0; //芯片上物理扇区的地址 switch (pdrv) { case SPI_FLASH : SectorWriteTotal = count * SPI_FLASH_SECTOR / PHY_SECTOR_SIZE; //计算当前需要写入的数据量需要多少个扇区 向下取证 SectorWriteLeft = count * SPI_FLASH_SECTOR % PHY_SECTOR_SIZE; //计算不足一个扇区的字节个数 if(SectorWriteLeft > 0) //若存在不足一个扇区的数据,则需要多写入一个扇区 SectorWriteTotal += 1; SectorPhyLocation = sector * SPI_FLASH_SECTOR / PHY_SECTOR_SIZE; //计算写入数据的起始位置对应到芯片上的第几个扇区 for(i = 0; i < SectorWriteTotal;i++) { SectorPhyLocationAddr = (SectorPhyLocation + i) * PHY_SECTOR_SIZE; //下一个要操作的扇区物理地址 SPI_FLASH_BufferRead(EraseBuff,SectorPhyLocationAddr,PHY_SECTOR_SIZE); //把当前扇区的所有内容读出来放入缓冲区 SPI_FLASH_SectorErase(SectorPhyLocationAddr); //将当前扇区的内容擦除 CurrenSectorLeft = PHY_SECTOR_SIZE; //重置当前扇区剩余的字节个数为整个扇区的大小 if(AddrStart != SectorPhyLocationAddr) //判断若要写入的地址与扇区的起始地址不重合,则证明扇区起始地址与要写入的地址间原本可能存在数据 { SPI_FLASH_BufferWrite(EraseBuff,SectorPhyLocationAddr,(AddrStart - SectorPhyLocationAddr)); //将两地址间的有效数据反写 CurrenSectorLeft = CurrenSectorLeft - (AddrStart - SectorPhyLocationAddr); //当前扇区剩余字节数减去已写入的字节数量 } if(WriteLeftBytes <= CurrenSectorLeft) //判断当前扇区可以把剩下要写入的数据装下 { SPI_FLASH_BufferWrite((u8 *)buff,AddrStart,WriteLeftBytes); //则在起始位置写入剩下所有的数据 AddrStart += WriteLeftBytes; //起始地址调整到末尾 (此时此操作可能无意义) CurrenSectorLeft = CurrenSectorLeft - WriteLeftBytes; //扇区剩余字节减去写入数量 WriteLeftBytes = 0; //剩余写入数据量为0,写入完毕 } else //当前扇区只可以装入一部分要写入的数据 { SPI_FLASH_BufferWrite((u8 *)buff,AddrStart,CurrenSectorLeft); //将数据写满该扇区的剩余部分 AddrStart += CurrenSectorLeft; //写入地址调整 WriteLeftBytes -= CurrenSectorLeft; //剩余写入字节数调整 CurrenSectorLeft = 0; //当前扇区剩余字节数清0 } if(CurrenSectorLeft > 0) //若当前扇区未被写满,则将剩余部分缓冲区反写回Flash SPI_FLASH_BufferWrite(EraseBuff,AddrStart,CurrenSectorLeft); } res = RES_OK; return res; } return RES_PARERR;}
disk_ioctl 至少增加GET_SECTOR_COUNT、GET_BLOCK_SIZE、CTRL_SYNC三个状态的返回值,GET_SECTOR_COUNT的返回值为按照读取扇区来算总的扇区个数,GET_BLOCK_SIZE的返回值为读取扇区的大小,CTRL_SYNC返回值为RES_OK即可。
DRESULT disk_ioctl ( BYTE pdrv, /* Physical drive nmuber (0..) */ BYTE cmd, /* Control code */ void *buff /* Buffer to send/receive control data */){ DRESULT res; switch (pdrv) { case SPI_FLASH : switch(cmd) { case GET_SECTOR_COUNT: (*(DWORD *)buff) = 32768; res = RES_OK; break; case GET_BLOCK_SIZE: (*(DWORD *)buff) = SPI_FLASH_SECTOR; res = RES_OK; break; case CTRL_SYNC: res = RES_OK; break; } return res; } return RES_PARERR;}
至此,文件系统移植完毕,调用的时候f_mkfs(“0:”,0,512);只需要调用一次,其他的测试如下
void FatfsTest(){ FATFS fs; FIL fsrc; BYTE buffer[4096]; FRESULT res; UINT br, bw; BYTE if_Erase = 0; BYTE if_mkfs = 0; SPI_FLASH_Init(); if(if_Erase) SPI_FLASH_BulkErase(); res = f_mount(&fs,"0:",1); if(res == FR_NO_FILESYSTEM) { f_mkfs("0:",0,512); res = f_mount(&fs,"0:",1); } res = f_open(&fsrc, "0:src", FA_CREATE_ALWAYS | FA_WRITE | FA_READ); res = f_write(&fsrc, "12345", 5, &bw); res = f_close(&fsrc); res = f_open(&fsrc, "0:src", FA_WRITE | FA_READ); res = f_read(&fsrc, buffer, sizeof(buffer), &br);}
至此移植完成。
移植中遇到的问题:
1.执行挂载f_mount时出现FR_NO_FILESYSTEM提示。原因为没有执行f_mkfs,整个flash没有文件系统格式化。
2.执行过f_mkfs,但是依然出现FR_NO_FILESYSTEM的提示。仔细查找跟踪代码后,发现disk_write(pdrv, fs->win, 0, 1)
写入flash后立刻读出数据不一致,尤其是tbl[4] = sys; 写入错误会导致读出的时候找不到具体对应的文件系统,从而导致错误提示。原因是写入函数没有将原先的数据擦除,原先将该区域写入0,之后没有擦除则无法恢复。Flash的特性是1可以翻转写入0,但0不能写入1,只有擦除后,才可以正确。因此修改了disk_write,增加了先擦出再写入。
- STM32F103RC,FATFS,w25x16移植笔记
- Fatfs文件系统分析(4)-FATFS文件系统移植笔记
- FatFs移植笔记(R0.09)
- FatFs移植笔记(R0.09)
- STM32的FATFS文件系统移植笔记
- STM32的FATFS文件系统移植笔记
- fatfs移植
- FATFS移植
- w25x16
- stm32f103rc
- FatFs之tiny FatFs移植
- MSP430F5438A单片机基于SPI的FatFs移植笔记(一)
- MSP430F5438A单片机基于SPI的FatFs移植笔记(二)
- STM32的FATFS文件系统移植笔记(转…
- FatFs文件系统的移植
- FatFs文件系统的移植
- fatfs文件系统移植
- Fatfs移植到tq240
- ABAP 创建会计凭证错误:BKPFF $ RTDCLNT300
- maven学习(上-下)- 基本入门用法
- 移动端注意事项
- python 不是内部或外部命令解决方法
- iOS开发 将某个视图置于某视图之上
- STM32F103RC,FATFS,w25x16移植笔记
- C#控制台 利用命名参数提高程序的自己解释自己的特性
- shell 脚本hello world
- 网络、互联网、因特网的基本概念与组成
- mybatis的分页插件:mybatis-paginator、mybatis-pageHelper
- python对list中的每个元素进行某种操作
- 不同应用程序提供的数据的获取显示—自定义ContentProvider
- Android AIDL 进程间通信
- 前端,财务数据的正则表达式(一篇专门写给自己的博客)