📄 flashfile.c
字号:
//的FDT还没有改变。
if(result_block == cn_limit_uint32) //分配失败(无空闲块)
{
return cn_limit_uint32; //返回错误
}
}else //成功写入
{
break;
}
}while(fail_counter <= 10); //以连续遇到10个坏块为异常退出条件
if(fail_counter > 10) //因10次坏块而结束do-while循环
return cn_limit_uint32;
else //数据已经正确写入
return result_block;
}
//----把数据写入新块-----------------------------------------------------------
//功能: 把芯片的块缓冲区的内容写入到一个尚无有效数据的新块中,因写入前块内并无
// 有效数据,故无需动用掉电恢复块,如果在写入时遇到坏块,申请一个新块替换
// 之,并把坏块登记到MAT表中(并不把MAT写入到flash中),返回替换后的块号。
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
// block_no,目标块号
// offset,起始地址在块内的偏移量
// size,写入缓冲区长度
//返回: 写入成功则返回实际写入的块号,
// 写入失败返回cn_limit_uint32,空间不足或者连续遇到10个坏块会导致失败
//-----------------------------------------------------------------------------
uint32_t __DFFSD_write_new_block(struct st_DBX_flash_tag *DBX_flash_tag,
uint32_t block_no,uint32_t offset,uint32_t size)
{
uint32_t fail_counter; //如果连续分配10块均不能正确写入,则返回
uint32_t write_result,result_block,DBX_start_block;
struct flash_chip *chip = DBX_flash_tag->chip;
fail_counter = 0;
DBX_start_block = DBX_flash_tag->start_block;
result_block = block_no;
do //因写入过程可能产生坏块,故需要用循环,直到正确写入才退出
{
//查看是否需要擦除
if(!chip->query_block_ready_with_ecc(
result_block+DBX_start_block,
offset,chip->block_buf+offset,size))
{//需要擦除
//擦除目标块
chip->erase_block(result_block + DBX_start_block);
//把数据写入目标块中
write_result = chip->write_data_with_ecc(
result_block+DBX_start_block,
offset,chip->block_buf+offset,size);
}else //不需要擦除,新申请的块刚好是一个已经被擦除的块。
{
//直接把数据写入到目标块中
write_result = chip->write_data_with_ecc(
result_block + DBX_start_block,
offset,chip->block_buf+offset,size);
}
if(write_result != size) //写入失败
{
fail_counter++; //写入失败次数增量
__DFFSD_register_invalid(DBX_flash_tag,result_block); //登记坏块
//分配新块,必须使用简易分配法,否则容易造成连环套
result_block = __DFFSD_allocate_block_simple(DBX_flash_tag);
if(result_block == cn_limit_uint32) //分配失败(无空闲块)
{
return cn_limit_uint32; //返回错误
}
}else //成功写入
{
//当然了,擦写一次,目标块的磨损次数就加1
//即使无需擦除,这也是新申请的一块的第一次写入,磨损次数自然也要加1
__DFFSD_inc_abrasion_times(DBX_flash_tag,result_block);
break;
}
}while(fail_counter <= 10); //以连续遇到10个坏块为异常退出条件
if(fail_counter > 10) //因10次坏块而结束do-while循环
return cn_limit_uint32;
else //数据已经正确写入
return result_block;
}
//----移动文件读指针-----------------------------------------------------------
//功能: 把一个文件的读指针移动到一个新位置
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
// fp,目标文件指针
// new_ptr,新的读指针
//返回: true=成功,false=有错误
//-----------------------------------------------------------------------------
bool_t __DFFSD_move_file_read_ptr(struct st_DBX_flash_tag *DBX_flash_tag,
djyfs_file *fp,sint64_t new_ptr)
{
if(new_ptr > fp->file_size)
return false;
switch (fp->open_mode)
{
case enum_r_rb:
{
fp->read_ptr = new_ptr; //读位置
}break;
case enum_w_wb:
{
return false; //读位置无效
}break;
case enum_a_ab:
{
return false; //读位置无效
}break;
case enum_r_rb_plus:
{
fp->read_ptr = new_ptr; //读位置
fp->write_ptr = new_ptr; //写位置
}break;
case enum_w_wb_plus:
{
fp->read_ptr = new_ptr; //读位置
fp->write_ptr = new_ptr; //写位置
}break;
case enum_a_ab_plus:
{
fp->read_ptr = new_ptr; //读位置
}break;
default: return false;
}
return true;
}
//----移动文件写指针-----------------------------------------------------------
//功能: 把一个文件的写指针移动到一个新位置
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
// fp,目标文件指针
// new_ptr,新的写指针
//返回: true=成功,false=有错误
//-----------------------------------------------------------------------------
bool_t __DFFSD_move_file_write_ptr(struct st_DBX_flash_tag *DBX_flash_tag,
djyfs_file *fp,sint64_t new_ptr)
{
switch (fp->open_mode)
{
case enum_r_rb:
{
return false; //只读文件,写位置无效
}break;
case enum_w_wb:
{
fp->write_ptr = new_ptr; //写位置
}break;
case enum_a_ab:
{
fp->write_ptr = new_ptr; //写位置
}break;
case enum_r_rb_plus:
{
fp->read_ptr = new_ptr; //读位置
fp->write_ptr = new_ptr; //写位置
}break;
case enum_w_wb_plus:
{
fp->read_ptr = new_ptr; //读位置
fp->write_ptr = new_ptr; //写位置
}break;
case enum_a_ab_plus:
{
fp->write_ptr = new_ptr; //写位置
}break;
default: return false;
}
if(new_ptr > fp->file_size) //写指针超出文件长度
{
//在FDT表中修改文件长度
__DFFSD_update_FDT_file_size(DBX_flash_tag,fp,fp->write_ptr);
fp->file_size = fp->write_ptr; //用写指针覆盖文件长度
}
return true;
}
//----写缓冲区写入flash--------------------------------------------------------
//功能: 把文件写缓冲区的数据写入flash中
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
// fp,被操作的文件指针
//返回:实际写入flash的字节数
//-----------------------------------------------------------------------------
uint32_t __DFFSD_write_buf_to_flash(struct st_DBX_flash_tag *DBX_flash_tag,
struct file_rsc *fp)
{
struct flash_chip *chip;
struct file_access_tag access_tag;
sint64_t wr_point;
uint32_t completed = 0,write_len;
uint32_t offset_start;
uint32_t block_no,start_block,end_block,loop;
uint32_t true_block,last_block;
uint32_t buffed_data; //文件写缓冲区中的数据量和剩余数据量
chip = DBX_flash_tag->chip; //取文件柜(文件)所属芯片
if(fp->p_write_buf != NULL)
{
buffed_data = ring_check(fp->p_write_buf); //检查写缓冲区中的数据量
if(buffed_data == 0) //写缓冲区没有数据
return 0;
}else
return 0; //没有写缓冲区
wr_point = fp->write_ptr-buffed_data; //计算开始写入数据的位置
//计算起始写位置处于文件内第几块
start_block = wr_point /chip->block_size;
offset_start = wr_point % chip->block_size; //计算起始偏移
//计算终止读写位置处于文件内第几块
end_block = (fp->write_ptr - 1)/chip->block_size;
__DFFSD_get_access_info(DBX_flash_tag,fp,&access_tag);
//定位写入点的块号,文件柜内的相对块号。
block_no = access_tag.write_block_no;
last_block = access_tag.last_block_no;
for(loop = start_block; loop <= end_block; loop++)
{
if((wr_point >= access_tag.true_size) && (wr_point != 0))
{
//分配一个新块
block_no = __DFFSD_allocate_block(DBX_flash_tag);
if(block_no == cn_limit_uint32) //分配失败(无空闲块)
break;
}
//计算本次写入的数据长度
if(buffed_data - completed > chip->block_size - offset_start)
write_len = chip->block_size - offset_start;
else
write_len = buffed_data - completed;
ring_read(fp->p_write_buf,chip->block_buf+offset_start,write_len);
if(wr_point >= access_tag.true_size) //追加数据
{
if(offset_start == 0) //待写入的块内尚无有效数据
{
//写入目标块
true_block = __DFFSD_write_new_block(DBX_flash_tag,block_no,
0,write_len);
if(true_block != cn_limit_uint32) //正确写入
{
if(wr_point != 0)
__DFFSD_add_MAT_item(DBX_flash_tag,last_block,true_block);
}else //写入错误
break;
}else //虽是追加,但待写入的块已经有部分有效数据
{
//写入目标块
true_block = __DFFSD_write_append_block(DBX_flash_tag,block_no,
offset_start,write_len);
if(true_block != cn_limit_uint32)
{//正确写入
if(true_block != block_no) //写入时发生了块替换
__DFFSD_update_MAT_item(DBX_flash_tag,block_no,true_block);
}else //写入错误
break;
}
last_block = true_block;
access_tag.true_size += write_len;
chip->erase_block(DBX_flash_tag->PCRB_no
+ DBX_flash_tag->start_block);
}else //在文件的中间写入,若需擦除就需要使用PCRB块进行保护
{
//写入目标块
true_block = __DFFSD_write_update_block(DBX_flash_tag,block_no,
offset_start,write_len);
if(true_block != cn_limit_uint32) //正确写入
{
if(true_block != block_no) //写入时发生了块替换
__DFFSD_update_MAT_item(DBX_flash_tag,block_no,true_block);
}else //写入错误
break;
//确定下一循环写入点的块号,文件柜内的相对块号。
block_no = DBX_flash_tag->DDR_MAT[block_no].next;
chip->erase_block(DBX_flash_tag->PCRB_no
+ DBX_flash_tag->start_block);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -