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

📄 flashfile.c

📁 新一代基于事件的嵌入式操作系统dyos在三星的s3c44b0的arm芯片上的完整移植代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    //获取文件所属芯片
    chip = DBX_flash_tag->chip;
    //读出文件的目录项
    __DFFSD_read_FDT_item(DBX_flash_tag,(uint32_t)fp->file_medium_tag,&FDT_item);
    //从目录项中取文件首块块号
    loop = __pick_little_32bit(FDT_item.fstart_dson,0);
    do
    {
        next_block = loop;
        loop = DBX_flash_tag->DDR_MAT[next_block].next;
    }while(loop != next_block);
    return next_block;
}

//----获取文件访问信息---------------------------------------------------------
//功能: 提取用于访问文件所需的位置信息,包括读位置块号,写位置块号,文件占用块
//      数,以及文件最后一块的块号。
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
//      fp,文件指针,调用方需确保是文件而不是目录
//      access_tag,用于返回结果的指针
//返回: 在access_tag中返回各种参数
//----------------------------------------------------------------------------
void __DFFSD_get_access_info(struct st_DBX_flash_tag *DBX_flash_tag,
                            struct file_rsc *fp,
                            struct file_access_tag *access_tag)
{
    uint32_t block,next_block,r_block,w_block,blocks=0;
    struct flash_chip *chip;
    struct fdt_info FDT_item;

    //获取文件所属芯片
    chip = DBX_flash_tag->chip;
    r_block = fp->read_ptr / chip->block_size;
    w_block = fp->write_ptr / chip->block_size;
    //读出文件的目录项
    __DFFSD_read_FDT_item(DBX_flash_tag,(uint32_t)fp->file_medium_tag,&FDT_item);
    //从目录项中取文件首块块号
    next_block = __pick_little_32bit(FDT_item.fstart_dson,0);
    //读文件真实尺寸,为防止符号扩展导致不必要的麻烦,按无符号数移位。
    //true_size只反映flash中的数据,不包括写缓冲区中的数据
    access_tag->true_size = __pick_little_32bit(FDT_item.file_size,0)
            +((uint64_t)__pick_little_32bit(FDT_item.file_size,1)<<32);
    do
    {
        block = next_block;
        if(blocks == r_block)
            access_tag->read_block_no = block;
        if(blocks == w_block)
            access_tag->write_block_no = block;
        blocks++;
        next_block = DBX_flash_tag->DDR_MAT[next_block].next;
    }while(block != next_block);
    access_tag->last_block_no = block;
    return ;
}

//----写操作后同步文件缓冲区---------------------------------------------------
//功能: 执行文件写操作之后,调用本函数同步缓冲区。
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
//      fp,目标文件指针
//      write_len,实际写入长度
//返回: true=成功,false=有错误
//-----------------------------------------------------------------------------
bool_t __DFFSD_sync_buf_after_write(struct st_DBX_flash_tag *DBX_flash_tag,
                               djyfs_file *fp,uint32_t write_len)
{
    switch(fp->open_mode)
    {
        case enum_r_rb:   //只读文件,无需操作
        {
        }break;
        case enum_w_wb:   //只写文件,无需操作
        {
        }break;
        case enum_a_ab:   //只写文件,无需操作
        {
        }break;
        case enum_r_rb_plus:  //读写位置相同,若读缓冲区有数据,删掉write_len长度
        case enum_w_wb_plus:  //的数据量。
        {
            ring_dumb_read(fp->p_read_buf,write_len);
        }break;
        case enum_a_ab_plus:  //读写位置可以不同,读前调用__sync_buf_before_read
        {                   //函数已经保证写缓冲区不会与读缓冲区冲突,新写入的
                            //数据肯定不会覆盖读缓冲区中原有数据,故无需处理。
        }break;
        default:break;
    }
    return true;
}

//----改写一块:覆盖数据--------------------------------------------------------
//功能: 把芯片块缓冲区的内容写入flash中某块,覆盖被写入的位置的原有数据,如果
//      在写入时遇到坏块,申请一个新块替换之,并把坏块登记到MAT表中(并不把MAT写
//      入到flash中),返回替换后的块号。写入前,先看看是否需要擦除,如果需要擦除
//      则要看该块是否已经在busy[8]区,如是,还要用"释放-重新申请-擦写"的过程进
//      行块替换。待写入的数据是块缓冲区从offset开始的size个字节。
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
//      block_no,目标块号
//      offset,起始地址在块内的偏移量
//      size,写入缓冲区长度
//返回: 写入成功则返回实际写入的块号,
//      写入失败返回cn_limit_uint32,空间不足或者连续遇到10个坏块会导致失败
//-----------------------------------------------------------------------------
uint32_t __DFFSD_write_update_block(struct st_DBX_flash_tag *DBX_flash_tag,
                             uint32_t block_no,uint32_t offset,uint32_t size)
{
    uint32_t fail_counter;  //如果连续分配10块均不能正确写入,则返回
    uint32_t write_result,result_block,DBX_start_block;
    struct flash_chip *chip = DBX_flash_tag->chip;
    uint8_t *buf;
    bool_t block_ready,write_success;

    buf = chip->block_buf;
    DBX_start_block = DBX_flash_tag->start_block;
    fail_counter = 0;
    result_block = block_no;
    if(DBX_flash_tag->nand_ecc)
        block_ready = chip->query_block_ready_with_ecc(
                                    result_block+DBX_start_block,
                                    offset,buf+offset,size);
    else
        block_ready = chip->query_block_ready_no_ecc(
                                    result_block+DBX_start_block,
                                    offset,buf+offset,size);
    if(offset != 0)
        //把目标块的数据读到块缓冲区中,先读offset以前的部分
        chip->read_data_with_ecc(block_no+DBX_start_block,
                                 0,buf,offset);
    if(offset+size != chip->block_size)
        //再读有效部分以后的部分
        chip->read_data_with_ecc(block_no+DBX_start_block,
                                 offset+size,buf+offset+size,
                                 chip->block_size-offset-size);

    //把数据写入到掉电恢复块,
    chip->write_PCRB(DBX_flash_tag->PCRB_no+DBX_start_block,
                     block_no + DBX_start_block,buf);
    do  //因写入过程可能产生坏块,故需要用循环,直到正确写入才退出
    {
        if((fail_counter == 0) && (block_ready)) //无需擦除的情况
        {
            write_result = chip->write_data_with_ecc(
                                result_block + DBX_start_block,
                                offset,buf+offset,size);
            if(write_result == size)
                write_success = true;
            else
                write_success = false;
        }else           //需要擦除的情况
        {
            chip->erase_block(result_block+DBX_start_block);//擦除块
            //写入目标块,整块写入
            write_result = chip->write_data_with_ecc(
                                result_block + DBX_start_block,
                                0,buf,chip->block_size);
            if(write_result == chip->block_size)
            {
                //磨损次数增量
                __DFFSD_inc_abrasion_times(DBX_flash_tag,result_block);
                write_success = true;
            }else
                write_success = false;
        }
        if(!write_success)   //写入失败,坏块
        {
            fail_counter++;     //写入失败次数增量
            //登记坏块到磨损表
            __DFFSD_register_invalid(DBX_flash_tag,result_block);
            //分配新块,必须使用简易分配法,否则容易造成连环套
            result_block = __DFFSD_allocate_block_simple(DBX_flash_tag);
            //注意,掉电恢复块的目标块号无需修改,因为此时MAT表以及可能需要修改
            //的FDT还没有改变。
            if(result_block == cn_limit_uint32) //分配失败(无空闲块)
            {
                return cn_limit_uint32;         //返回错误
            }
        }else       //成功写入
        {
            break;
        }
    }while(fail_counter <= 10); //以连续遇到10个坏块为异常退出条件
    if(fail_counter > 10)           //因10次坏块而结束do-while循环
        return cn_limit_uint32;
    else                            //数据已经正确写入
        return result_block;
}

//----改写一块:添加数据--------------------------------------------------------
//功能: 把芯片块缓冲区的内容写入flash中某块,被写入的位置原来没有有效数据,如果
//      在写入时遇到坏块,申请一个新块替换之,并把坏块登记到MAT表中(并不把MAT写
//      入到flash中),返回替换后的块号。写入前,先看看是否需要擦除,如果需要擦除
//      则要看该块是否已经在busy[8]区,如是,还要用"释放-重新申请-擦写"的过程进
//      行块替换。待写入的数据是块缓冲区从offset开始的size个字节。
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
//      block_no,目标块号
//      offset,起始地址在块内的偏移量
//      size,写入缓冲区长度
//返回: 写入成功则返回实际写入的块号,
//      写入失败返回cn_limit_uint32,空间不足或者连续遇到10个坏块会导致失败
//-----------------------------------------------------------------------------
uint32_t __DFFSD_write_append_block(struct st_DBX_flash_tag *DBX_flash_tag,
                             uint32_t block_no,uint32_t offset,uint32_t size)
{
    uint32_t fail_counter;  //如果连续分配10块均不能正确写入,则返回
    uint32_t write_result,result_block,DBX_start_block;
    struct flash_chip *chip = DBX_flash_tag->chip;
    uint8_t *buf;
    bool_t block_ready,PCRB_writed=false,write_success;

    buf = chip->block_buf;
    DBX_start_block = DBX_flash_tag->start_block;
    fail_counter = 0;
    result_block = block_no;
    if(DBX_flash_tag->nand_ecc)
        block_ready = chip->query_block_ready_with_ecc(
                                    result_block+DBX_start_block,
                                    offset,buf+offset,size);
    else
        block_ready = chip->query_block_ready_no_ecc(
                                    result_block+DBX_start_block,
                                    offset,buf+offset,size);

    do  //因写入过程可能产生坏块,故需要用循环,直到正确写入才退出
    {
        if((fail_counter == 0) && (block_ready))
        {
            write_result = chip->write_data_with_ecc(
                                    result_block + DBX_start_block,
                                    offset,buf+offset,size);
            if(write_result == size)
                write_success = true;
            else
                write_success = false;
        }else
        {
            if(!PCRB_writed)
            {
                if(offset != 0)
                    //把目标块的数据读到块缓冲区中,先读offset以前的部分
                    chip->read_data_with_ecc(block_no+DBX_start_block,
                                             0,buf,offset);
                if(offset+size != chip->block_size)
                    //再读有效部分以后的部分
                    chip->read_data_with_ecc(block_no+DBX_start_block,
                                             offset+size,buf+offset+size,
                                             chip->block_size-offset-size);
                //把数据写入到掉电恢复块,
                chip->write_PCRB(DBX_flash_tag->PCRB_no+DBX_start_block,
                                 block_no + DBX_start_block,buf);
                PCRB_writed = true;
            }
            chip->erase_block(result_block+DBX_start_block);
            //写入目标块,整块写入
            write_result = chip->write_data_with_ecc(
                                result_block + DBX_start_block,
                                0,buf,chip->block_size);
            if(write_result == chip->block_size)
            {
                //磨损次数增量
                __DFFSD_inc_abrasion_times(DBX_flash_tag,result_block);
                write_success = true;
            }else
                write_success = false;
        }
        if(!write_success)   //写入失败,坏块
        {
            fail_counter++;     //写入失败次数增量
            //登记坏块到磨损表
            __DFFSD_register_invalid(DBX_flash_tag,result_block);
            //分配新块,必须使用简易分配法,否则容易造成连环套
            result_block = __DFFSD_allocate_block_simple(DBX_flash_tag);
            //注意,掉电恢复块的目标块号无需修改,因为此时MAT表以及可能需要修改

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -