Files
player/Project/Src/MyApp/flash_manager.c
2025-07-05 19:47:28 +08:00

339 lines
7.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;i<flashHeaderSize;i++) {if (((u8*)flashHeader)[i]==0xff) ((u8*)flashHeader)[i]=0;}
flashHeader->File[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;i<flashHeaderSize;i++) {if (((u8*)flashHeader)[i]==0xff) ((u8*)flashHeader)[i]=0;}
ret=flashHeader->FileNumber;
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;i<flashHeaderSize;i++) {if (((u8*)flashHeader)[i]==0xff) ((u8*)flashHeader)[i]=0;}
if (index<flashHeader->FileNumber)
{
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;i<flashHeaderSize;i++) {if (((u8*)flashHeader)[i]==0xff) ((u8*)flashHeader)[i]=0;}
if (index<flashHeader->FileNumber)
{
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;i<flashHeaderSize;i++) {if (((u8*)flashHeader)[i]==0xff) ((u8*)flashHeader)[i]=0;}
if (flashHeader->FileNumber<20)
{
for (int i=0;i<flashHeader->FileNumber;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;i<flashHeaderSize;i++) {if (((u8*)flashHeader)[i]==0xff) ((u8*)flashHeader)[i]=0;}
if (flashHeader->FileNumber>20)//如果文件数量大于10说明文件被破坏
{
FLASH_EraseAllSector();
flashHeader->FileNumber=0;
}
for (int i=0;i<flashHeader->FileNumber;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;i<check_size;i++)
{
FLASH_ReadData(flash_mem,addr,4096);
for (int j=0;j<4096;j++)
{
if (flash_mem[j]!=0xff)
{
FLASH_EraseOneSector(addr);
break;
}
}
addr+=4096;
}
myfree(flash_mem);
return 0;
}
//循环写入,必须在擦除之后才能写入
int FLASH_LoopWrite (u32 addr,u32 size ,int (*pGetData)(u8 *buff,u32 size))
{
if (pGetData==0) return -1;
u8* flash_mem=mymalloc (4096);
u32 check_size=0;
while (size)
{
if (size>4096)
{
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;
}