⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mdr.c

📁 新一代基于事件的嵌入式操作系统dyos在三星的s3c44b0的arm芯片上的完整移植代码
💻 C
📖 第 1 页 / 共 4 页
字号:
//----------------------------------------------------
//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 + -