📄 ddr.c
字号:
u32_temp = DBX_flash_tag->DDR_DBL[temp];
if(u32_temp == old_block_no)
{
DBX_flash_tag->DDR_DBL[temp] = new_block_no;
break;
}
}
//计算DBL表被修改的位置处在DDR表中是第几块
temp= temp*4 / chip->block_size;
//DDR_main中标记该块为未写入
DBX_flash_tag->writed_DDR_main[temp] = false;
}break;
case cn_DDR_bak_block : //原old_block_no块是DDR_bak块
{
//new_block_no设置为DDR_main块
MAT_item[new_block_no].attr = cn_DDR_bak_block;
DDR_blocks = (DBX_flash_tag->DDR_size + chip->block_size -1)
/ chip->block_size; //计算DDR表所占的块数
for(temp = 0; temp < DDR_blocks; temp++)
{
u32_temp = DBX_flash_tag->DDR_DBL[DDR_blocks + temp];
if(u32_temp == old_block_no)
DBX_flash_tag->DDR_DBL[DDR_blocks + temp] = new_block_no;
}
//计算DDR表被修改的位置处在DDR表中是第几块
temp= (DDR_blocks+ temp)*4 / chip->block_size;
//DDR_main中标记该块为未写入
DBX_flash_tag->writed_DDR_bak[temp] = false;
}break;
case cn_PCRB_block : //原old_block_no块是掉电恢复块,再说吧
{
}break;
default : break;
}
//如果原old_block_no是某文件的首块,还要修改fdt(目录)表中该文件对应的条目
//如果原old_block_no是fdt表的首块,还要修改DDR表中的FDSB
}
//----磨损平衡表轮转-----------------------------------------------------------
//功能:busy_region[0]和free_region[0]均空的时候,磨损平衡表便轮转一圈,使
// busy_region[8]和free_region[8]变成空的。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//返回:无
//-----------------------------------------------------------------------------
void __DFFSD_whirl_ART_table(struct st_DBX_flash_tag *DBX_flash_tag)
{
struct flash_chip *chip = DBX_flash_tag->chip;
uint32_t *busy_region,*free_region,*balance_region;
uint32_t loop,ARB_block;
uint16_t whirl_regions;
uint16_t *times_tab;
times_tab = DBX_flash_tag->ART_times; //取磨损次数表
busy_region = &DBX_flash_tag->balance_region[9]; //第一个忙分区
free_region = DBX_flash_tag->balance_region; //第一个空闲分区
balance_region = DBX_flash_tag->balance_region;
for(whirl_regions = 0; whirl_regions < 8; whirl_regions++)
{//检查需轮转的区的数量,即从busy和free的0区开始,检查free和busy同时为空的
//区的数量,直到第一个不同时为空的区为止。
if((busy_region[whirl_regions] != busy_region[whirl_regions+1])
|| (free_region[whirl_regions] != free_region[whirl_regions+1]))
break;
}
if(whirl_regions == 0)
return;
DBX_flash_tag->DDR_ARB += whirl_regions * 128;//磨损次数基数增加轮转区数
//计算DDR_ARB在MAT表中位置处在DDR表中是第几块
ARB_block = (DBX_flash_tag->DDR_size + chip->block_size -1)
/ chip->block_size * 4 + 4;
ARB_block = ARB_block / chip->block_size;
//DDR_bak中标记该块为未写入
DBX_flash_tag->writed_DDR_bak[ARB_block] = false;
//DDR_main中标记该块为未写入
DBX_flash_tag->writed_DDR_main[ARB_block] = false;
for(loop = 0; loop < balance_region[18]; loop++)
{
times_tab[loop] -= whirl_regions*128; //所有块的磨损次数减少轮转区数
}
for(loop = 1; loop <= 9 - whirl_regions; loop++)
{
busy_region[loop] = busy_region[loop+whirl_regions];
free_region[loop] = free_region[loop+whirl_regions];
}
for(; loop < 9; loop++)
{
busy_region[loop] = balance_region[18];
free_region[loop] = busy_region[0];
}
}
//----磨损次数加1--------------------------------------------------------------
//功能: 当某块的磨损次数增加时,调用本函数,把这种变化登记到内存中磨损平衡表中,
// 但并不写入到flash。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
// block_no,被增加次数的块
//返回: 无
//----------------------------------------------------------------------------
void __DFFSD_inc_abrasion_times(struct st_DBX_flash_tag *DBX_flash_tag,
uint32_t block_no)
{
uint32_t temp,block_position;
uint32_t *pos_tab;
uint16_t *times_tab;
uint32_t *busy_region,*free_region;
uint16_t block_times;
pos_tab = DBX_flash_tag->ART_position; //取磨损位置表
times_tab = DBX_flash_tag->ART_times; //取磨损次数表
//取目标块在磨损块号表(次数表)中的位置
block_position = pos_tab[block_no];
times_tab[block_position]++; //目标块的磨损次数增量
block_times = times_tab[block_position]; //取目标块的磨损次数
if((block_times % 128 != 0)||(block_times >= 1024))
{
return; //增加次数后不跨区,直接返回。
}
//下面处理需要跨区的情况,block_no块要放到磨损次数高一区
busy_region = &DBX_flash_tag->balance_region[9]; //第一个忙分区
temp = block_times/128 - 1; //取block_no块所在的磨损分区
//看block_no是忙块还是闲块,只有忙块才会增加次数,这个判断只是容错而已
if(block_position >= busy_region[0])
temp += 9; //block_no是忙块,跳过9个闲区
__DFFSD_ART_flip(DBX_flash_tag,temp,temp+1,block_position);
busy_region = &DBX_flash_tag->balance_region[9]; //第一个忙分区
free_region = DBX_flash_tag->balance_region; //第一个空闲分区
if((busy_region[0] == busy_region[1]) &&(free_region[0] == free_region[1]))
//当出现free[0]和busy[0]同时空的情况,磨损表就轮转一圈
__DFFSD_whirl_ART_table(DBX_flash_tag);
}
//----登记一个坏块-------------------------------------------------------------
//功能:把一个坏块登记到内存中的磨损平衡表中,本函数只修改内存中的擦除平衡表,
// 并不写入flash,用户须确保调用本函数后,在适当的时间写入flash。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
// block_no,坏块块号
//返回:无
//-----------------------------------------------------------------------------
void __DFFSD_register_invalid(struct st_DBX_flash_tag *DBX_flash_tag,
uint32_t block_no)
{
struct flash_chip *chip = DBX_flash_tag->chip; //取得文件柜所属芯片
uint32_t loop,block_position,block_no_temp;
uint32_t *pos_tab,*block_no_tab;
uint16_t *times_tab;
uint32_t *balance_region,*busy_region;
uint16_t block_times;
pos_tab = DBX_flash_tag->ART_position; //取磨损位置表
block_no_tab = DBX_flash_tag->ART_block_no; //取磨损块号表,与次数表同列
times_tab = DBX_flash_tag->ART_times; //取磨损次数表
balance_region = DBX_flash_tag->balance_region; //磨损分区表首址
busy_region = &DBX_flash_tag->balance_region[9]; //第一个忙分区
//取坏块在磨损块号表(次数表)中的位置
block_position = pos_tab[block_no];
block_times = times_tab[block_position]; //暂存坏块的磨损次数
loop = block_times/128 +1; //取坏块的磨损分区的下一分区号
//看坏块原是忙块还是闲块,由于总是先分配再使用,坏块总是在使用中产生,使用
//中的块肯定是忙块,故一般不会有闲块变成坏块的情况,容一下错吧
if(block_position >= busy_region[0])
loop += 9; //坏块是忙块,跳过9个区
for(; loop < 19; loop++) //遍历所有磨损分区表,把坏块从原分区转移到坏块分区
{
balance_region[loop] -= 1; //分区指针上移一格
if(balance_region[loop] == balance_region[loop-1])
{//相连的两分区指针重叠,说明第i-1分区是空的。
balance_region[loop]--;
continue; //无需搬动块,进行下一轮比较。
}
//取第i分区的第一个单元的块号(即在pos表中的偏移量)
block_no_temp = block_no_tab[balance_region[loop]];
//第i分区第一个单元的磨损次数copy到上次循环移空的单元
times_tab[block_position] = times_tab[balance_region[loop]];
//第i分区第一个单元的块号copy到上次循环移空的单元
block_no_tab[block_position] = block_no_temp;
//第i分区第一个单元的位置表指向目标单元号
pos_tab[block_no_temp] = block_position;
block_position = balance_region[loop]; //本次清空的单元索引号
}
//坏块的擦除次数copy到坏块分区的首单元
times_tab[block_position] = block_times;
//坏块块号放到坏块分区首单元的ART_block_no表中
block_no_tab[block_position] = block_no;
//pos表的坏块指针指向坏块分区首单元
pos_tab[block_no] = block_position;
//设置block_no块为坏块
DBX_flash_tag->DDR_MAT[block_no].attr = cn_invalid_block;
//计算block_new在MAT表中位置处在DDR表中是第几块
loop =(__DFFSD_MAT_start(DBX_flash_tag)+block_no*4*2) / chip->block_size;
DBX_flash_tag->writed_DDR_bak[loop] = false; //DDR_bak中标记该块为未写入
//DDR_main中标记该块为未写入
DBX_flash_tag->writed_DDR_main[loop] = false;
}
//----释放一块到free表--------------------------------------------------------
//功能: 把一块从busy表转移到free表。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
// block_no,释放的块号
//返回:无
//----------------------------------------------------------------------------
void __DFFSD_free_block(struct st_DBX_flash_tag *DBX_flash_tag,
uint32_t block_no)
{
uint32_t block_position;
uint32_t *pos_tab;
uint32_t target_region;
pos_tab = DBX_flash_tag->ART_position;
block_position = pos_tab[block_no];
//与第一个忙分区首块比较
if(block_position < DBX_flash_tag->balance_region[9])
return; //被释放块本来就是闲块,无需释放
else
DBX_flash_tag->free_sum++;
//被释放块的区号。
target_region = DBX_flash_tag->ART_times[block_position]/128;
//把目标块移到空闲区
__DFFSD_ART_flip(DBX_flash_tag,target_region+9,target_region,block_position);
//只把块属性改为空闲,不修改链表,最大限度保留数据恢复的可能。
DBX_flash_tag->DDR_MAT[block_no].attr = cn_free_block;
}
//----交换条目-----------------------------------------------------------------
//功能: 交换两个ART条目。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
// pos1,DBX_flash_tag->ART_block_no表的条目号
// pos2,DBX_flash_tag->ART_block_no表的另一个条目号
//返回: 无
//-----------------------------------------------------------------------------
void __DFFSD_exchange_ART_item(struct st_DBX_flash_tag *DBX_flash_tag,
uint32_t pos1,uint32_t pos2)
{
uint32_t block_no1,block_no2;
uint16_t ART_times;
block_no1 = DBX_flash_tag->ART_block_no[pos1];
block_no2 = DBX_flash_tag->ART_block_no[pos2];
DBX_flash_tag->ART_block_no[pos1] = block_no2;
DBX_flash_tag->ART_block_no[pos2] = block_no1;
DBX_flash_tag->ART_position[block_no1] = pos2;
DBX_flash_tag->ART_position[block_no2] = pos1;
ART_times = DBX_flash_tag->ART_times[pos1];
DBX_flash_tag->ART_times[pos1] = DBX_flash_tag->ART_times[pos2];
DBX_flash_tag->ART_times[pos2] = ART_times;
}
//----磨损块号表排序-----------------------------------------------------------
//功能: 把从flash芯片中读出的未排序的ART表在内存中排序,把排序结果写到
// DBX_flash_tag的三个表:ART_position,ART_block_no和ART_times中。
// 在执行前,前磨损表是按块号排序的
// 排序后的块号表:
// 磨损次数 0~127的空闲块起始位置----free_region[0],balance_region[0]
// 磨损次数 0~127的空闲块结束位置
// 磨损次数 128~255的空闲块起始位置----free_region[1],balance_region[1]
// 磨损次数 128~255的空闲块结束位置
// 磨损次数 256~383的空闲块起始位置----free_region[2],balance_region[2]
// 磨损次数 256~383的空闲块结束位置
// 磨损次数 38
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -