📄 mdr.c
字号:
return false;
}
if( ! __DFFSD_allocate_DBX(chip,size,&DBX_start)) //分配存储空间
return false;
strcpy(MDR_DBX->DBX_format_flag,"unready"); //格式化标志
__fill_little_32bit(MDR_DBX->DBX_start_block,0,DBX_start); //起始块号
__fill_little_32bit(MDR_DBX->DBX_blocks_sum,0,size); //文件柜尺寸(块数)
__DFFSD_fill_ECC_MDR_DBX((uint8_t *)MDR_DBX); //填充ECC码
if( ! __DFFSD_write_MDR_DBX(chip,DBX_no,MDR_DBX_buf))
return false;
chip->MDR.DBX_created[DBX_no] = true;
//打开文件系统设备的右手接口
if((fs_handle_right = dev_open_right("fs",0)) == NULL)
return false;
//分配文件柜设备专用数据结构内存,该结构将嵌入到反设备结构中
DBX_device_tag = (struct st_DBX_device_tag*)
m_malloc_gbl(sizeof(struct st_DBX_device_tag),0);
if(DBX_device_tag == NULL)
goto goto_exit_install_chip;
//分配flash文件系统专用数据结构内存,该结构将嵌入到文件柜设备中
DBX_flash_tag = (struct st_DBX_flash_tag*)
m_malloc_gbl(sizeof(struct st_DBX_flash_tag),0);
if(DBX_flash_tag == NULL)
goto goto_exit_install_chip;
DBX_flash_tag->ART_position = NULL;
DBX_flash_tag->ART_block_no = NULL;
DBX_flash_tag->ART_times = NULL;
DBX_flash_tag->writed_DDR_main = NULL;
DBX_flash_tag->writed_DDR_bak = NULL;
DBX_flash_tag->chip = chip; //flash文件柜存储器所属芯片
DBX_flash_tag->DBX_no = DBX_no; //本文件柜在芯片中的序号
DBX_flash_tag->PCRB_no = cn_limit_uint32; //未格式化
DBX_flash_tag->DDR_main = cn_limit_uint32; //未格式化
DBX_flash_tag->DDR_bak = cn_limit_uint32; //未格式化
DBX_flash_tag->start_block = DBX_start;
DBX_flash_tag->block_sum = size;
DBX_flash_tag->nand_ecc = nand_ecc;
table_size = DBX_flash_tag->block_sum * (4+4+2);
//为磨损位置表分配内存
DBX_flash_tag->ART_position = (uint32_t*)m_malloc_gbl(table_size,0);
if(DBX_flash_tag->ART_position == NULL)
goto goto_exit_install_chip;
//为磨损块号表分配内存
DBX_flash_tag->ART_block_no = DBX_flash_tag->ART_position
+ DBX_flash_tag->block_sum;
//为磨损次数表分配内存
DBX_flash_tag->ART_times = (uint16_t*)(DBX_flash_tag->ART_block_no
+ DBX_flash_tag->block_sum);
//计算DDR表尺寸
DBX_flash_tag->DDR_size = __DFFSD_calculate_DDR_size(DBX_flash_tag);
//1份DDR表占用的块数
DDR_blocks = (DBX_flash_tag->DDR_size
+chip->block_size-1)/chip->block_size;
//申请两份DBL表所需内存
DBX_flash_tag->DDR_DBL =(uint32_t*)m_malloc_gbl(DDR_blocks*8,0);
if(DBX_flash_tag->DDR_DBL == NULL)
goto goto_exit_install_chip;
//申请MAT表所需内存
DBX_flash_tag->DDR_MAT = (struct MAT_table *)m_malloc_gbl(
DBX_flash_tag->block_sum*sizeof(struct MAT_table),0);
if(DBX_flash_tag->DDR_MAT == NULL)
goto goto_exit_install_chip;
//两份写入标志
DBX_flash_tag->writed_DDR_main = (bool_t*)m_malloc_gbl(
DDR_blocks*sizeof(bool_t)*2,0);
if(DBX_flash_tag->writed_DDR_main == NULL)
goto goto_exit_install_chip;
DBX_flash_tag->writed_DDR_bak=DBX_flash_tag->writed_DDR_main+DDR_blocks;
//填充函数指针和文件柜名
__DFFSD_fill_DBX_device_tag(DBX_device_tag,name);
//文件柜设备的存储媒体指向flash文件柜存储器
DBX_device_tag->DBX_medium_tag = (ptu32_t)DBX_flash_tag;
DBX_device_tag->formatted =false;
semp_dbx.left = chip->left_semaphore; //芯片的左手信号量
semp_dbx.right = chip->right_semaphore; //芯片的右手信号量
if(dev_ctrl(fs_handle_right,enum_fs_add_DBX,
(ptu32_t)DBX_device_tag,(ptu32_t)&semp_dbx)
!= enum_fs_no_error)
{
goto goto_exit_install_chip;
}
//这是正常出口
dev_close_right(fs_handle_right); //关闭文件系统设备
return true;
goto_exit_install_chip:
dev_close_right(fs_handle_right); //关闭文件系统设备
if(DBX_flash_tag !=NULL)
{
if(DBX_flash_tag->writed_DDR_main != NULL)
m_free(DBX_flash_tag->writed_DDR_main);
if(DBX_flash_tag->DDR_MAT != NULL)
m_free(DBX_flash_tag->DDR_MAT);
if(DBX_flash_tag->DDR_DBL != NULL)
m_free(DBX_flash_tag->DDR_DBL);
if(DBX_flash_tag->DDR_DBL != NULL)
m_free(DBX_flash_tag->DDR_DBL);
if(DBX_flash_tag->ART_position != NULL)
m_free(DBX_flash_tag->ART_position);
m_free(DBX_flash_tag);
}
if(DBX_device_tag !=NULL) m_free(DBX_device_tag);
return false; //文件柜加入到设备树失败
}
//----查找MDR_bak的块号--------------------------------------------------------
//功能: 在读MDR_main失败,无法从中获取MDR_bak的块号时,根据芯片的块尺寸计算
// MDR_bak可能的存放位置。当用本函数确定块号时,应该从该块号开始连续查找
// 5块,直到找到合法的MDR_bak块为止,如果5块都未能找到合法的MDR_bak,则认为
// 本flash没有按照djyosfs初始化过。
//参数: chip,目标芯片
//返回: 块号,0表示没有找到
//-----------------------------------------------------------------------------
uint32_t __DFFSD_probe_MDR_bak(struct flash_chip *chip)
{
//db 没有考虑坏块,以后补充。
return (cn_MDR_size+chip->block_size-1) / chip->block_size;
}
//----校验MDR_CDR--------------------------------------------------------------
//功能: 校验MDR_CDR,并改正的数据,如果不能改正,返回错误
//参数: buf,保存有未校验的MDR_CDR数据的缓冲区
//返回: true=无错或者被修正,false=有错并且不能改正。
//-----------------------------------------------------------------------------
bool_t __DFFSD_verify_MDR_CDR(uint8_t *buf)
{
return true;
}
//----校验MDR_DBX--------------------------------------------------------------
//功能: 校验MDR_DBX,并改正的数据,如果不能改正,返回错误
//参数: buf,保存有未校验的MDR_DBX数据的缓冲区
//返回: true=无错或者被修正,false=有错并且不能改正。
//-----------------------------------------------------------------------------
bool_t __DFFSD_verify_MDR_DBX(uint8_t *buf)
{
return true;
}
//----校验MDR结束标志----------------------------------------------------------
//功能: 1.校验MDR表的最后4个字节是否AA5555AA,最多只允许一位不符。
// 2.校验CDR和DBX表的ECC
//参数: buf,字节缓冲区
//返回: true=校验正确,false=错误
//-----------------------------------------------------------------------------
//特别注意,对齐问题/大小端问题/最小寻址单元大于8位问题,这些问题使得不能把
//AA5555AA组成32位整数来比较
bool_t __DFFSD_verify_end_flag(uint8_t *buf)
{
uint8_t temp[4] = {0xAA,0x55,0x55,0xAA};
uint8_t xor;
ufast_t loop4,loop8,error_bit = 0;
for(loop4 = 0; loop4 < 4; loop4++)
{
if(buf[loop4] != temp[loop4])
{
xor = buf[loop4] ^ temp[loop4];
for(loop8 = 0; loop8 < 8; loop8++)
{
if(xor & (1<<loop8))
error_bit ++;
if(error_bit > 1)
return false;
}
}else
continue;
}
if(! __DFFSD_verify_MDR_CDR(buf))
return false;
if(! __DFFSD_verify_MDR_DBX(buf))
return false;
return true;
}
//----MDR滚动记录ECC校验-------------------------------------------------------
//功能: MDR中滚动存储的记录进行ECC校验,并改正数据。
//参数: buf,记录指针
//返回: 0=无错,1=有错但被修正,2=无法修正
//-----------------------------------------------------------------------------
uint32_t __DFFSD_verify_MDR_record(uint8_t *buf)
{
return 0;
}
//----扫描滚动存储区-----------------------------------------------------------
//功能: 扫描滚动存储缓冲区,读取已经格式化的文件柜的DDR_main块号、DDR_bak块号、
// PCRB块号。
//参数: chip,被操作的芯片
// MDR_buf,缓冲区
// MDR_record,返回扫描到的数据的指针
// end_offset,最后一条有效记录位置
//返回: 无
//-----------------------------------------------------------------------------
void __DFFSD_uasm_roll(struct flash_chip *chip,uint8_t *MDR_buf,
struct MDR_temp_record *MDR_record,uint32_t end_offset)
{
uint8_t *record;
uint32_t loop,loop3,item_sum=0;
bool_t got_DDR_main[cn_DBX_sum_max];//各文件柜DDR_main块号是否找到标志
bool_t got_DDR_bak[cn_DBX_sum_max]; //各文件柜DDR_bak块号是否找到标志
bool_t got_PCRB[cn_DBX_sum_max]; //各文件柜PCRB块号是否找到标志
for(loop3 = 0; loop3 < cn_DBX_sum_max; loop3++)
{
got_DDR_main[loop3] = false;
got_DDR_bak[loop3] = false;
got_PCRB[loop3] = false;
if(MDR_record->formatted[loop3])
{
item_sum +=3; //每个已经格式化的文件柜都有3条滚动记录
}
}
//循环扫描所有滚动存储区的有效条目。
for(loop = end_offset-8;loop >= cn_roll_offset; loop-=8)
{
record = MDR_buf + loop;
for(loop3 = 0; loop3 < cn_DBX_sum_max; loop3++)
{
if(! MDR_record->formatted) //文件柜未格式化
continue;
__DFFSD_verify_MDR_record(record); //校验该记录---db,校验错误怎么办?
if(!got_DDR_main[loop3]) //DDR_main滚动记录还未找到
{
//检查本项目是不是第loop个文件柜的DDR_main块号
if((record[0] == cn_MDR_DDR_main) && (record[1] == loop3))
{
item_sum--; //找到,剩余项目数减量
got_DDR_main[loop3] = true; //标记该DDR_main块号项已找到
//将结果写入返回的结构指针中
MDR_record->DDR_main_block_no[loop3]
= __pick_little_32bit(&record[2],0);
break;
}
}
if(!got_DDR_bak[loop3]) //DDR_bak滚动记录还未找到
{
//检查本项目是不是第loop个文件柜的DDR_bak块号
if((record[0] == cn_MDR_DDR_bak) && (record[1] == loop3))
{
item_sum--; //找到,剩余项目数减量
got_DDR_bak[loop3] = true; //标记该DDR_bak块号项已找到
//将结果写入返回的结构指针中
MDR_record->DDR_bak_block_no[loop3]
= __pick_little_32bit(&record[2],0);
break;
}
}
if(!got_PCRB[loop3]) //PCRB滚动记录还未找到
{
//检查本项目是不是第loop个文件柜的PCRB块号
if((record[0] == cn_MDR_PCRB) && (record[1] == loop3))
{
item_sum--; //找到,剩余项目数减量
got_PCRB[loop3] = true; //标记该PCRB块号项已找到
//将结果写入返回的结构指针中
MDR_record->PCRB_block_no[loop3] =
__pick_little_32bit(&record[2],0);
break;
}
}
}
if(item_sum == 0) //剩余项目为0,表明需要找的项目已经全部找到
break;
}
}
//----检查MDR_bak的完整性------------------------------------------------------
//功能: 检查MDR_bak是否完整,是否因上次掉电时正在写入而导致不完整,方法是检查
// 尾部的AA5555AA,以及最后一条滚动记录的校验码
//参数: chip,目标芯片
//返回: true=完整,false=不完整
//-----------------------------------------------------------------------------
bool_t __DFFSD_check_MDR_bak(struct flash_chip *chip)
{
uint8_t MDR_buf[cn_MDR_size];
__DFFSD_read_MDR_bak(chip,MDR_buf);
return (__DFFSD_verify_end_flag(MDR_buf));
}
//----检测滚动区结束位置-------------------------------------------------------
//功能: 检测滚动存储区第一个空闲记录的偏移量,用折半查找方法
//参数: chip,目标芯片
// MDR_buf,MDR表缓冲区
//返回: 偏移量
//-----------------------------------------------------------------------------
uint32_t __DFFSD_find_roll_next(struct flash_chip *chip,uint8_t *MDR_buf)
{
uint32_t busy_endian,free_endian,middle,result;
uint32_t block_offset;
busy_endian = cn_roll_offset/8;
free_endian = cn_MDR_size /8 -1; //最后一项用于完整性标记
while(1)
{
middle = (busy_endian+free_endian)/2; //计算中间项
block_offset = 8*middle;
//测试第block_no块偏移block_offset开始的8字节是否擦除后未使用过。
//虽然至今所知的flash都可以用是否等于0xff来判断是否擦除,但datasheet
//上并没有这样说,难保哪天不会出来一个不是这样的,故把判断交给芯片
//driver才可确保可移植性。
if(chip->query_ready_with_data(NULL,MDR_buf+block_offset,8))
{//第middle单元是空闲的
if(middle == busy_endian)
{
result = middle*8;
break;
}else
free_endian = middle;
}else
{//第middle单元是已经使用了的
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -