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

📄 ddfrom.c

📁 Atmal Flash驱动以及基于驱动之上的Flash页读写实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	{
		sector_addr = PRRA_BLOCK_START_ADDR + i * PARA_BLOCK_SIZE;
		FML_SectorLockF(sector_addr);	
	}
	#endif
	return;
}


#ifdef ATMEL
/************************************************************************/
/*	函数名:	FML_SectorUnLock											*/
/*	功能:		解除开机后Flash块的soft-lock										*/
/*	输入参数:	sector -- 被解锁的块物理地址						*/
/*	输出参数:	无														*/
/*	返回值:	无				*/
/*																		*/
/************************************************************************/
word FML_SectorLockF(ulong sector)
{
	word i, count;
	*sysAddress(0x555) = 0xAA;
	*sysAddress(0xAAA) = 0x55;
	*sysAddress(0x555) = 0x80;
	*sysAddress(0x555) = 0xAA;
	*sysAddress(0xAAA) = 0x55;
	*sysAddress(sector) = 0x60;

	//for (count = 0; count < 5000; count++)
	//	i = i;
	return 0;
}

/************************************************************************/
/*	函数名:	FML_BlockErase											*/
/*	功能:		擦除已废弃的物理块										*/
/*	输入参数:	block_addr -- 被擦除块的物理地址						*/
/*	输出参数:	无														*/
/*	返回值:	操作返回FML_SUCCESS,否则返回FML_FAILURE				*/
/*																		*/
/************************************************************************/
FML_RESULT FML_BlockEraseF(ulong pwAddr)
{
	word TimeOut = 0;
	ulong Dst = pwAddr;
	word CurrData;

	__DI();
	*sysAddress(0x555) = 0xf0;
	*sysAddress(0x555) = 0xaa;
	*sysAddress(0xAAA) = 0x55;
	*sysAddress(0x555)  = 0x80;
	*sysAddress(0x555)  = 0xaa;
	*sysAddress(0xAAA) = 0x55;
	*sysAddress(Dst) = 0x30;

	while( TimeOut < Erase_MAX_TIMEOUT )
	{
		CurrData = *sysAddress(Dst);
		CurrData = CurrData & IO7_BIT;
		if (CurrData == IO7_BIT)
		{
			__EI();
			return FML_SUCCESS;
		}

		TimeOut++;
	}
	*sysAddress(0x555) = 0xF0;
	__EI();
	return FML_FAILURE;
}


/************************************************************************/
/*	函数名:	FML_ProgOneWord											*/
/*	功能:		往Flash的指定地址上写入1个word							*/
/*	输入参数:	dst -- 要写入的地址										*/
/*				data -- 要写入的数据									*/
/*	输出参数:	无														*/
/*	返回值:	操作返回FML_SUCCESS,否则返回FML_FAILURE				*/
/*																		*/
/************************************************************************/
FML_RESULT FML_ProgOneWordF(ulong pwAddr, word wData)
{
	word TimeOut = 0;
	ulong Dst = pwAddr;
	word TrueData = wData;
	word CurrData;

	__DI();
	*sysAddress(0x555) = 0x00F0; 
	*sysAddress(0x555) = 0x00AA; // write data 0x00AA to device addr 0x555
	*sysAddress(0xAAA) = 0x0055; // write data 0x0055 to device addr 0xAAA
	*sysAddress(0x555) = 0x00A0; // write data 0x00A0 to device addr 0x555
	*sysAddress(Dst) = TrueData; // transfer the word to destination

	TrueData = TrueData & IO7_BIT;
	while( TimeOut < MAX_TIMEOUT )
	{
		CurrData = *sysAddress(Dst);
		CurrData = CurrData & IO7_BIT;
		if (CurrData == TrueData)
		{
			__EI();
			return FML_SUCCESS;
		}
		TimeOut++;
	}
	__EI();
	return FML_FAILURE;
}
#endif

#ifdef SHARP
word FML_SectorUnLockF(void)
{
	byte reg_sts;
	__DI();
	*sysAddress(0x0000) = 0x0050;
	*sysAddress(0x0000) = 0x0070;
	reg_sts = *sysAddress(0x0000);
	if (reg_sts != 0x80)
	{
		__EI();
		return reg_sts;
	}
	*sysAddress(0x0000) = 0x0060;
	*sysAddress(0x0000) = 0x00D0;
	while (*sysAddress(0x0000) != 0x0080);
	*sysAddress(0x0000) = 0x00FF;
	__EI();
	return 0;
}

FML_RESULT FML_BlockEraseF(ulong pwAddr)
{
	//word i, timeout;
	__DI();
  	*sysAddress(0x0000) = 0x50;			/* clear stats register */

	*sysAddress(pwAddr) = 0x20;
	*sysAddress(pwAddr) = 0xD0;

	while(*sysAddress(0x0000) != 0x80);	

	#if 0
	while(timeout < MAX_TIMEOUT)
	{
		i =	*sysAddress(pwAddr);
		if ( i == 0x80 )
		{
			*sysAddress(0x0000) = 0xFF;
			__EI();
			return 0;
		}
		i++;
	}
	
	//*sysAddress(0x0000) = 0xFF;
	__EI();
	return i;
	#endif
	*sysAddress(0x0000) = 0xFF;
	__EI();
	return 0;
}

FML_RESULT FML_ProgOneWordF(ulong pwAddr, word wData)
{
	word i, timeout;
	__DI();
	*sysAddress(0x0000) = 0x50;
	*sysAddress(pwAddr) = 0x40;
	*sysAddress(pwAddr) = wData;
	
	while(*sysAddress(0x0000) != 0x80);
	*sysAddress(0x0000) = 0xFF;
	__EI();
	return 0;
}
#endif

/************************************************************************/
/*	函数名:	FML_ProgOnePage											*/
/*	功能:		往Flash的指定地址上写入1页数据							*/
/*	输入参数:	dst -- 要写入的地址										*/
/*				src -- 待写入的数据										*/
/*	输出参数:	无														*/
/*	返回值:	操作返回FML_SUCCESS,否则返回FML_FAILURE				*/
/*																		*/
/************************************************************************/
FML_RESULT FML_ProgOnePage(ulong dst, word *src)
{	
	byte count;
	FML_RESULT result;

	if (dst % BLOCK_SIZE == 0) return FML_FAILURE;	//add by wjt for prevent wrong addr write
	for (count = 0; count < PAGE_SIZE; count++)
	{
		result = FML_ProgOneWord(dst, *src);
		if ( result != FML_SUCCESS ) 
		{
			return FML_FAILURE;
		}
		dst ++;
		src ++;
	}
	return FML_SUCCESS;
}

/************************************************************************/
/*	函数名:	FML_ReadOnePage											*/
/*	功能:		从Flash的指定地址上读入1页数据							*/
/*	输入参数:	addr -- 要读入的地址									*/
/*				data_ptr -- 存放读出数据的内存指针							*/
/*	输出参数:	无														*/
/*	返回值:	操作返回FML_SUCCESS				*/
/*																		*/
/************************************************************************/
static FML_RESULT FML_ReadOnePage(ulong addr, word *data_ptr)
{
	byte i;
	for( i = 0; i < PAGE_SIZE; i++)
	{
		*(data_ptr + i) = *(sysAddress(addr + i));	
	}
	return FML_SUCCESS;
}

/************************************************************************/
/*	函数名:	FML_GetRealAddr											*/
/*	功能:		得到逻辑页对应的真实物理地址							*/
/*	输入参数:	nID -- 逻辑页号											*/
/*	输出参数:	*block_id -- 逻辑块号									*/
/*				*page_id -- 块内物理页号								*/
/*				*page_addr -- 页物理地址								*/
/*	返回值:	如果该物理页未使用,返回FML_FLASH_FREE					*/
/*				否则返回FML_FLASH_INUSE									*/
/*																		*/
/************************************************************************/
static FML_FLASH_STATUS FML_GetRealAddr(ulong nID, byte *block_id, 
										byte *page_id, ulong *page_addr)
{	
	byte temp_bid, temp_pid;
	word phy_page_id;
	temp_bid = (nID - 1)/ MAX_LOGIC_PAGE_NUM;		//求逻辑块号
	temp_pid = nID % MAX_LOGIC_PAGE_NUM;		//求块内逻辑页号
	*block_id = temp_bid + 1;
	if (temp_pid == 0) temp_pid = MAX_LOGIC_PAGE_NUM;
	phy_page_id = LogicPage[temp_bid][temp_pid-1];

	if (phy_page_id == 0xFF) 
	{
		return FML_FLASH_FREE;
	}

	else
	{
		*page_id = phy_page_id;
		//物理页首地址 = 块首地址 + 块管理信息大小 + PAT大小 + 块内页地址
		*page_addr  = LogicBlock[temp_bid] + BLOCK_INFO_SIZE + PAT_SIZE  + (phy_page_id - 1) * PAGE_SIZE;
		return FML_FLASH_INUSE;
	}
}


/************************************************************************/
/*	函数名:	FML_AllocNewBlock										*/
/*	功能:		分配新的物理块											*/
/*	输入参数:	block_id -- 逻辑块号									*/
/*	输出参数:	*block_addr -- 新块的物理地址							*/
/*	返回值:	操作返回FML_SUCCESS,否则返回FML_FAILURE				*/
/*																		*/
/************************************************************************/
static FML_RESULT FML_AllocNewBlock(byte block_id, ulong *block_addr)
{
	ulong temp_addr;
	word logic_block_num;
	ulong temp_data;
	byte i;
	FML_RESULT rel;
	
	*block_addr = FreeBlock[0];				//将新块的物理地址赋予*block_addr
	if (*block_addr == BLOCK_ADDR_INVALID)	//已无新块可供申请
	{
		return FML_FAILURE;					
	}
	temp_addr = *block_addr + 1;			//物理块逻辑块号存放地址
	logic_block_num = block_id & 0x00FF;	//将逻辑块号调整为word型数据

	rel = FML_ProgOneWord(temp_addr, logic_block_num);
	if (rel == FML_SUCCESS)
	{
		//为了使每个Block尽量地被平均使用到,将数组FreeBlock中的数据前移一个单元
		//即把原来FreeBlock[1]的数据放到FreeBlock[0]中,把FreeBlock[2]的数据放到
		//FreeBlock[1]中,依此类推,最后一项的数据置为0xFFFFFFFF
		for (i = 0; i < MAX_FREE_BLOCK - 1; i++)
		{
			temp_data = FreeBlock[i + 1];
			FreeBlock[i] = temp_data;
		}
		FreeBlock[MAX_FREE_BLOCK - 1] = BLOCK_ADDR_INVALID;
	}
	FreePage[block_id - 1]  = 1;
	return rel;
}


/************************************************************************/
/*	函数名:	FML_BlockCopy											*/
/*	功能:		将可用空间不足的物理块上的数据整理复制到新块中			*/
/*	输入参数:	block_id -- 源数据所在的块								*/
/*	输出参数:	无														*/
/*	返回值:	操作返回FML_SUCCESS,否则返回FML_FAILURE				*/
/*																		*/
/************************************************************************/
static FML_RESULT FML_BlockCopy(byte block_id)
{
	ulong new_block_addr;
	ulong old_block_addr;
	word i;
	word pat_data;
	ulong pat_addr = 0;
	ulong data_addr;
	ulong old_data_addr;
	word buffer_page[PAGE_SIZE];
	ulong phy_page_count;
	PAT_UNIT_INFO page_info;
	FML_RESULT rel;

	old_block_addr = LogicBlock[block_id - 1];
	FML_AllocNewBlock(block_id, &new_block_addr);
	for ( i = 0; i < MAX_LOGIC_PAGE_NUM; i++)
	{
		if ( LogicPage[block_id - 1][i] != PAGE_FREE )
		{
			phy_page_count = FreePage[block_id - 1];
			FreePage[block_id - 1]++;

			pat_addr = new_block_addr + phy_page_count + BLOCK_INFO_SIZE  - 1;
			data_addr = new_block_addr + BLOCK_INFO_SIZE + PAT_SIZE + (phy_page_count - 1)* PAGE_SIZE;
			pat_data = 0x00FF & (i + 1);
			old_data_addr = old_block_addr + BLOCK_INFO_SIZE + PAT_SIZE 
								+ ((word)(LogicPage[block_id - 1][i] - 1)) * PAGE_SIZE;
			FML_ProgOneWord(pat_addr, pat_data);	//写入PAT单元数据
			//读取旧块上的一页数据
			FML_ReadOnePage(old_data_addr, buffer_page);
			//将数据写入新块
			rel = FML_ProgOnePage(data_addr, buffer_page);
			if ( rel == FML_FAILURE )
			{
				return FML_FAILURE;
			}
		}
	}
	FML_ProgOneWord( new_block_addr, BLOCK_IN_USE);
	FML_ProgOneWord( old_block_addr, BLOCK_INVALID);
	
	LogicBlock[block_id - 1] = new_block_addr;		//存储新块对应的物理块首地址
	memset(LogicPage[block_id - 1], 0xFF, MAX_LOGIC_PAGE_NUM);
	pat_addr = new_block_addr + BLOCK_INFO_SIZE;	//新块PAT起始地址

	//依次读取PAT中每个单元的管理信息作相应处理
	//因为是新整理的块,所以物理页最大可能为MAX_LOGIC_PAGE_NUM
	//FreePage[block_id - 1] = MAX_PHY_PAGE_NUM;		del by wjt 2005.11.14
	for ( phy_page_count = 0; phy_page_count < FreePage[block_id - 1]; 
								phy_page_count++)
	{
		page_info = *((volatile PAT_UNIT_INFO*)( ROM_BASE + pat_addr * 2));	//读取PAT单元信息			

		if ( page_info.page_sts == PAGE_USED )		//如果该页已使用
		{
			//存储物理块号到数组LogicPage中
			LogicPage[block_id - 1][page_info.page_lid - 1] = phy_page_count + 1;						
		}
		pat_addr++;
		#if 0	//del start by wjt 2005.11.14
		else //该页未使用
		{
			//如果该页为最小空闲物理页,则把物理页号存入数组FreePage
			if ( phy_page_count + 1 < FreePage[block_id - 1] )
			{
				FreePage[block_id - 1] = phy_page_count + 1;
				break;
			}
		}
		
		#endif
	}

	//擦除已废弃的旧块并把块首地址赋给数组FreeBlock的最后一项
	rel = FML_BlockErase(old_block_addr);
	if ( rel == FML_FAILURE )
	{
		return FML_FAILURE;
	}
	FreeBlock[MAX_FREE_BLOCK - 1] = old_block_addr;
									
	return FML_SUCCESS;
}


/************************************************************************/
/*	函数名:	FML_AllocNewPage										*/
/*	功能:		分配新的物理页并置为待写入状态							*/
/*	输入参数:	block_id -- 逻辑块号									*/
/*	输出参数:	*pat_addr -- 新页对应的pat单元地址						*/
/*				*page_addr -- 新页的页首物理地址						*/
/*	返回值:	操作返回FML_SUCCESS,否则返回FML_FAILURE				*/
/*																		*/
/************************************************************************/
static FML_RESULT FML_AllocNewPage(byte block_id, ulong *pat_addr, ulong *page_addr)
{	
	ulong temp_addr;
	word free_page_id;
	FML_RESULT rel;

	free_page_id = FreePage[block_id - 1];
	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];
	}
	FreePage[block_id - 1]++;				//最小空物理页地址增1

	//计算物理页管理信息地址
	temp_addr = LogicBlock[block_id - 1] + BLOCK_INFO_SIZE + (free_page_id - 1) ;
	//将新页对应的PAT单元的第一个字节置为00
	rel = FML_ProgOneWord(temp_addr, 0x00FF);		

	if ( rel == FML_SUCCESS )
	{
		*pat_addr = temp_addr;
		
		 *page_addr= LogicBlock[block_id - 1] + BLOCK_INFO_SIZE + 	PAT_SIZE + (free_page_id - 1) * PAGE_SIZE;
	}
	return rel;
}

word FML_SectorLock(void)
{
	word rel;
	int (*func)(ulong);
	func = (int(*)())FML_RAMLock;
	rel = func();
	//*sysAddress(0x0000) = 0x00FF;
	return rel;
}

word FML_BlockErase(ulong pwAddr)
{
	FML_RESULT rel;
	int (*func)(ulong);
	func = (int(*)())FML_RAMErase;
	rel = func(pwAddr);
	//if (rel == FML_FAILURE) *sysAddress(0x0000) = 0xFF;
	return rel;
}

word FML_ProgOneWord(ulong dst, word data)
{
	FML_RESULT rel;
	int (*func)(ulong, word);
	func = (int(*)())FML_RAMProg;
	rel = func(dst, data);
	if (rel == FML_FAILURE) *sysAddress(0x0000) = 0xFF;
	return rel;
}

#ifdef   __cplusplus
    }
#endif

⌨️ 快捷键说明

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