📄 flashfile.c
字号:
completed += write_len;
wr_point += write_len;
offset_start = 0; //第二块开始,起始偏移地址肯定是0
}
__DFFSD_write_DDR(DBX_flash_tag);//把DDR表的变化写入flash中(DDR表可能没变化)
return completed;
}
//----读操作前同步文件缓冲区---------------------------------------------------
//功能: 执行文件写操作之前,调用本函数同步缓冲区。
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
// fp,目标文件指针
// read_len,欲读取长度
//返回: true=成功,false=有错误
//特别说明: struct file_rsc中有home_left,通过它也是可以很快找到该文件所属的dbx
// 的,但home_left是左手句柄,而flash_driver处于文件系统的右手,应该禁
// 止它访问左手句柄,故需要文件系统提供DBX_flash_tag指针
//-----------------------------------------------------------------------------
bool_t __DFFSD_sync_buf_before_read(struct st_DBX_flash_tag *DBX_flash_tag,
djyfs_file *fp,uint32_t read_len)
{
switch(fp->open_mode)
{
case enum_r_rb: //只读文件,无需操作
{
}break;
case enum_w_wb: //只写文件,无需操作
{
}break;
case enum_a_ab: //只写文件,无需操作
{
}break;
case enum_r_rb_plus: //读写位置相同,若写缓冲区有数据,必须写到flash
case enum_w_wb_plus: //与en_r_rb_plus处理方式相同
{
__DFFSD_write_buf_to_flash(DBX_flash_tag,fp);
}break;
case enum_a_ab_plus: //追加写,可读。如果读位置与写缓冲区有交错则把写缓
//冲区写入flash,否则什么也不干
{
if(fp->read_ptr + read_len > fp->write_ptr)
__DFFSD_write_buf_to_flash(DBX_flash_tag,fp);
}break;
default:break;
}
return true;
}
//----写入flash文件------------------------------------------------------------
//功能:把缓冲区中的数据写入文件,执行下列操作:
// 1、如果写缓冲区有足够的空间,把数据写入写缓冲区即可。
// 2、如果写缓冲区没有足够的空间,连同写缓冲区原有数据和输入缓冲区中的数据
// 一并写入flash
// 3、写入完成后检查读缓冲区是否需要同步并执行之。
// 4、检查FDT表和DDR表是否需要修改并执行之
//参数:buf,输入缓冲区
// len,本次写入的数据量
// fp,被操作的文件指针
//返回:本次写入的数据量,不包含写缓冲区中原有的数据
//注: 本函数并没有先调用__DFFSD_write_buf_to_flash函数,再写buf中的内容,那样
// 可能需要多一次调用flash写操作,效率低;而是把写缓冲区的数据与buf中的数据
// 合并一次写入flash.
//-----------------------------------------------------------------------------
uint32_t DFFSD_write_file(struct file_rsc *fp,uint8_t *buf,uint32_t len)
{
struct flash_chip *chip;
struct st_DBX_device_tag *DBX_device_tag;
struct st_DBX_flash_tag *DBX_flash_tag;
struct file_access_tag access_tag;
uint32_t completed = 0,write_len,write_sum;
sint64_t wr_point;
uint32_t offset_start;
uint32_t block_no,start_block,end_block,loop,temp;
uint32_t true_block,last_block;
uint32_t buffed_data,spare_len; //文件写缓冲区中的数据量和剩余数据量
if((fp==NULL)||(len==0)||(buf==NULL))
return 0;
DBX_device_tag = (struct st_DBX_device_tag *)(fp->home_DBX->private_tag);
//文件柜指针
DBX_flash_tag = (struct st_DBX_flash_tag *)DBX_device_tag->DBX_medium_tag;
chip = DBX_flash_tag->chip; //取文件柜(文件)所属芯片
buffed_data = ring_check(fp->p_write_buf); //检查缓冲区中的数据量
if(ring_capacity(fp->p_write_buf) - buffed_data >= len)
{//缓冲区内有足够的容量,直接把数据写到缓冲区即可。
completed = ring_write(fp->p_write_buf,(uint8_t*)buf,len);
}else
{
//如果缓冲区没有足够的容量,则把本次需要写入的数据连同缓冲区原来的数据
//一并写入flash,下面开始执行写入操作。
//计算连缓冲区中的数据在一起,一共要写入flash的数据量
write_sum = len + buffed_data;
spare_len = buffed_data; //缓冲区剩余数据量
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 + len -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(write_sum - completed > chip->block_size - offset_start)
write_len = chip->block_size - offset_start;
else
write_len = write_sum - completed;
if(spare_len != 0) //写缓冲区里还有数据
{
temp = ring_read(fp->p_write_buf,
chip->block_buf+offset_start,write_len);
spare_len -= temp; //写缓冲区减去实际读出的数据量
//实际读出的数据量比write_len少,说明本次读已经把写缓冲区读空。
if(temp != write_len)
{
//继续从输入缓冲区中拷贝数据
memcpy(chip->block_buf+temp+offset_start,
buf,write_len-temp);
}
}else //写缓冲区已经空,从输入缓冲区拷贝数据
memcpy(chip->block_buf+offset_start,
buf+completed-buffed_data,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;
wr_point += 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;
wr_point += write_len;
if(wr_point > access_tag.true_size)
access_tag.true_size = wr_point;
chip->erase_block(DBX_flash_tag->PCRB_no
+ DBX_flash_tag->start_block);
}
completed += write_len;
offset_start = 0; //第二块开始,起始偏移地址肯定是0
}
}
if((completed - buffed_data) > 0) //写入有数据
{
__DFFSD_sync_buf_after_write(DBX_flash_tag,fp,completed-buffed_data);
__DFFSD_move_file_write_ptr(DBX_flash_tag,fp,
fp->write_ptr + completed-buffed_data);
}
__DFFSD_write_DDR(DBX_flash_tag);//如果DDR表有变化,写入flash中
return completed - buffed_data;
}
//----读flash文件--------------------------------------------------------------
//功能;把文件中的数据读入到缓冲区中,执行以下操作
// 1、看读缓冲区中有没有数据,有则读入到接收缓冲区中
// 2、若读缓冲区中的数据量不足或没有数据,则从flash中补充读取,并按照不越块
// 边界为限最大限度地填写读缓冲区
// 3、读出完成后看是否需要同步写缓冲区并执行之
//参数:buf,输入缓冲区
// len,读出的数据量
// fp,被操作的文件指针
//返回:实际读取的字节数
//-----------------------------------------------------------------------------
uint32_t DFFSD_read_file(struct file_rsc *fp,uint8_t *buf,uint32_t len)
{
struct flash_chip *chip;
struct st_DBX_device_tag *DBX_device_tag;
struct st_DBX_flash_tag *DBX_flash_tag;
uint32_t completed = 0,read_len,result_len;
uint32_t offset_start;
uint32_t block_no,start_block,end_block,loop;
uint32_t read_result;
if((fp==NULL)||(len==0)||(buf==NULL))
return 0;
DBX_device_tag = (struct st_DBX_device_tag *)(fp->home_DBX->private_tag);
//文件柜指针
DBX_flash_tag = (struct st_DBX_flash_tag *)DBX_device_tag->DBX_medium_tag;
__DFFSD_sync_buf_before_read(DBX_flash_tag,fp,len);
chip = DBX_flash_tag->chip; //取文件柜(文件)所属芯片
//计算起始读写位置处于文件内第几块
start_block = fp->read_ptr/chip->block_size;
//计算终止读写位置处于文件内第几块
end_block = (fp->read_ptr + len -1)/chip->block_size;
offset_start = fp->read_ptr % chip->block_size;
if(fp->read_ptr + len >fp->file_size)
result_len = fp->file_size - fp->read_ptr;
else
result_len = len;
//定位读出点的块号,文件柜内的相对块号。
block_no = __DFFSD_locate_block(DBX_flash_tag,fp,fp->read_ptr);
for(loop = start_block; loop <= end_block; loop++)
{
if(result_len - completed > chip->block_size - offset_start)
read_len = chip->block_size - offset_start;
else
read_len = result_len - completed;
//读出目标块
read_result =chip->read_data_with_ecc(
block_no + DBX_flash_tag->start_block,
offset_start,buf+completed,read_len);
if(read_result == 2) //读出错误,坏块
{
return completed; //读出时发现坏块如何处理呢?---db
}
completed += read_len;
offset_start = 0; //第二块开始,起始偏移地址肯定是0
block_no = DBX_flash_tag->DDR_MAT[block_no].next;
}
fp->read_ptr += completed;
return completed;
}
//----刷写缓冲区---------------------------------------------------------------
//功能: 把文件写缓冲区的数据写入flash
//参数:fp,被操作的文件指针
//返回:实际写入flash的字节数
//-----------------------------------------------------------------------------
uint32_t DFFSD_flush_file(struct file_rsc *fp)
{
struct st_DBX_device_tag *DBX_device_tag;
struct st_DBX_flash_tag *DBX_flash_tag;
if(fp==NULL)
return 0;
DBX_device_tag = (struct st_DBX_device_tag *)(fp->home_DBX->private_tag);
//文件柜指针
DBX_flash_tag = (struct st_DBX_flash_tag *)DBX_device_tag->DBX_medium_tag;
return __DFFSD_write_buf_to_flash(DBX_flash_tag,fp);
}
//----查询文件可读数据量-------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -