📄 ddfrom.c
字号:
/****************************************************************************/
/* 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 + -