?? 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 + -