339 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			339 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
 | ||
| #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;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 |