📄 ddr.c
字号:
//----------------------------------------------------
//Copyright (C), 2004-2009, lst.
//版权所有 (C), 2004-2009, lst.
//所属模块:flash文件系统
//作者:lst
//版本:V1.0.0
//文件描述:flash文件系统中DDR表的部分
//其他说明:
//修订历史:
// 2. ...
// 1. 日期:
// 作者:
// 新版本号:
// 修改说明:
//------------------------------------------------------
#include "inc_os.h"
#include "flashfile.h"
#include "ddr.h"
#include <string.h>
//----重构DDR_bak--------------------------------------------------------------
//功能:正确读取DDR_main到内存后后,如果校验发现flash中的DDR_bak与内存中的DDR表
// 不一致,将调用本函数。除DBL部分外,两份DDR表的其余部分是相同的,故只需
// 根据DDR表中的MAT表重构出一份DDR_DBL_bak即可,然后把整个DDR_bak表标记为
// 需要写入。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//返回:无
//-----------------------------------------------------------------------------
void __DFFSD_rebuild_DDR_bak(struct st_DBX_flash_tag *DBX_flash_tag)
{
uint32_t i,loop,DBL_offset,DDR_blocks;
struct flash_chip *chip = DBX_flash_tag->chip;
bool_t *writed = DBX_flash_tag->writed_DDR_bak; //指向是否完成写入的指针
uint32_t *DBL_buf;
DDR_blocks = (DBX_flash_tag->DDR_size + chip->block_size -1)
/ chip->block_size; //计算DDR表占用的块数
DBL_buf = DBX_flash_tag->DDR_DBL+DDR_blocks;
for(loop = 0; loop < DDR_blocks; loop++) //设置整个DDR_bak需写入
writed[loop] = false;
//以下几行扫描整个文件柜,初始化DBL_bak表
DBL_offset = 0;
for(loop = 0; loop < DBX_flash_tag->block_sum; loop++)
{
if(DBX_flash_tag->DDR_MAT[loop].attr == cn_DDR_bak_block)
{
DBL_buf[DBL_offset] = loop; //第loop块是DDR_bak块
DBL_offset ++; //DBL偏移增量
}
}
//异常断电的特殊情况下,可能造成MAT中的DDR_bak块数不够的情况,详见文档
//《DDR表异常断电算法》
//为所缺少的DBL块分配新块
//此时初始化还未完成,不能使用正常的块分配算法,直接找free块,
if(DBL_offset < DDR_blocks)
{
for(loop = 0; loop < DBX_flash_tag->block_sum; loop++)
{
if(DBX_flash_tag->DDR_MAT[loop].attr == cn_free_block)
{
//第loop块是空闲块,改为DDR_bak块
DBL_buf[DBL_offset] = loop;
//把MAT表中第loop块的属性改为DDR_bak块
DBX_flash_tag->DDR_MAT[loop].attr = cn_DDR_bak_block;
//计算MAT表中第loop项的地址在DDR表中的偏移量
i = DBX_flash_tag->DDR_size-(DBX_flash_tag->block_sum-loop)*4*2;
//计算MAT表中第loop项的地址在DDR表中的偏移块号
i = i / chip->block_size;
//第loop块的用途被修改,MAT第koop项位置DDR_main也被修改,重写之
DBX_flash_tag->writed_DDR_main[i] = false;
DBL_offset ++; //DBL偏移增量
if(DBL_offset == DDR_blocks)
break;
}
}
}
}
//----重构DDR_main-------------------------------------------------------------
//功能:正确读取DDR_main到内存后后,肯定DDR_main是有问题的,将调用本函数重构
// DDR_main表。除DBL部分外,两份DDR表的其余部分是相同的,故只需根据DDR表中
// 的MAT表重构出一份DDR_DBL_main即可,然后把整个DDR_main表标记为需要写入。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//返回:无
//-----------------------------------------------------------------------------
void __DFFSD_rebuild_DDR_main(struct st_DBX_flash_tag *DBX_flash_tag)
{
uint32_t i,loop,DBL_offset,DDR_blocks;
struct flash_chip *chip = DBX_flash_tag->chip;
bool_t *writed = DBX_flash_tag->writed_DDR_bak; //指向是否完成写入的指针
uint32_t *DBL_buf;
DDR_blocks = (DBX_flash_tag->DDR_size + chip->block_size -1)
/ chip->block_size; //计算DDR表占用的块数
DBL_buf = DBX_flash_tag->DDR_DBL;
for(loop = 0; loop < DDR_blocks; loop++) //置整个DDR_main需写入
writed[loop] = false;
//以下几行扫描整个文件柜,初始化DBL_main表
DBL_offset = 0;
for(loop = 0; loop < DBX_flash_tag->block_sum; loop++)
{
if(DBX_flash_tag->DDR_MAT[loop].attr == cn_DDR_main_block)
{
DBL_buf[DBL_offset] = loop; //第loop块是DDR_main块
DBL_offset ++; //DBL偏移增量
}
}
//异常断电的特殊情况下,可能造成MAT中的DDR_main块数不够的情况,详见文档
//《DDR表异常断电算法》
//为所缺少的DBL块分配新块
//此时初始化还未完成,不能使用正常的块分配算法,直接找free块,
if(DBL_offset < DDR_blocks)
{
for(loop = 0; loop < DBX_flash_tag->block_sum; loop++)
{
if(DBX_flash_tag->DDR_MAT[loop].attr == cn_free_block)
{
//第loop块是空闲块,改为DDR_bak块
DBL_buf[DBL_offset] = loop;
//把MAT表中第loop块的属性改为DDR_main块
DBX_flash_tag->DDR_MAT[loop].attr = cn_DDR_bak_block;
//计算MAT表中第loop项的地址在DDR表中的偏移量
i = DBX_flash_tag->DDR_size -(DBX_flash_tag->block_sum-loop)*4*2;
//计算MAT表中第loop项的地址在DDR表中的偏移块号
i = i / chip->block_size;
//第loop块的用途被修改,MAT第koop项位置DDR_main也被修改,重写之
DBX_flash_tag->writed_DDR_main[i] = false;
DBL_offset ++; //DBL偏移增量
if(DBL_offset == DDR_blocks)
break;
}
}
}
}
//----计算MAT表起始偏移--------------------------------------------------------
//功能: 计算DDR表中MAT表的起始偏移地址,如果DDR_size不超过1块,则ART表后直接存
// MAT表,否则MAT表要做8字节对齐以免单个MAT表项跨块。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//返回: MAT表起始地址偏移
//-----------------------------------------------------------------------------
uint32_t __DFFSD_MAT_start(struct st_DBX_flash_tag *DBX_flash_tag)
{
uint32_t MAT_start;
struct flash_chip *chip = DBX_flash_tag->chip;
MAT_start=(DBX_flash_tag->DDR_size+chip->block_size -1)/chip->block_size*4
+4 +4 + DBX_flash_tag->block_sum*2;
if(DBX_flash_tag->DDR_size > chip->block_size)
{
MAT_start = align_up_8(MAT_start);
}
return MAT_start;
}
//----读DDR表------------------------------------------------------------------
//功能:本函数被__DFFSD_scan_DDR函数调用,扫描一个DDR表,读取DDR表的内容,然后
// 初始化DBX_flash_tag与DDR表有关的成员。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
// which,读取哪一个DDR表,0=DDR_main,1=DDR_bak
//返回:true=完全无错,flash中DDR表被读入到DBX_flash_tag中。
// false=有错误,flash中DDR表有任何错误,__DFFSD_scan_DDR函数会调用
// __rebuild_DDR_bak或__rebuild_DDR_main函数重构DDR表
//-----------------------------------------------------------------------------
bool_t __DFFSD_read_DDR(struct st_DBX_flash_tag *DBX_flash_tag,
ufast_t which)
{
uint32_t block_no; //DDR表的块号
uint32_t DDR_blocks; //DDR表占用的块数
uint32_t loop,read_size;
uint32_t offset = 0,completed = 0;
uint32_t FDSB_start,ARB_start,ART_start,ART_end,MAT_start;
uint32_t temp;
struct MAT_table *MAT_item;
struct flash_chip *chip = DBX_flash_tag->chip; //获取文件柜对应的芯片
uint32_t *DBL_buf;
DDR_blocks = (DBX_flash_tag->DDR_size+chip->block_size-1)/chip->block_size;
if(which == 0)
{
DBL_buf = DBX_flash_tag->DDR_DBL; //取DBL_main缓冲区指针
DBL_buf[0] = DBX_flash_tag->DDR_main;
}else
{
DBL_buf = DBX_flash_tag->DDR_DBL+DDR_blocks; //取DBL_bak缓冲区指针
DBL_buf[0] = DBX_flash_tag->DDR_bak;
}
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);
MAT_item = DBX_flash_tag->DDR_MAT;
for(loop = 0; loop < DDR_blocks; loop++) //从首块到末块循环
{
block_no = DBL_buf[loop] + DBX_flash_tag->start_block;
if(loop == DDR_blocks-1)
read_size = DBX_flash_tag->DDR_size - completed;
else
read_size = chip->block_size;
if(chip->read_data_with_ecc(block_no,0,chip->block_buf,read_size)
!= read_size)
{
return false; //读函数返回错误
}else
{
while(offset - completed < read_size)
{
if(offset < FDSB_start) //DBL
{
DBL_buf[offset/4] = __pick_little_32bit(
chip->block_buf+(offset-completed),0);
offset +=4;
}else if(offset < ARB_start) //FDSB
{
DBX_flash_tag->DDR_FDSB = __pick_little_32bit(
chip->block_buf+(offset-completed),0);
offset +=4;
}else if(offset < ART_start) //ARB
{
DBX_flash_tag->DDR_ARB = __pick_little_32bit(
chip->block_buf+(offset-completed),0);
offset +=4;
}else if(offset < ART_end) //ART
{
temp = (offset-ART_start)/2;
DBX_flash_tag->ART_times[temp] = __pick_little_16bit(
chip->block_buf+(offset-completed),0);
DBX_flash_tag->ART_position[temp] = temp;
DBX_flash_tag->ART_block_no[temp] = temp;
offset +=2;
}else if(offset < MAT_start) //跳过对齐填充
{
offset = MAT_start;
}else if(offset <= DBX_flash_tag->DDR_size)
{
temp = __pick_little_32bit(
chip->block_buf+(offset-completed),0);
MAT_item->attr = temp >>30;
//向前指针
MAT_item->previous = temp & 0x3fffffff;
temp = __pick_little_32bit(
chip->block_buf+(offset-completed),1);
MAT_item->attr += (temp >>30)<<2;
//向后指针
MAT_item->next = temp & 0x3fffffff;
offset +=8;
MAT_item++;
}
}
completed += chip->block_size;
}
}
for(loop = 0; loop < DBX_flash_tag->block_sum; loop++) //磨损表不排序
{
DBX_flash_tag->ART_block_no[loop] = loop;
DBX_flash_tag->ART_position[loop] = loop;
}
return true; //哈哈,如果有任何错误,函数走不到这里
}
//----校验DDR_bak-------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -