⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ddfrom.c

📁 Atmal Flash驱动以及基于驱动之上的Flash页读写实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************/
/* Copyright (c) 2005,夏新电子通信事业部									*/
/* All rights reserved.														*/
/*                   														*/
/* 文件名称:Ddfrom.c             										*/
/* 摘    要:该文件包含Atmel Flash驱动中间层的函数定义						*/
/*                    														*/
/* 当前版本:1.0               												*/
/* 作    者:王劲涛              											*/
/* 完成日期:2005年6月14日 创建           									*/
/*                   														*/
/****************************************************************************/

#ifdef __cplusplus
    extern   "C"
    {
#endif


/************************************************************************/
/*      INCLUDE FILES                                                   */
/************************************************************************/
#include	<stdio.h>
#include 	"stdlib.h"
#include    <string.h>
#include	"Tdef.h"
#include 	"DFR_def.h"
#include	"Ddfrom.h"

//#define SHARP
#define ATMEL

/************************************************************************/
/*      全局变量                                                  		*/
/************************************************************************/
byte LogicPage[MAX_USE_BLOCK][MAX_LOGIC_PAGE_NUM];	//逻辑页号对应的物理页号数组
ulong LogicBlock[MAX_USE_BLOCK];					//已用块物理地址数组
byte FreePage[MAX_USE_BLOCK];						//最小可用物理页号数组
ulong FreeBlock[MAX_FREE_BLOCK];					//备用块物理地址数组
word FML_RAMLock[ERASE_PROG_CODE_SIZE];
word FML_RAMProg[ERASE_PROG_CODE_SIZE];			//用于将FML_ProgOneWord函数转存到内存
word FML_RAMErase[ERASE_PROG_CODE_SIZE];			//用于将FML_BlockErase函数转存到内存

//所使用Block的相对地址
const ulong fml_block_address[MAX_USE_BLOCK + MAX_FREE_BLOCK] = 
{	0x020000, 0x028000, 0x030000, 0x038000 };

/************************************************************************/
/*	函数名:	FfxFlashFormat											*/
/*	功能:		格式化Flash中用于存放可变数据的块						*/
/*	输入参数:	mode, 为兼容原接口保留,无实际意义						*/
/*	输出参数:	无														*/
/*	返回值:	如果成功返回FSYS_FMDFORMAT_OK,否则返回FSYS_FMDFORMAT_ERR*/
/*																		*/
/************************************************************************/
word dDFRomFormat(void)
{
	word count = 0;
	ulong temp_addr;
	FML_RESULT rel = FML_SUCCESS;

	while ( count < MAX_USE_BLOCK )
	{
		temp_addr = fml_block_address[count];
		rel = FML_BlockErase(temp_addr);
		rel |= FML_ProgOneWord(temp_addr, BLOCK_IN_USE);
		temp_addr++;
		count++;
		rel |= FML_ProgOneWord(temp_addr, count);
		if ( rel != FML_SUCCESS )
		{
			return DDFR_NG;
		}
		
	}

	while ( count < MAX_USE_BLOCK + MAX_FREE_BLOCK )
	{
		temp_addr = fml_block_address[count];
		rel = FML_BlockErase(temp_addr);
		if ( rel != FML_SUCCESS )
		{
			return DDFR_NG;
		}
		count++;
	}
	return DDFR_OK;
}



#if 1
/************************************************************************/
/*	函数名:	FfxInitialize											*/
/*	功能:		初始化驱动中间层的管理									*/
/*	输入参数:	无														*/
/*	输出参数:	无														*/
/*	返回值:	如果成功返回CMN_FSY_OK,否则返回CMN_FSY_DRIVER_ERROR	*/
/*																		*/
/************************************************************************/
word dDFRomInit(void)
{
	word temp_data;
	ulong temp_addr, count, i;
	word flash_sts;
	FML_RESULT rel;
	byte phy_page_count;			//物理块号计数
	PAT_UNIT_INFO page_info;
	byte free_block_count = 0;
	ulong block_addr;

	FML_init();				
	memset(LogicBlock, 0xFF, MAX_USE_BLOCK * sizeof(ulong));
	memset(LogicPage, 0xFF, MAX_USE_BLOCK * MAX_LOGIC_PAGE_NUM);	
	for ( count = 0; count < MAX_USE_BLOCK + MAX_FREE_BLOCK; count++ )
	{
		flash_sts = *sysAddress(fml_block_address[count]);
		temp_addr = fml_block_address[count];
		temp_data = *sysAddress(temp_addr + 1);		//第3、4个字节为逻辑块号数据

		//如果该块已使用
		if ( flash_sts == BLOCK_IN_USE )
		{
			//chg start by wjt 2005.11.01
			if (temp_data > 0 && temp_data <= MAX_USE_BLOCK)	//逻辑块号合法
			{
				LogicBlock[temp_data - 1] = temp_addr;	//存储逻辑块对应的物理块首地址
				temp_addr = LogicBlock[temp_data - 1] + BLOCK_INFO_SIZE;	//PAT起始地址

				//依次读取PAT中每个单元的管理信息作相应处理
				FreePage[temp_data - 1] = MAX_PHY_PAGE_NUM + 1;
				for ( phy_page_count = 0; phy_page_count < MAX_PHY_PAGE_NUM; phy_page_count++, temp_addr++)
				{
					page_info = *((volatile PAT_UNIT_INFO*)( ROM_BASE + temp_addr*2));	//读取PAT单元信息			
					if ( page_info.page_sts == PAGE_USED )		//如果该页已使用
					{
						if ( page_info.page_lid <= MAX_LOGIC_PAGE_NUM && page_info.page_lid != 0 )	//如果块内逻辑页号合法
						{
							LogicPage[temp_data - 1][page_info.page_lid - 1] = phy_page_count + 1;		//存储物理块号到数组LogicPage中
						}
						else if( page_info.page_lid > MAX_LOGIC_PAGE_NUM )		//该逻辑页号超出范围(写入页号时断电)
						{
							FML_ProgOneWord( temp_addr, PAGE_INVALID);				//将出错的逻辑页号修改为00
						}
						else 		//PAT单元信息为0x0000
						{
							continue;
						}					
					}
				
					else if ( page_info.page_sts == PAGE_FREE )	//该页未使用
					{
						//如果该页为最小空闲物理页,则把物理页号存入数组FreePage
						if ( phy_page_count + 1 < FreePage[temp_data - 1] )
						{
							FreePage[temp_data - 1] = phy_page_count + 1;
						}
					}
				
					else //写入页状态时断电
					{
						FML_ProgOneWord(temp_addr, PAGE_INVALID);		//将出错的逻辑页状态修改为00
					}
				}
			}

			else	//存储的逻辑块号非法
			{
				//对该块进行擦除操作
				rel = FML_BlockErase(fml_block_address[count]);
				if ( rel == FML_FAILURE )
				{
					return CMN_FSY_DRIVER_ERROR;
				}
				if ( free_block_count < MAX_FREE_BLOCK)
				{
					//将该块物理地址填入FreeBlock数组
					FreeBlock[free_block_count] = fml_block_address[count];
					free_block_count++;
				}
			}		
		}
		//chg end by wjt 2005.11.01
		
		//如果该块未使用,将该块物理地址填入FreeBlock数组
		else if ( flash_sts == BLOCK_FREE )
		{
			if ( temp_data != 0xFFFF )		//新块数据写入时断电
			{
				rel = FML_BlockErase(fml_block_address[count]);
				if ( rel == FML_FAILURE )
				{
					return CMN_FSY_DRIVER_ERROR;
				}
			}
			if ( free_block_count < MAX_FREE_BLOCK)
			{
				FreeBlock[free_block_count] = fml_block_address[count];
				free_block_count++;
			}
		}

		//如果该块已废弃(表明上次擦除工作因意外未完成)
		else if ( flash_sts == BLOCK_INVALID )
		{
			//对该块进行擦除操作
			rel = FML_BlockErase(fml_block_address[count]);
			if ( rel == FML_FAILURE )
			{
				return CMN_FSY_DRIVER_ERROR;
			}
			if ( free_block_count < MAX_FREE_BLOCK)
			{
				//将该块物理地址填入FreeBlock数组
				FreeBlock[free_block_count] = fml_block_address[count];
				free_block_count++;
			}
		}
		
		//块状态修改时断电
		else
		{
			//对该块进行擦除操作
			rel = FML_BlockErase(fml_block_address[count]);
			if ( rel == FML_FAILURE )
			{
				return CMN_FSY_DRIVER_ERROR;
			}
			if ( free_block_count < MAX_FREE_BLOCK)
			{
				//将该块物理地址填入FreeBlock数组
				FreeBlock[free_block_count] = fml_block_address[count];
				free_block_count++;
			}
		}
	}

	//add start by wjt 2005.10.21 文件系统容错性处理
	for ( count = 0; count < MAX_USE_BLOCK; count++ )
	{
		if ( LogicBlock[count] == 0xFFFFFFFF )
		{
			temp_addr = FreeBlock[0];
			rel = FML_ProgOneWord(temp_addr, BLOCK_IN_USE);
			temp_addr++;
			rel |= FML_ProgOneWord(temp_addr, count + 1);
			LogicBlock[count] = FreeBlock[0];
			for ( i = 0; i < MAX_USE_BLOCK + MAX_FREE_BLOCK; i++ )
			{
				if ( *sysAddress(fml_block_address[i]) == BLOCK_FREE )
				{
					FreeBlock[0] = fml_block_address[i];
					break;
				}
			}
		}
	}
	//add end by wjt 2005.10.21
	return CMN_FSY_OK;
}
	

/************************************************************************/
/*	函数名:	FfxSectorRead											*/
/*	功能:		根据起始逻辑页号从Flash上读入一页或几页的信息			*/
/*	输入参数:	nID -- 起始的逻辑页号									*/
/*		  		num -- 需要读入的页数									*/
/*	输出参数:	*pcBuffer -- 存储读出的数据								*/
/*	返回值:	如果成功返回FSYS_FMDREDANS_OK,否则返回FSYS_FMDREDANS_NG*/
/*																		*/
/************************************************************************/
word dDFRomRead(word aUnit, word nID, byte *pcBuffer)
{
	ulong i;
	byte num;
	ulong page_lid;				//逻辑页号
	byte page_pid;				//块内物理页号
	ulong page_addr;
	byte block_id;
	word *buffer = (word *)pcBuffer;
	FML_RESULT rel;
	FML_FLASH_STATUS flash_sts;

	if ( nID > MAX_USE_BLOCK * MAX_LOGIC_PAGE_NUM ) return DDFR_NG;
	if (((nID % MAX_LOGIC_PAGE_NUM)!=1) && (aUnit == DDFR_BLOCK)) return DDFR_NG;
	switch (aUnit)
	{
		case DDFR_PAGE:
			num = 1;
		case DDFR_BLOCK:
			num = MAX_LOGIC_PAGE_NUM;
		default:
			num = 1;
	}
	
	for (i = 0; i < num; i++)
	{
		page_lid = nID + i;
		flash_sts = FML_GetRealAddr(page_lid, &block_id, &page_pid, &page_addr);
		if ( flash_sts == FML_FLASH_FREE )	
		{
			memset((byte *)buffer, 0xff, PAGE_SIZE*2);
			//return FSYS_FMDREDANS_NG;
		}
		else
		{
			rel = FML_ReadOnePage(page_addr, buffer);
		}
		buffer += PAGE_SIZE;		//因为buffer为byte*, 而PAGE_SIZE是按16bit记数
	}
	
	return DDFR_OK;
}


/************************************************************************/
/*	函数名:	FfxSectorWrite											*/
/*	功能:		根据起始逻辑页号向Flash上写入一页的信息					*/
/*	输入参数:	nID -- 起始的逻辑页号									*/
/*		  		aSrcAddr -- 将要被写入的内容							*/
/*		 																*/
/*	输出参数:	无														*/
/*	返回值:	如果成功返回FSYS_FMDWRTANS_OK,否则返回FSYS_FMDWRTANS_NG*/
/*																		*/
/************************************************************************/
word dDFRomWrite(word nID, byte *aSrcAddr)
{
	byte block_id;		//逻辑块号
	word free_page_id = 0;
	byte phy_page_in_block;					//块内物理页号
	byte logic_page_in_block;					//块内逻辑页号
	ulong logic_page_id = nID;					//总逻辑页号
	ulong page_addr;							//页物理地址
	ulong pat_addr;								//PAT单元地址
	byte *alt_data_addr = aSrcAddr;			//源数据地址
	word *data_addr = (word *)alt_data_addr;
	FML_RESULT rel;
	FML_FLASH_STATUS flash_sts;

	if ( nID > MAX_USE_BLOCK * MAX_LOGIC_PAGE_NUM ) return DDFR_NG;

	logic_page_in_block = logic_page_id % MAX_LOGIC_PAGE_NUM;
	if (logic_page_in_block == 0) logic_page_in_block = MAX_LOGIC_PAGE_NUM;
	flash_sts = FML_GetRealAddr( logic_page_id, &block_id, &phy_page_in_block, &page_addr);
	if (flash_sts !=  FML_FLASH_FREE) 
	{
		FML_AllocNewPage(block_id, &pat_addr, &page_addr);
		phy_page_in_block = LogicPage[block_id - 1][logic_page_in_block - 1];
	}
	else
	{
		free_page_id = FreePage[block_id - 1];
		//add start by wjt 2005.11.14 for overrun bug
		if (free_page_id > MAX_PHY_PAGE_NUM) 
		{
			rel = FML_BlockCopy(block_id);
			if (rel != FML_SUCCESS) return FML_FAILURE;
			free_page_id = FreePage[block_id - 1];
		}
		//add end by wjt 2005.11.14 for overrun bug
		FreePage[block_id - 1]++;
		//计算物理页管理信息地址
		page_addr = LogicBlock[block_id - 1] + (free_page_id - 1) * PAGE_SIZE + BLOCK_INFO_SIZE + PAT_SIZE;
		pat_addr = LogicBlock[block_id - 1] + (free_page_id - 1) + BLOCK_INFO_SIZE ;
		FML_ProgOneWord(pat_addr, 0x00FF);
	}
			
	//将一页信息写入到Flash中
	rel = FML_ProgOnePage(page_addr, data_addr);
	if ( rel == FML_FAILURE )
	{
		return DDFR_NG;
	}
	//写入成功后修改在相应的PAT单元中写入逻辑页号并更新数组FreePage
	FML_ProgOneWord(pat_addr, 0x00FF&logic_page_in_block);
	LogicPage[block_id - 1][logic_page_in_block - 1] = FreePage[block_id - 1] - 1;
	if ( flash_sts !=  FML_FLASH_FREE )
	{
		pat_addr = LogicBlock[block_id - 1] + BLOCK_INFO_SIZE + (phy_page_in_block - 1);
		FML_ProgOneWord(pat_addr, 0x0000);
	}

	return DDFR_OK; 
}


/************************************************************************/
/*	函数名:	dDFRomStatusChk											*/
/*	功能:		本函数是为兼容原有文件系统而保留,不做具体操作			*/
/*	输入参数:	无														*/
/*	输出参数:	无														*/
/*	返回值:	无														*/
/*																		*/
/************************************************************************/
word dDFRomStatusChk(void)
{
	return DDFR_OK;
}


/************************************************************************/
/*	函数名:	dDFRomReWriteSet											*/
/*	功能:		本函数是为兼容原有文件系统而保留,不做具体操作			*/
/*	输入参数:	无														*/
/*	输出参数:	无														*/
/*	返回值:	无														*/
/*																		*/
/************************************************************************/
word dDFRomReWriteSet(word aMode)
{
	return DDFR_OK;
}
#endif


/************************************************************************/
/*	函数名:	FML_init					*/
/*	功能:		解除开机后所有FML管理下的Flash块的soft-lock	*/
/*	输入参数:	sector -- 被解锁的块物理地址			*/
/*	输出参数:	无														*/
/*	返回值:	无				*/
/*																		*/
/************************************************************************/
void FML_init(void)
{
 	ulong i, block_sum;
	ulong sector_addr = 0;
	word length = 0;
	ulong p1 = (ulong)FML_BlockEraseF;
	ulong p2 = (ulong)FML_ProgOneWordF;

	length = p2 - p1;
	if ((length % 2) != 0) length++;
	for (i = 0; i < length/2; i++)
	{
		FML_RAMErase[i] = *((volatile word *)p1);
		p1+=2;
	}

	p1 = FML_ProgOnePage;
	length = p1 - p2;
	if ((length % 2) != 0) length++;
	for (i = 0; i < length/2; i++)
	{
		FML_RAMProg[i] = *((volatile word *)p2);
		p2+=2;
	}

	#ifdef SHARP
	p1 = (ulong)FML_BlockEraseF;
	p2 = (ulong)FML_SectorLockF;
	length = p1 - p2;
	if ((length % 2) != 0) length++;
	for (i = 0; i < length/2; i++)
	{
		FML_RAMLock[i] = *((volatile word *)p2);
		p2+=2;
	}
	#endif
	#ifdef ATMEL_1601
	//Lock font's block
	for (i = 0; i < FONT_BLOCK_NUM; i++)
	{
		sector_addr = i * MAIN_BLOCK_SIZE;
		FML_SectorLockF(sector_addr);	
	}

	//Lock program's block
	block_sum = FONT_BLOCK_NUM + MAX_USE_BLOCK + MAX_FREE_BLOCK;
	for (i = block_sum; i < MAIN_BLOCK_NUM; i++)
	{
		sector_addr = i * MAIN_BLOCK_SIZE;
		FML_SectorLockF(sector_addr);	
	}

	for (i = 0; i < PARA_BLOCK_NUM; i++)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -