|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2011-2-14 11:34:54
|
显示全部楼层
内存整理程序也写好了,调试时检测无误。我的方法是划一块4K的空间作为缓冲区,然后从低到高按地址检测VSS属性值,有效则压入缓冲区中,缓冲区满则格式化已检测完的区域(多种情况)。有几个地方有些冗余,像缓冲区的SAT属性可不写,而且上面的程序为和文档中匹配,这时有几个变量值就传递有些麻烦。加个进度条显示整理速度,再加个饼图还能显示已用和剩余空间大小及碎片(无效VSS)大小,嘿嘿,想想都不错。
// 读取块号为Mem缓冲区的SAT
word *Read_MemSAT(void)
{
dword addr;
word psat[MAX_SI];
addr = MEMERY_ADDR + SAT_OFFSET;
Flash_Read(addr, (byte *)(&psat), SAT_SIZE);
return (word *)psat;
}
// 读取缓冲区分割号SatID缓冲区只有一个块大小
byte Get_MemVSS(void)
{
word *psat;
word sat;
byte i;
psat = Read_MemSAT();
for(i = 0; i < MAX_SI; i++)
{
sat = *psat++;
if(IsFree(sat)) // 是否使能
return i;
}
}
// 设置vss相应的SAT单元属性值std和VSS ID号
void MEM_SetSATStd(byte vss, byte sat, SAT_STD std)
{
dword addr;
word satval;
addr = VSS_START_ADDR + SAT_OFFSET + sat*2;
satval = (word)((std << 14) | vss); // SAT属性值及VSS ID号
Flash_Enable(addr);
Flash_Write(addr, (byte *)(&satval), 2);
Flash_Disable(addr);
}
// 内存整理函数
void Memery_Releaze(void)
{
byte buf[SECTOR_SIZE]; //
dword addr;
word *psat;
word sat;
byte i, j;
byte vss;
byte memsat;
byte memvss;
byte cnt = 0; // 转入缓冲区的VSS数
byte renew = 0; // 已更新的块数
Flash_Enable(MEMERY_ADDR);
Flash_ErasePage(MEMERY_ADDR);
Flash_Disable(MEMERY_ADDR);
for(i = 0; i < MAX_BLOCK; i++)
{
Cpu_Delay100US(800);
psat = ReadSat(i);
for(j = 0; j < MAX_SI; j++)
{
sat = *psat++;
if(IsValid(sat)) // 是否有效
{
vss = (byte)(sat & (~VSS_MASK));
memsat = Get_MemVSS();
addr = Get_VSSAddr(vss);
memset(buf, 0xFF, sizeof(buf));
Flash_Read(addr, buf, SECTOR_SIZE);
addr = MEMERY_ADDR + memsat*SECTOR_SIZE; // 对应VSS ID的物理地址
//Flash_Enable(addr);
//Flash_Write(addr, buf, SECTOR_SIZE);
//Flash_Disable(addr);
MEM_SetSATStd(vss, memsat, VSS_Valid); // 更改缓冲区中属性
Cpu_Delay100US(100);
SAT_SetState(vss, VSS_Invalid); // 同时修改原SAT属性为无效
Cpu_Delay100US(100);
if(++cnt == MAX_SI) // 如果缓冲区满则检测各块VSS使用情况
{
cnt = 0;
addr = VSS_START_ADDR + (renew << 14); // 格式化已检测完的块并重新写入整理后VSS数据
Flash_Enable(addr);
Flash_ErasePage(addr);
Flash_Disable(addr);
for(memvss = 0; memvss < MAX_SI; memvss++) // 将缓冲区中VSS更新至更新块中
{
addr = MEMERY_ADDR + memvss*SAT_SIZE; // 对应VSS ID的物理地址
Flash_Read(addr, buf, SECTOR_SIZE);
addr = VSS_START_ADDR + (renew << 14) + memvss*SECTOR_SIZE;
Flash_Enable(addr); // 数据写入更新块中
Flash_Write(addr, buf, SAT_SIZE);
Flash_Disable(addr);
Cpu_Delay100US(100);
BlockID = renew;
SatID = memvss;
SAT_SetState(vss, VSS_Valid); // 修改SAT属性为有效
}
renew++; // 更新块数+1
}
}
}
}
if(cnt != 0) // 不满一整块的VSS整理后写入
{
addr = VSS_START_ADDR + (renew << 14); // 格式化已检测完的块并重新写入整理后VSS数据
Flash_Enable(addr);
Flash_ErasePage(addr);
Flash_Disable(addr);
for(memvss = 0; memvss < cnt; memvss++) // 将缓冲区中VSS更新至更新块中
{
addr = MEMERY_ADDR + memvss*SAT_SIZE; // 对应VSS ID的物理地址
Flash_Read(addr, buf, SECTOR_SIZE);
addr = VSS_START_ADDR + (renew << 14) + memvss*SECTOR_SIZE;
Flash_Enable(addr); // 数据写入更新块中
Flash_Write(addr, buf, SAT_SIZE);
Flash_Disable(addr);
Cpu_Delay100US(100);
BlockID = renew;
SatID = memvss;
SAT_SetState(vss, VSS_Valid); // 修改SAT属性为有效
}
}
for(i = 0; i < MAX_BLOCK; i++)
{
cnt = 0; // 作为无效VSS计数
Cpu_Delay100US(800);
EnterCritical();
psat = ReadSat(i);
ExitCritical();
for(j = 0; j < MAX_SI; j++)
{
sat = *psat++;
if(IsInvalid(sat)) // 是否无效
cnt++;
}
if(cnt == MAX_SI) // 如果该块全为无效则格式化该扇区
{ // 也可以设定成本块内无效数大于某一值就格式化 此时有效VSS都已压入缓冲区
// 而且reney始终小于等于当前检测块号 不担心误删有效数据
addr = VSS_START_ADDR + (i << 14);
Flash_Enable(addr);
Flash_ErasePage(addr);
Flash_Disable(addr);
}
}
memset(VSS_Table, 0x00, sizeof(VSS_Table)); // 更新VSS_Table表
for(i = 0; i < MAX_BLOCK; i++)
Scan_SAT(i);
//VSS_Table[BlockID] &= ~(1 << SatID); // 更新VSS_Table表
} |
|