📄 ddr.c
字号:
block_no_tab[busy_region[loop]] = block_no;
pos_tab[block_no] = busy_region[loop];
}
busy_region[8]--; //busy_region8指针指向原busy7.end的位置
//下面把free8.invalid_num块copy到busy_region8.0的位置
times_tab[busy_region[8]] = times_tab[free_region[8] + invalid_num]+1;
block_no = block_no_tab[free_region[8] + invalid_num];
block_no_tab[busy_region[8]] = block_no;
pos_tab[block_no] = busy_region[8];
//下面把保存的原busy0.end的信息copy到free8.invalid_num块
times_tab[free_region[8] + invalid_num] = times_bak;
block_no_tab[free_region[8]+invalid_num] = block_no_bak;
pos_tab[block_no_bak] = free_region[8]+invalid_num;
//下面根据块交换结果修改MAT表,block_no_bak保存的是原busy0.end的块号,
//block_no保存的是该块被交换到的目标块号。
__DFFSD_update_MAT_item(DBX_flash_tag,block_no_bak,block_no);
}
for(loop = 0; loop < invalid_num; loop++)//本循环把所有坏块转移到invalid_region
{
block_no = block_no_tab[free_region[8]+loop];
__DFFSD_register_invalid(DBX_flash_tag,block_no);
}
return true;
}
//----简单分配一块------------------------------------------------------------
//功能: 与__allocate_block函数类似,但是不做任何块交换,而是直接从free[0]区取出
// 一块。如果free[0]空,则实际取到的可能是free[1]或更高区的块
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//返回: 块号,是文件柜的相对块号,若没有空闲块,返回-1
//----------------------------------------------------------------------------
uint32_t __DFFSD_allocate_block_simple(struct st_DBX_flash_tag *DBX_flash_tag)
{
uint32_t block_no;
uint32_t *block_no_tab;
uint16_t *times_tab,times_bak;
uint32_t *free_region;
uint32_t target_region;
if(DBX_flash_tag->free_sum== 0)
return cn_limit_uint32;
else
DBX_flash_tag->free_sum--;
block_no_tab = DBX_flash_tag->ART_block_no; //取磨损块号表,与次数表同列
times_tab = DBX_flash_tag->ART_times; //取磨损次数表
free_region = DBX_flash_tag->balance_region; //第一个空闲分区
times_bak =times_tab[0]; //读取free表0区第一块磨损次数
//该块变成忙块后插入相应忙区,由于free[0]开始可能会有若干个空闲区,故不
//能简单地认为free[0]区取出的块不改变磨损次数会出现在busy[0]区
target_region = times_bak/128 + 9; //取忙区的目标区号
//读取free表0区第一块块号
block_no = block_no_tab[0];
//从第0区的位置0跳到第target_region区
__DFFSD_ART_flip(DBX_flash_tag,0,target_region,0);
return block_no;
}
//----分配一块----------------------------------------------------------------
//功能: 从free表中取出一块,并把该块放到busy表中。目标块的磨损次数不增量。如果:
// 1.空闲块全部集中在free_region[8]区,且busy_region[0]非空,就要进行坏块
// 磨损平衡替换。从busy_region[0]中取一块A,再从free_region[8]中取一块B,
// A块的内容copy到B块,把B块放到busy_region[8]中。注意这个过程要涉及到
// 修改MAT表。
// 2.如果同时出现busy_region[0]和free_region[0]均空的现象,磨损表整体轮转
// 一圈,使busy_region[8]和free_region[8]均空。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//返回: 块号,是文件柜的相对块号,若没有空闲块,返回-1
//----------------------------------------------------------------------------
uint32_t __DFFSD_allocate_block(struct st_DBX_flash_tag *DBX_flash_tag)
{
uint32_t block_no;
uint32_t *block_no_tab;
uint16_t *times_tab,times_bak;
uint32_t *free_region;
uint32_t target_region;
if(DBX_flash_tag->free_sum== 0)
return cn_limit_uint32;
else
DBX_flash_tag->free_sum--;
block_no_tab = DBX_flash_tag->ART_block_no; //取磨损块号表,与次数表同列
times_tab = DBX_flash_tag->ART_times; //取磨损次数表
free_region = DBX_flash_tag->balance_region; //第一个空闲分区
if(free_region[0] == free_region[8]) //free[0~7]已经空
__DFFSD_exchange_busy0_free8(DBX_flash_tag); //调用写磨损平衡块交换函数
times_bak =times_tab[0];//读取free表0区第一块磨损次数
// times_bak++; //磨损次数加1,注释掉,改为实际发生擦写时再增加。
//该块变成忙块后插入end_region区,由于free[0]开始可能会有若干个空闲区,故不
//能简单地认为free[0]区取出的块不改变磨损次数会出现在busy[0]区
target_region = times_bak/128 + 9;
//读取free表0区第一块块号
block_no = block_no_tab[0];
//从第0区的位置0跳到第target_region区
__DFFSD_ART_flip(DBX_flash_tag,0,target_region,0);
return block_no;
}
//----写DDR表到flash-----------------------------------------------------------
//功能: 根据DBX_flash_tag->writed_main表中的内容,把DDR表中需要写入的内容写
// 入到flash中DDR_main表中。
// 1.把DDR表写入到flash中,存储位置由DBL_main提供
// 2.如果产生坏块,则申请新块,并在DBL_main、MAT_main、MAT_bak中标记。
// 3.如果产生坏块,MAT_bak和MAT_main的内容都有修改,但只有which参数指定的
// 那个MAT表修改后的内容会在本次写入flash,而另一份在__DFFSD_write_DDR函
// 数中再次调用本函数完成写入
// 4.为简化算法,即使发生坏块替换,也不修改磨损次数,只在mat表中把标示坏块,把
// 新块标示为DDR块.这样,发生坏块替换时,只需要修改MAT表和DBL表就可以了.由于
// 模式次数无需精确平衡,这样做是允许的。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
// which,读取哪一个DDR表,0=DDR_main,1=DDR_bak
//返回: true=成功写入
// false=失败,当写入遇到坏块,又没有空闲块可供分配时,会失败
//特注: 用循环写入,
//----------------------------------------------------------------------------
bool_t __DFFSD_write_DDR_exe(struct st_DBX_flash_tag *DBX_flash_tag,
ufast_t which)
{
struct flash_chip *chip; //芯片指针
uint32_t loop,DDR_blocks,DDR_no,write_result;
uint32_t write_len,completed = 0;
uint32_t block_no,block_new,temp;
bool_t *writed; //指向是否完成写入的指针
bool_t finished;
struct MAT_table *MAT_item;
uint32_t *DBL_buf;
uint8_t *buf;
uint32_t FDSB_start,ARB_start,ART_start,ART_end,MAT_start,offset;
uint8_t block_attr;
chip = DBX_flash_tag->chip; //取得文件柜所属芯片
buf = chip->block_buf;
//1份DDR表占用的块数,
DDR_blocks = (DBX_flash_tag->DDR_size+chip->block_size-1)/chip->block_size;
if(which == 0)
{
writed = DBX_flash_tag->writed_DDR_main;
block_attr = cn_DDR_main_block;
DBL_buf = DBX_flash_tag->DDR_DBL;
}else
{
writed = DBX_flash_tag->writed_DDR_bak;
block_attr = cn_DDR_bak_block;
DBL_buf = DBX_flash_tag->DDR_DBL + DDR_blocks;
}
MAT_item = DBX_flash_tag->DDR_MAT;
FDSB_start = DDR_blocks*4;
ARB_start = FDSB_start + 4;
ART_start = ARB_start +4;
ART_end = ART_start + DBX_flash_tag->block_sum *2;
MAT_start = __DFFSD_MAT_start(DBX_flash_tag);
do
{
finished = true; //假定本循环可以完成全部写入操作
for(loop = 0; loop < DDR_blocks; loop++)
{
if(writed[loop] == true)
{
continue; //本块已经写入,跳过。
}
completed = loop * chip->block_size;
offset = completed;
if(loop == DDR_blocks-1)
write_len = DBX_flash_tag->DDR_size - completed;
else
write_len = chip->block_size;
while(offset - completed < write_len)
{
if(offset < FDSB_start) //DBL
{
__fill_little_32bit(buf+(offset-completed),0,
DBL_buf[offset/4]);
offset +=4;
}else if(offset < ARB_start) //FDSB
{
__fill_little_32bit(buf+(offset-completed),0,
DBX_flash_tag->DDR_FDSB);
offset +=4;
}else if(offset < ART_start) //ARB
{
__fill_little_32bit(buf+(offset-completed),0,
DBX_flash_tag->DDR_ARB);
offset +=4;
}else if(offset < ART_end) //ART
{
__fill_little_16bit(buf+(offset-completed),0,
DBX_flash_tag->ART_times[(offset-ART_start)/2]);
offset +=2;
}else if(offset < MAT_start) //跳过对齐填充
{
offset = MAT_start;
}else if(offset <= DBX_flash_tag->DDR_size)
{
temp = MAT_item->previous & 0x3fffffff;
temp += (uint32_t)MAT_item->attr<<30;
//向前指针
__fill_little_32bit(buf+(offset-completed),0,temp);
temp = MAT_item->next & 0x3fffffff;
temp += (uint32_t)MAT_item->attr>>2<<30;
//向后指针
__fill_little_32bit(buf+(offset-completed),1,temp);
MAT_item++;
offset +=8;
}
}
block_no = DBL_buf[loop];
//擦除目标块
chip->erase_block(block_no + DBX_flash_tag->start_block);
write_result = chip->write_data_with_ecc(
block_no + DBX_flash_tag->start_block,
0,chip->block_buf,write_len); //块写入
if( write_result == write_len) //检测是否正确写入
{
__DFFSD_inc_abrasion_times(DBX_flash_tag,block_no);
writed[loop] = true; //正确写入则标记本块已经写入
}else
{//写入错误,产生了坏块,做下列处理:---db,此处未调试
//block_no是新产生坏块的块号,block_new是替换坏块的好块块号
block_new = __DFFSD_allocate_block(DBX_flash_tag);
if(block_new == cn_limit_uint32)
return false; //文件柜满,这种情况不多见
writed[loop] = false; //标记第loop块未写入
finished = false; //本循环没有完成写入
//把坏块登记到擦除平衡表中,但没有写入到flash
__DFFSD_register_invalid(DBX_flash_tag,block_no);
//坏块在DBL中的位置,被新块块号覆盖
DBL_buf[loop] = block_new;
//计算DBL中存放block_new的位置在DDR表中的块号
DDR_no = 4 * loop/chip->block_size;
writed[DDR_no] = false;
//更新MAT表中block_new块的属性
MAT_item[block_new].attr = block_attr;
//计算block_new在MAT表中位置处在DDR表中是第几块
DDR_no = (MAT_start+block_new*8) / chip->block_size;
//DDR_main中标记该块为未写入
DBX_flash_tag->writed_DDR_main[DDR_no] = false;
//DDR_bak中标记该块为未写入
DBX_flash_tag->writed_DDR_bak[DDR_no] = false;
//该MAT表中block_no块的属性为坏块
MAT_item[block_no].attr = cn_invalid_block;
//计算block_no在MAT表中位置处在DDR表中是第几块
DDR_no=(MAT_start+block_no*8) / chip->block_size;
//DDR_main中标记该块为未写入
DBX_flash_tag->writed_DDR_main[DDR_no] = false;
//DDR_bak中标记该块为未写入
DBX_flash_tag->writed_DDR_bak[DDR_no] = false;
}
}
}while(finished == false);
return true;
}
//----写一个文件柜的DDR表-----------------------------------------------------
//功能:将buf缓冲区中的DDR表写入指定文件柜的DDR区
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//返回:true=成功执行,false=写入错误
//---------------------------------------------------------------------------
bool_t __DFFSD_write_DDR(struct st_DBX_flash_tag *DBX_flash_tag)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -