📄 fdt.c
字号:
//----------------------------------------------------
//Copyright (C), 2004-2009, lst.
//版权所有 (C), 2004-2009, lst.
//所属模块:flash文件系统
//作者:lst
//版本:V1.0.0
//文件描述:flash文件系统中FDR表部分
//其他说明:
//修订历史:
// 2. ...
// 1. 日期:
// 作者:
// 新版本号:
// 修改说明:
//------------------------------------------------------
#include "inc_os.h"
#include "flashfile.h"
#include "fdt.h"
#include "ddr.h"
#include <string.h>
//----初始化FDT表--------------------------------------------------------------
//功能:初始化FDT表,把存储块划分为一个个FDT_item,并用双向链表连接起来。FDT
// 表的第一个FDT_item始终是根目录项。本函数只会在文件柜格式化时调用
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
//返回:true=成功,false=失败
//-----------------------------------------------------------------------------
bool_t __DFFSD_init_FDT(struct st_DBX_flash_tag *DBX_flash_tag)
{
uint8_t *FDT_buf;
struct fdt_info *pl_FDT_item;
struct flash_chip *chip;
uint32_t true_block,FDT_block_no;
uint32_t block_capacity,loop;
chip = DBX_flash_tag->chip;
FDT_block_no = DBX_flash_tag->DDR_FDSB;
block_capacity = chip->block_size / 256;
DBX_flash_tag->FDT_capacity = block_capacity;
DBX_flash_tag->FDT_free_num= block_capacity - 1;
FDT_buf = chip->block_buf;
for(loop=0; loop < block_capacity; loop++)
{
pl_FDT_item = (struct fdt_info*)(FDT_buf + loop * 256);
pl_FDT_item->name_buf_len = cn_flash_file_name_limit +1;
pl_FDT_item->mattr = 0xff; //表示空闲FDT_item
//以下把所有FDT_item的修改和创建日期时间均改为2009-01-04-12-00-00,
//那是djyos的生日。
pl_FDT_item->second_create = 0x00;
pl_FDT_item->minute_create = 0x00;
pl_FDT_item->hour_create = 0x12;
pl_FDT_item->date_create = 0x04;
pl_FDT_item->month_create = 0x01;
pl_FDT_item->year_low_create= 0x09;
pl_FDT_item->year_high_create=0x20;
pl_FDT_item->second_modify = 0x00;
pl_FDT_item->minute_modify = 0x00;
pl_FDT_item->hour_modify = 0x12;
pl_FDT_item->date_modify = 0x04;
pl_FDT_item->month_modify = 0x01;
pl_FDT_item->year_low_modify =0x09;
pl_FDT_item->year_high_modify=0x20;
strcpy(pl_FDT_item->name,"free item");
__fill_little_32bit(pl_FDT_item->file_size,0,0);
__fill_little_32bit(pl_FDT_item->file_size,1,0);
if(loop == 0) //这是根目录项
{
//根目录项的next和previous指针用于把空闲块串起来。
//根目录项的previous指针指向FDT末项
__fill_little_32bit(pl_FDT_item->previous,0,block_capacity-1);
//根目录项的next指针指向第一个空闲项
__fill_little_32bit(pl_FDT_item->next,0,1);
//根目录项的file_size指针用途特殊,前4字节记录着空闲FDT表项数
__fill_little_32bit(pl_FDT_item->file_size,0,block_capacity-1);
//根目录项的file_size指针用途特殊,后4字节记录着总FDT表项数
__fill_little_32bit(pl_FDT_item->file_size,1,block_capacity);
//根目录项的父目录指针parent空着
__fill_little_32bit(pl_FDT_item->parent,0,cn_limit_uint32);
//根目录项的子目录指针fstart_dson空着
__fill_little_32bit(pl_FDT_item->fstart_dson,0,cn_limit_uint32);
//根目录是个只读目录
pl_FDT_item->mattr = cn_FS_ATTR_DIRECTORY + cn_FS_ATTR_READ_ONLY;
strcpy(pl_FDT_item->name,"root folder");
}else if(loop == block_capacity-1) //空闲的最后一项
{
//previous指针前一项
__fill_little_32bit(pl_FDT_item->previous,0,block_capacity-2);
//最后一项的next指针指向根目录项
__fill_little_32bit(pl_FDT_item->next,0,0);
__fill_little_32bit(pl_FDT_item->parent,0,cn_limit_uint32);
__fill_little_32bit(pl_FDT_item->fstart_dson,0,cn_limit_uint32);
}else
{
//previous指针指向前一项
__fill_little_32bit(pl_FDT_item->previous,0,loop - 1);
//next指针指向后一项
__fill_little_32bit(pl_FDT_item->next,0,loop + 1);
__fill_little_32bit(pl_FDT_item->parent,0,cn_limit_uint32);
__fill_little_32bit(pl_FDT_item->fstart_dson,0,cn_limit_uint32);
}
}
//把缓冲区写入flash块内
true_block = __DFFSD_write_new_block(DBX_flash_tag,
FDT_block_no,0,chip->block_size);
if(true_block == cn_limit_uint32) //如果写入错误
return false;
if(true_block != FDT_block_no) //如果发生了块交换
__DFFSD_update_MAT_item(DBX_flash_tag,FDT_block_no,true_block);
return true;
}
//----FDT表增加1块-------------------------------------------------------------
//功能:当FDT表项用完后,调用本函数增加1块存储器,并把新增加的存储器划分为一个
// 个FDT_item块,然后用双向链表连接起来,并连接到空闲表中去。
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
//返回:true=成功,false=失败,一般是因为没有空闲块
//-----------------------------------------------------------------------------
bool_t __DFFSD_add_FDT_block(struct st_DBX_flash_tag *DBX_flash_tag)
{
uint8_t *FDT_buf;
struct fdt_info *pl_FDT_item,FDT_item;
struct flash_chip *chip;
uint32_t FDT_item_new_start,free_item,new_block_no,true_block;
uint32_t block_capacity,last_block_no;
uint32_t loop;
if(DBX_flash_tag->valid_sum <= 2)
return false; //剩余可用块数小于等于2时,分配一块给FDT表是毫无意义的
chip = DBX_flash_tag->chip;
FDT_item_new_start = DBX_flash_tag->FDT_capacity;
block_capacity = chip->block_size / 256;
__DFFSD_read_FDT_item(DBX_flash_tag,0,&FDT_item);
new_block_no = __DFFSD_allocate_block(DBX_flash_tag); //申请一个flash块
if(new_block_no == cn_limit_uint32)
return false;
FDT_buf = chip->block_buf;
pl_FDT_item = (struct fdt_info*)FDT_buf;
//新申请块的第一项previous指针指向根目录项
__fill_little_32bit(pl_FDT_item->previous,0,0);
//新申请块的next指针指向新申请块的第二项
__fill_little_32bit(pl_FDT_item->next,0,FDT_item_new_start + 1);
pl_FDT_item = (struct fdt_info*)(FDT_buf + (block_capacity-1) * 256);
//新申请块的最后一项的previous指针指向倒数第二项
__fill_little_32bit(pl_FDT_item->previous,0,
FDT_item_new_start + loop -1);
if(0 == DBX_flash_tag->FDT_free_num) //已经没有空闲FDT_item
{
//根目录项的previous指针指向新申请块的末项
__fill_little_32bit(FDT_item.previous,0,
FDT_item_new_start + block_capacity-1);
//根目录项的next指针指向新申请块的首项
__fill_little_32bit(FDT_item.next,0,FDT_item_new_start);
//根目录项写入flash中
if(! __DFFSD_write_FDT_item(DBX_flash_tag,0,&FDT_item))
return false;
//新申请块的最后一项的next指针指向根目录项
__fill_little_32bit(pl_FDT_item->next,0,0);
}else //还剩余少许空闲FDT_item
{
//读第一个空闲FDT_item的条目号
free_item = __pick_little_32bit(FDT_item.next,0);
//根目录项的next指针指向新申请块的首项
__fill_little_32bit(FDT_item.next,0,FDT_item_new_start);
//根目录项写入flash
if(! __DFFSD_write_FDT_item(DBX_flash_tag,0,&FDT_item))
return false;
//读第一个空闲FDT项到缓冲区中
__DFFSD_read_FDT_item(DBX_flash_tag,free_item,&FDT_item);
//原第一个空闲项的向前指针指向新申请块的最后一项
__fill_little_32bit(FDT_item.previous,0,
FDT_item_new_start + block_capacity-1);
//原第一个空闲项写入flash
if(! __DFFSD_write_FDT_item(DBX_flash_tag,free_item,&FDT_item))
return false;
//新申请块的最后一项的next指针指向原第一个空闲项
__fill_little_32bit(pl_FDT_item->next,0,free_item);
}
for(loop=1; loop < block_capacity-1; loop++)
{//把新申请块除首末FDT条目以外的其他FDT条目连接起来
pl_FDT_item = (struct fdt_info*)(FDT_buf + loop * 256);
__fill_little_32bit(pl_FDT_item->previous,0,
FDT_item_new_start + loop - 1);
__fill_little_32bit(pl_FDT_item->next,0,
FDT_item_new_start + loop + 1);
}
true_block = __DFFSD_write_new_block(DBX_flash_tag,
new_block_no,0,chip->block_size);
if(true_block == cn_limit_uint32)
return false; //此时,FDT根目录项的指针已经改变并写入flash,但新块缓冲
//区却没有写入flash,将造成FDT的free项链断裂,错误可以在
//启动时查出,那时将会看到根目录项中第一个空闲项的号码大
//于MAT中FDT块的容量。---db,启动检查此项
//loop保存FDT首块的块号,用于定位MAT表中的FDT链
loop = DBX_flash_tag->DDR_FDSB;
do //本循环用于找到MAT表中FDT链的最后一块
{
last_block_no = loop;
loop = DBX_flash_tag->DDR_MAT[last_block_no].next;
}while(loop != last_block_no);
//把新申请块的实际写入的块号加入到MAT表中的FDT块号链中
__DFFSD_add_MAT_item(DBX_flash_tag,last_block_no,true_block);
DBX_flash_tag->FDT_capacity += block_capacity;
DBX_flash_tag->FDT_free_num += block_capacity;
if(!__DFFSD_write_DDR(DBX_flash_tag))
return false;
chip->erase_block(DBX_flash_tag->PCRB_no + DBX_flash_tag->start_block);
return true;
}
//----把一个FDT_item添加到空闲-------------------------------------------------
//功能: 把一个已经被孤立的FDT_item加入到空闲项链表中,成为第一个结点。
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
// FDT_item_no,被释放的条目号
//返回: 无
//-----------------------------------------------------------------------------
void __DFFSD_add_FDT_free_item(struct st_DBX_flash_tag *DBX_flash_tag,
uint32_t FDT_item_no)
{
uint32_t free_first;
struct fdt_info FDT_item;
__DFFSD_read_FDT_item(DBX_flash_tag,0,&FDT_item); //读出根目录项
DBX_flash_tag->FDT_free_num++;
//FDT表根目录项的file_size指针特殊用途:前4字节记录空闲FDT表项数
__fill_little_32bit(FDT_item.file_size,0,DBX_flash_tag->FDT_free_num);
free_first = __pick_little_32bit(FDT_item.next,0);
if(DBX_flash_tag->FDT_free_num == 1) //原空闲链表是空的
{
//根目录项的向前向后指针均指向目标项
__fill_little_32bit(FDT_item.next,0,FDT_item_no);
__fill_little_32bit(FDT_item.previous,0,FDT_item_no);
__DFFSD_write_FDT_item(DBX_flash_tag,0,&FDT_item); //写入根目录项
//读出被释放项
__DFFSD_read_FDT_item(DBX_flash_tag,FDT_item_no,&FDT_item);
//目标块的向前向后指针均指向根目录项
__fill_little_32bit(FDT_item.next,0,0);
__fill_little_32bit(FDT_item.previous,0,0);
FDT_item.mattr |= cn_FS_ATTR_DELETED;
//被修改项写入flash。
__DFFSD_write_FDT_item(DBX_flash_tag,FDT_item_no,&FDT_item);
//为最大限度保留数据恢复信息,不修改除链表以外的其他数据
}else //空闲链表非空
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -