#include "flash_manager.h" #include "mymem.h" #include "spi_flash.h" #include "string.h" #ifndef BOOTLOADER # include "rtthread.h" #endif //使用信号量对FLASH的访问进行保护 #ifndef BOOTLOADER static struct rt_semaphore g_flash={0}; static rt_err_t g_flash_err=RT_ERROR; #define FLASH_ENTER_USED() {while (g_flash_err==RT_ERROR) \ {g_flash_err=rt_sem_init(&g_flash,"g_flash",1,RT_IPC_FLAG_PRIO);}\ rt_sem_take (&g_flash,RT_WAITING_FOREVER);\ } #define FLASH_EXIT_USED() {rt_sem_release (&g_flash);} #else #define FLASH_ENTER_USED() {} #define FLASH_EXIT_USED() {} #endif int FLASH_ReadData (uint8_t* pBuffer, uint32_t ReadAddr , uint32_t NumByteToRead ) { FLASH_ENTER_USED(); sFLASH_ReadBuffer (pBuffer,ReadAddr,NumByteToRead); //SPI_Flash_Read (pBuffer,ReadAddr,NumByteToRead); //W25QXX_Read (pBuffer,ReadAddr,NumByteToRead); FLASH_EXIT_USED(); return 0; } int FLASH_WriteData (uint8_t* pBuffer, uint32_t WriteAddr, uint32_t NumByteToWrite) { FLASH_ENTER_USED(); sFLASH_WriteBuffer (pBuffer,WriteAddr,NumByteToWrite); //SPI_Flash_Write_NoCheck (pBuffer,WriteAddr,NumByteToWrite); //W25QXX_Write_NoCheck (pBuffer,WriteAddr,NumByteToWrite); FLASH_EXIT_USED(); return 0; } int FLASH_EraseOneSector (uint32_t SectorAddr) { FLASH_ENTER_USED(); sFLASH_EraseSector (SectorAddr); //SPI_Flash_Erase_Sector (SectorAddr); //W25QXX_Erase_Sector(SectorAddr); FLASH_EXIT_USED(); return 0; } int FLASH_EraseAllSector (void) { FLASH_ENTER_USED(); sFLASH_EraseBulk(); //SPI_Flash_Erase_Chip (); //W25QXX_Erase_Chip(); FLASH_EXIT_USED(); return 0; } //向FLASH中添加文件 //本函数把要添加文件的文件名,存储地址和大小信息存储至文件头中 //函数没有进行地址是否重合的判断,请使用FLASH_GetUsed()函数取得可以使用的地址 int FLASH_AddFile (char *fileName,u32 address,u32 fileSize) { FLASH_HeaderStruct *flashHeader=0; u32 flashHeaderSize=4096; flashHeader=mymalloc(flashHeaderSize); FLASH_ReadData((u8*)flashHeader,0,flashHeaderSize); for (int i=0;iFile[flashHeader->FileNumber].Address=address; flashHeader->File[flashHeader->FileNumber].FileSize=fileSize; mymemcpy(flashHeader->File[flashHeader->FileNumber].FileName,fileName,strlen(fileName)+1); flashHeader->FileNumber++; FLASH_CheckErase(0,4096); FLASH_WriteData((u8*)flashHeader,0,4096); myfree(flashHeader); return 0; } //返回FLASH中存储的文件数目 int FLASH_GetFileNum (void) { int ret=0; FLASH_HeaderStruct *flashHeader=0; u32 flashHeaderSize=4096; flashHeader=mymalloc(flashHeaderSize); FLASH_ReadData((u8*)flashHeader,0,flashHeaderSize); for (int i=0;iFileNumber; myfree(flashHeader); return ret; } //获取指定索引的文件信息,返回0,成功 int FLASH_GetFileInfo (int index,FLASH_FileStruct *file) { int ret=0; FLASH_HeaderStruct *flashHeader=0; u32 flashHeaderSize=4096; flashHeader=mymalloc(flashHeaderSize); FLASH_ReadData((u8*)flashHeader,0,flashHeaderSize); for (int i=0;iFileNumber) { mymemcpy (file, &flashHeader->File[index],sizeof (FLASH_FileStruct)); } else { ret=-1; } myfree(flashHeader); return ret; } //删除指定索引之后的所有文件 int FLASH_DeleteFile (int index) { int ret=0; FLASH_HeaderStruct *flashHeader=0; u32 flashHeaderSize=4096; flashHeader=mymalloc(flashHeaderSize); FLASH_ReadData((u8*)flashHeader,0,flashHeaderSize); for (int i=0;iFileNumber) { flashHeader->FileNumber=index; u32 sizeUsed=FLASH_GetUsed(); FLASH_CheckErase(0,4096); FLASH_WriteData((u8*)flashHeader,0,4096); u32 addrToDelete =FLASH_GetUsed(); u32 sizeToDelete=sizeUsed-addrToDelete; FLASH_CheckErase (addrToDelete,sizeToDelete); } else { ret=-1; } myfree(flashHeader); return ret; } //获取FLASH容量 u32 FLASH_GetFlashSize (void) { return 16*1024*1024; } //返回FLASH已经使用了多少存储空间 //此返回值可直接用于新文件的存储地址 u32 FLASH_GetUsed (void) { FLASH_HeaderStruct *flashHeader=0; u32 flashHeaderSize=4096; u32 usedBluk=1;//文件索引用了一个块 flashHeader=mymalloc(flashHeaderSize); FLASH_ReadData((u8*)flashHeader,0,flashHeaderSize); for (int i=0;iFileNumber<20) { for (int i=0;iFileNumber;i++) { usedBluk+=flashHeader->File[i].FileSize/4096+1; } } myfree(flashHeader); return usedBluk*4096; } //读取指定文件,返回成功读取的大小 int FLASH_ReadFile (char *fileName,u32 offset,u8 *recvBuff,u32 readLength) { int ret=0; u32 file_size=0; u32 file_addr=FLASH_FindFile (fileName,&file_size); if (file_addr) { int read_block=0; if (readLength>file_size-offset) readLength=file_size-offset; ret=readLength; while (readLength) { if (readLength>4096) read_block=4096; else read_block=readLength; FLASH_ReadData (recvBuff,file_addr+offset,read_block); offset+=read_block; readLength-=read_block; recvBuff+=read_block; } } else { ret=0; } return ret; } //保存文件,返回非0失败 int FLASH_SaveFile (char *FileName,u8 *data,u32 size) { int ret=-1; if (FLASH_FindFile(FileName,0)==0) { u32 flash_write_addr=FLASH_GetUsed(); u32 save_size=0; FLASH_CheckErase(flash_write_addr,size); FLASH_AddFile(FileName,flash_write_addr,size); while(size) { if (size>4096) { save_size=4096; } else { save_size=size; } FLASH_WriteData(data,flash_write_addr,save_size); size-=save_size; flash_write_addr+=save_size; data+=save_size; } ret=0; } return ret; } //查找是否有同名文件,无返回0,有返回偏移地址 //参数size用于获取文件大小,不需要文件大小时此参数应为0 u32 FLASH_FindFile (char *fileName,u32 *size) { FLASH_HeaderStruct *flashHeader=0; u32 flashHeaderSize=4096; u32 ret=0; flashHeader=mymalloc(flashHeaderSize); FLASH_ReadData((u8*)flashHeader,0,flashHeaderSize); for (int i=0;iFileNumber>20)//如果文件数量大于10说明文件被破坏 { FLASH_EraseAllSector(); flashHeader->FileNumber=0; } for (int i=0;iFileNumber;i++) { if (strcmp(flashHeader->File[i].FileName,fileName)==0) { ret=flashHeader->File[i].Address; if (size) *size=flashHeader->File[i].FileSize; break; } } myfree(flashHeader); return ret; } //校验后擦除 //校验FLASH中指定存储空间是否有数据,如果有数据,则进行擦除操作 //函数没有进行地址对齐,请保证参数addr为4096的整数倍 int FLASH_CheckErase (u32 addr,u32 size) { u8* flash_mem=mymalloc (4096); u32 check_size=size/4096; if (size%4096) check_size++; for (int i=0;i4096) { check_size=4096; } else { check_size=size; } pGetData(flash_mem,check_size); FLASH_WriteData(flash_mem,addr,check_size); addr+=check_size; size-=check_size; } return 0; }