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