📄 mdr.c
字号:
//----------------------------------------------------
//Copyright (C), 2004-2009, lst.
//版权所有 (C), 2004-2009, lst.
//所属模块:flash文件系统
//作者:lst
//版本:V1.0.0
//文件描述:flash文件系统中MDR表部分
//其他说明:
//修订历史:
// 2. ...
// 1. 日期:
// 作者:
// 新版本号:
// 修改说明:
//------------------------------------------------------
#include "inc_os.h"
#include "flashfile.h"
#include "ddr.h"
#include "mdr.h"
#include <string.h>
//----初始化flash芯片---------------------------------------------------------
//功能:把芯片标记为djyosfs芯片,但并不建立文件柜。
//参数: chip,被操作的芯片
// reserves,保留块数量
//返回: true=初始化成功,false=失败
//---------------------------------------------------------------------------
void DFFSD_init_MDR(struct flash_chip *chip,uint32_t reserves)
{
uint8_t MDR_CDR_buffer[cn_MDR_CDR_size];
struct MDR_CDR_mirror *MDR_CDR = (struct MDR_CDR_mirror *)MDR_CDR_buffer;
uint32_t valid_blocks = 1; //首块肯定是可用的,故初值=1
uint32_t i,MDR_bak_block = 0;
//注意,nandflash只有首块是保证有效的,故MDR表尺寸不能超过首块,这不成问题,
//目前为止nandflash的block_size没有小于4K的。
//而norflash则没有这个限制,norflash保证整片都是好的。
for(i = 1; i < chip->block_sum; i++)
{ //找一个好块作为MDR备用块
if(chip->check_block(i))
{
valid_blocks++;
}
}
MDR_bak_block = __DFFSD_probe_MDR_bak(chip);
chip->valid_sum = valid_blocks;
chip->rev_blocks = reserves; //保留块数量
//保留块起始块号
chip->rev_start = MDR_bak_block
+(cn_MDR_size + chip->block_size -1) / chip->block_size;
chip->DBX_start = chip->rev_start + reserves; //文件柜起始块号
if(valid_blocks <= chip->DBX_start)
return; //有效块数太少
chip->MDR.MDR_bak_block = MDR_bak_block;
chip->MDR.roll_next_main = cn_roll_offset;
chip->MDR.roll_next_bak = cn_roll_offset;
for(i = 0; i < cn_DBX_sum_max; i++)
chip->MDR.DBX_created[i] = false;
strcpy((char*)MDR_CDR_buffer,"djyosfs");
__fill_little_32bit(MDR_CDR->chip_CDR_size,0,cn_MDR_CDR_size);
__fill_little_32bit(MDR_CDR->chip_block_sum,0,chip->block_sum);
__fill_little_32bit(MDR_CDR->chip_block_size,0,chip->block_size);
__fill_little_32bit(MDR_CDR->chip_MDR_bak,0,MDR_bak_block);
__fill_little_32bit(MDR_CDR->chip_reserve,0,reserves);
__DFFSD_fill_ECC_MDR_CDR(MDR_CDR_buffer);
__DFFSD_erase_MDR_main(chip);
__DFFSD_write_MDR_main(chip,MDR_CDR_buffer,
(uint32_t)MDR_CDR->chip_MDR_CDR_ECC-(uint32_t)MDR_CDR +4);
__DFFSD_write_end_flag_main(chip);
__DFFSD_erase_MDR_bak(chip);
__DFFSD_write_MDR_bak(chip,MDR_CDR_buffer,
(uint32_t)MDR_CDR->chip_MDR_CDR_ECC-(uint32_t)MDR_CDR +4);
__DFFSD_write_end_flag_bak(chip);
}
//----读MDR_bak表-------------------------------------------------------------
//功能: 把MDR表读到缓冲区。
//参数: chip,目标芯片,chip->bak_start必须已经初始化
// buf,保存所读数据的缓冲区
//返回: true=正确读取,false=错误。
//-----------------------------------------------------------------------------
bool_t __DFFSD_read_MDR_bak(struct flash_chip *chip,uint8_t *buf)
{
uint32_t complete_len=0,read_len;
uint32_t block_no = chip->MDR.MDR_bak_block;
do //本循环用于读取整个MDR_main到缓冲区,MDR_size可能大于1块,故循环。
{
if((cn_MDR_size-complete_len) > chip->block_size)
read_len = chip->block_size;
else
read_len = cn_MDR_size-complete_len;
//MDR表逐个记录单独校验,若整块校验,则每次增加记录都要改校验码,不可行
chip->read_data_no_ecc(block_no,0,buf+complete_len,read_len);
block_no++; //这里并没有考虑坏块的情况----db
complete_len += read_len;
}while(complete_len < cn_MDR_size);
return true;
}
//----读MDR_main表-------------------------------------------------------------
//功能: 把MDR表读到缓冲区。
//参数: chip,目标芯片
// buf,保存所读数据的缓冲区
//返回: 无
//-----------------------------------------------------------------------------
void __DFFSD_read_MDR_main(struct flash_chip *chip,uint8_t *buf)
{
uint32_t complete_len=0,read_len;
uint32_t block_no = 0; //MDR_main从0开始存储
do //本循环用于读取整个MDR_main到缓冲区,MDR_size可能大于1块,故循环。
{
if((cn_MDR_size-complete_len) > chip->block_size)
read_len = chip->block_size;
else
read_len = cn_MDR_size-complete_len;
//MDR表逐个记录单独校验,若整块校验,则每次增加记录都要改校验码,不可行
chip->read_data_no_ecc(block_no,0,buf+complete_len,read_len);
block_no++; //这里并没有考虑坏块的情况----db
complete_len += read_len;
}while(complete_len < cn_MDR_size);
return;
}
//----分配一个存储介质---------------------------------------------------------
//功能: 建立新文件柜时,调用此函数从存储介质中分配存储器。
//参数: chip,目标芯片
// size,待分配的块数。
// result,返回分配结果
//返回: true=分配成功,结果保存在result中,false = 分配额失败
////---------------------------------------------------------------------------
bool_t __DFFSD_allocate_DBX(struct flash_chip *chip,
uint32_t size,uint32_t *result)
{
uint8_t MDR_buf[cn_MDR_size];
//文件柜起始块数组,用于查询空闲空间,+2是为包含可能存在的首尾空闲区
uint32_t block_start[cn_DBX_sum_max+2];
//文件柜结束块数组,用于查询空闲空间,+2是为包含可能存在的首尾空闲区
uint32_t block_end[cn_DBX_sum_max+2];
struct MDR_DBX_mirror *MDR_DBX;
uint32_t loop,loop1=0,temp;
__DFFSD_read_MDR_main(chip,MDR_buf); //读出MDR到缓冲区(原样读出,不解析)
block_start[0] = chip->DBX_start;
block_end[0] = chip->DBX_start;
//MDR_DBX指针指向MDR缓冲区中第一个DBX区,用于检查各DBX区是否空闲
MDR_DBX = (struct MDR_DBX_mirror *)(MDR_buf+cn_MDR_CDR_size);
for(loop = 1; loop < cn_DBX_sum_max+1; loop++)
{//读出各已经建立的文件柜的起始块号和结束块号,保存到block_start和block_end
//两个数组里,数组元素比文件柜数多两个,是用于保存文件柜首尾空闲区间的
if(chip->MDR.DBX_created[loop-1])
{//对已经建立的文件柜,从它的MDR_DBX缓存中读出起始和结束块号
block_start[loop] = __pick_little_32bit(MDR_DBX->DBX_start_block,0);
//结束块号,该块已经不属于本文件柜了。
block_end[loop] = block_start[loop]
+ __pick_little_32bit(MDR_DBX->DBX_blocks_sum,0);
}else
{//为建立的文件柜,起始和结束块号均初始化为最近发现的已建立的文件柜的
//起始和结束块号,等效于本文件柜是空的。
block_start[loop] = block_end[loop-1];
block_end[loop] = block_end[loop-1];
}
MDR_DBX++; //缓冲区指向下一个文件柜的MDR_DBX
}
block_start[cn_DBX_sum_max+1] = chip->block_sum;//芯片尾部空闲区间的起始块号
block_end[cn_DBX_sum_max+1] = chip->block_sum; //芯片尾部空闲区间的结束块号
for(loop = 0; loop <cn_DBX_sum_max+1; loop++)
{//用冒泡法对各文件柜的起始块号排队(不是空闲块尺寸),芯片反复使用后可能发生
//交错,各文件柜所占用的存储器位置并不与其DBX在MDR中的顺序相同,只有按块地址
//排序后,才能有效确定各可用空间的尺寸。
for(loop1 = loop+1; loop1 < cn_DBX_sum_max+2; loop1++)
{
if(block_start[loop] > block_start[loop1])
{
temp = block_start[loop];
block_start[loop] = block_start[loop1];
block_start[loop1] = temp;
temp = block_end[loop];
block_end[loop] = block_end[loop1];
block_end[loop1] = temp;
}
}
}
//找一个满足要求的连续空闲空间
for(loop = 0; loop < cn_DBX_sum_max+1; loop++)
{
if(block_start[loop+1] - block_end[loop] >= size)
{
*result = block_start[loop]; //找到满足要求的空间
break;
}
}
if(loop == cn_DBX_sum_max +1)
return false; //没有找到满足要求的连续空闲区域
else
return true;
}
//----写入一个MDR_DBX块--------------------------------------------------------
//功能: 把一个MDR_DBX块写入flash中,需同时写入MDR_main和MDR_bak中
//参数: chip,目标芯片
// DBX_no,文件柜号
// MDR_DBX_buf,已经填充好的缓冲区
//返回: true=成功,false=失败
//-----------------------------------------------------------------------------
bool_t __DFFSD_write_MDR_DBX(struct flash_chip *chip,
uint32_t DBX_no,uint8_t *MDR_DBX_buf)
{
uint8_t MDR_buf[cn_MDR_size];
struct MDR_temp_record MDR_record;
uint32_t block_offset,block_no;
//新MDR_DBX在MDR表中的偏移量(字节)
block_offset = cn_MDR_CDR_size + DBX_no * cn_MDR_DBX_size;
block_no = block_offset / chip->block_size;//新MDR_DBX在MDR表中的块号
block_offset = block_offset % chip->block_size; //块内偏移量
//检查MDR_main是否需要擦除
if(chip->query_block_ready_no_ecc(
block_no,block_offset,NULL,cn_MDR_DBX_size))
{//MDR_main中该DBX块无需擦除
__DFFSD_write_MDR_DBX_main(chip,MDR_DBX_buf,DBX_no); //直接写入MDR_main
//下面把新MDR_DBX写入到MDR_bak中
block_no += chip->MDR.MDR_bak_block; //取MDR_bak块号
//检查MDR_bak是否需要擦除
if(chip->query_block_ready_no_ecc(
block_no,block_offset,NULL,cn_MDR_DBX_size))
{//MDR_bak中该DBX块无需擦除
__DFFSD_write_MDR_DBX_bak(chip,MDR_DBX_buf,DBX_no);
}else
{//MDR_bak中该DBX块需要擦除
__DFFSD_read_MDR_main(chip,MDR_buf); //读完整MDR表
__DFFSD_uasm_DBX(chip,&MDR_record,MDR_buf);
//从缓冲区中取出滚动区的有效数据,保存到MDR_record中,因新文件柜
//尚未完成初始化,滚动区中没有该文件柜的数据。
__DFFSD_uasm_roll(chip,MDR_buf,
&MDR_record,chip->MDR.roll_next_main);
memcpy(MDR_buf+cn_MDR_CDR_size + DBX_no * cn_MDR_DBX_size,
MDR_DBX_buf,cn_MDR_DBX_size);
__DFFSD_erase_MDR_bak(chip);
__DFFSD_write_MDR_bak(chip,MDR_buf,cn_CDR_and_DBX_size);
__DFFSD_write_roll_bak(chip,&MDR_record);
__DFFSD_write_end_flag_bak(chip);
}
}else
{//MDR_main中该DBX块需要擦除
__DFFSD_read_MDR_main(chip,MDR_buf);
__DFFSD_uasm_DBX(chip,&MDR_record,MDR_buf);
__DFFSD_uasm_roll(chip,MDR_buf,&MDR_record,chip->MDR.roll_next_main);
memcpy(MDR_buf+cn_MDR_CDR_size + DBX_no * cn_MDR_DBX_size,
MDR_DBX_buf,cn_MDR_DBX_size);
__DFFSD_erase_MDR_bak(chip);
__DFFSD_write_MDR_bak(chip,MDR_buf,cn_CDR_and_DBX_size);
__DFFSD_write_roll_bak(chip,&MDR_record);
__DFFSD_write_end_flag_bak(chip);
__DFFSD_erase_MDR_main(chip);
__DFFSD_write_MDR_main(chip,MDR_buf,cn_CDR_and_DBX_size);
__DFFSD_write_roll_main(chip,&MDR_record);
__DFFSD_write_end_flag_main(chip);
}
return true;
}
//----建立一个文件柜----------------------------------------------------------
//功能: 在指定芯片上增加一个文件柜,新文件柜只是登记在芯片上,并未加载至操作系统,
// 若要加载,必须重新启动系统。
//参数: chip,被操作的芯片
// size,新增加的文件柜尺寸(用块数表示)
// name,新增加的文件柜名字
// nand_ecc,本文件柜是否需要ecc校验
//返回: true = 成功,false = 失败,失败原因一般是存储空间不够。
//---------------------------------------------------------------------------
bool_t DFFSD_create_DBX(struct flash_chip *chip, uint32_t size,char *name,
bool_t nand_ecc)
{
struct st_DBX_flash_tag *DBX_flash_tag = NULL;
struct st_DBX_device_tag *DBX_device_tag = NULL;
struct dev_handle *fs_handle_right = NULL;
struct MDR_DBX_mirror *MDR_DBX;
struct rsc_node *fs_rsc_node;
struct DBX_semp_para semp_dbx;
uint32_t DBX_start,DBX_no,name_len,loop,table_size,DDR_blocks;
uint8_t MDR_DBX_buf[cn_MDR_DBX_size];
if((chip == NULL) && (size == 0) && (name == NULL))
return false;
name_len = rtstrlen(name,cn_flash_DBX_name_limit); //检测字符串长度,
if(name_len == 0) //文件柜名长度为0,非法
return false;
for(loop = 0; loop < cn_DBX_sum_max; loop++)//检查是否还可以建立新的文件柜
{
if(!chip->MDR.DBX_created[loop])
{
DBX_no = loop; //第loop个文件柜未建立,其MDR_DBX区块是空的
break; //为新文件柜找到MDR_DBX块后退出循环
}
}
if(loop == cn_DBX_sum_max)
return false; //MDR中已经没有空闲的DBX块
//以下初始化新文件柜的MDR_DBX缓存
MDR_DBX = (struct MDR_DBX_mirror*)MDR_DBX_buf;
if(name_len != cn_limit_uint32) //copy新文件柜名
{
strcpy(MDR_DBX->DBX_name,name);
}else
{
memcpy(MDR_DBX->DBX_name,name,cn_flash_DBX_name_limit);
MDR_DBX->DBX_name[cn_flash_DBX_name_limit] = '\0';
}
fs_rsc_node = rsc_search(NULL,"dev\\fs"); //取文件系统设备的资源结点指针
//在文件柜设备中查名为MDR_DBX->DBX_name的结点
if(rsc_search_son(fs_rsc_node,MDR_DBX->DBX_name))
{
y_error_login(enum_fs_DBX_name_repeat,"文件柜重名");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -