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

📄 flashfile.c

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


//----把数据写入新块-----------------------------------------------------------
//功能: 把芯片的块缓冲区的内容写入到一个尚无有效数据的新块中,因写入前块内并无
//      有效数据,故无需动用掉电恢复块,如果在写入时遇到坏块,申请一个新块替换
//      之,并把坏块登记到MAT表中(并不把MAT写入到flash中),返回替换后的块号。
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
//      block_no,目标块号
//      offset,起始地址在块内的偏移量
//      size,写入缓冲区长度
//返回: 写入成功则返回实际写入的块号,
//      写入失败返回cn_limit_uint32,空间不足或者连续遇到10个坏块会导致失败
//-----------------------------------------------------------------------------
uint32_t __DFFSD_write_new_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;
    fail_counter = 0;
    DBX_start_block = DBX_flash_tag->start_block;
    result_block = block_no;
    do  //因写入过程可能产生坏块,故需要用循环,直到正确写入才退出
    {
        //查看是否需要擦除
        if(!chip->query_block_ready_with_ecc(
                                    result_block+DBX_start_block,
                                    offset,chip->block_buf+offset,size))
        {//需要擦除
            //擦除目标块
            chip->erase_block(result_block + DBX_start_block);
            //把数据写入目标块中
            write_result = chip->write_data_with_ecc(
                                result_block+DBX_start_block,
                                offset,chip->block_buf+offset,size);
        }else   //不需要擦除,新申请的块刚好是一个已经被擦除的块。
        {
            //直接把数据写入到目标块中
            write_result = chip->write_data_with_ecc(
                                result_block + DBX_start_block,
                                offset,chip->block_buf+offset,size);
        }
        if(write_result != size)   //写入失败
        {
            fail_counter++;     //写入失败次数增量
            __DFFSD_register_invalid(DBX_flash_tag,result_block);   //登记坏块
            //分配新块,必须使用简易分配法,否则容易造成连环套
            result_block = __DFFSD_allocate_block_simple(DBX_flash_tag);
            if(result_block == cn_limit_uint32) //分配失败(无空闲块)
            {
                return cn_limit_uint32;         //返回错误
            }
        }else                   //成功写入
        {
            //当然了,擦写一次,目标块的磨损次数就加1
            //即使无需擦除,这也是新申请的一块的第一次写入,磨损次数自然也要加1
            __DFFSD_inc_abrasion_times(DBX_flash_tag,result_block);
            break;
        }
    }while(fail_counter <= 10);     //以连续遇到10个坏块为异常退出条件
    if(fail_counter > 10)           //因10次坏块而结束do-while循环
        return cn_limit_uint32;
    else                            //数据已经正确写入
        return result_block;
}

//----移动文件读指针-----------------------------------------------------------
//功能: 把一个文件的读指针移动到一个新位置
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
//      fp,目标文件指针
//      new_ptr,新的读指针
//返回: true=成功,false=有错误
//-----------------------------------------------------------------------------
bool_t __DFFSD_move_file_read_ptr(struct st_DBX_flash_tag *DBX_flash_tag,
                            djyfs_file *fp,sint64_t new_ptr)
{
    if(new_ptr > fp->file_size)
        return false;

    switch (fp->open_mode)
    {
        case enum_r_rb:
        {
            fp->read_ptr = new_ptr;             //读位置
        }break;
        case enum_w_wb:
        {
            return false;                       //读位置无效
        }break;
        case enum_a_ab:
        {
            return false;                       //读位置无效
        }break;
        case enum_r_rb_plus:
        {
            fp->read_ptr = new_ptr;             //读位置
            fp->write_ptr = new_ptr;            //写位置
        }break;
        case enum_w_wb_plus:
        {
            fp->read_ptr = new_ptr;             //读位置
            fp->write_ptr = new_ptr;            //写位置
        }break;
        case enum_a_ab_plus:
        {
            fp->read_ptr = new_ptr;             //读位置
        }break;
        default: return false;
    }
    return true;
}

//----移动文件写指针-----------------------------------------------------------
//功能: 把一个文件的写指针移动到一个新位置
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
//      fp,目标文件指针
//      new_ptr,新的写指针
//返回: true=成功,false=有错误
//-----------------------------------------------------------------------------
bool_t __DFFSD_move_file_write_ptr(struct st_DBX_flash_tag *DBX_flash_tag,
                             djyfs_file *fp,sint64_t new_ptr)
{
    switch (fp->open_mode)
    {
        case enum_r_rb:
        {
            return false;                       //只读文件,写位置无效
        }break;
        case enum_w_wb:
        {
            fp->write_ptr = new_ptr;            //写位置
        }break;
        case enum_a_ab:
        {
            fp->write_ptr = new_ptr;            //写位置
        }break;
        case enum_r_rb_plus:
        {
            fp->read_ptr = new_ptr;             //读位置
            fp->write_ptr = new_ptr;            //写位置
        }break;
        case enum_w_wb_plus:
        {
            fp->read_ptr = new_ptr;             //读位置
            fp->write_ptr = new_ptr;            //写位置
        }break;
        case enum_a_ab_plus:
        {
            fp->write_ptr = new_ptr;            //写位置
        }break;
        default: return false;
    }
    if(new_ptr > fp->file_size)       //写指针超出文件长度
    {
        //在FDT表中修改文件长度
       __DFFSD_update_FDT_file_size(DBX_flash_tag,fp,fp->write_ptr);
        fp->file_size = fp->write_ptr;  //用写指针覆盖文件长度
    }
    return true;
}

//----写缓冲区写入flash--------------------------------------------------------
//功能: 把文件写缓冲区的数据写入flash中
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
//      fp,被操作的文件指针
//返回:实际写入flash的字节数
//-----------------------------------------------------------------------------
uint32_t __DFFSD_write_buf_to_flash(struct st_DBX_flash_tag *DBX_flash_tag,
                                    struct file_rsc *fp)
{
    struct flash_chip *chip;
    struct file_access_tag access_tag;
    sint64_t wr_point;
    uint32_t completed = 0,write_len;
    uint32_t offset_start;
    uint32_t block_no,start_block,end_block,loop;
    uint32_t true_block,last_block;
    uint32_t buffed_data; //文件写缓冲区中的数据量和剩余数据量
    chip = DBX_flash_tag->chip;     //取文件柜(文件)所属芯片

    if(fp->p_write_buf != NULL)
    {
        buffed_data = ring_check(fp->p_write_buf); //检查写缓冲区中的数据量
        if(buffed_data == 0)        //写缓冲区没有数据
            return 0;
    }else
        return 0;       //没有写缓冲区
    wr_point = fp->write_ptr-buffed_data;   //计算开始写入数据的位置
    //计算起始写位置处于文件内第几块
    start_block = wr_point /chip->block_size;
    offset_start = wr_point % chip->block_size; //计算起始偏移
    //计算终止读写位置处于文件内第几块
    end_block = (fp->write_ptr - 1)/chip->block_size;
    __DFFSD_get_access_info(DBX_flash_tag,fp,&access_tag);
    //定位写入点的块号,文件柜内的相对块号。
    block_no = access_tag.write_block_no;
    last_block = access_tag.last_block_no;
    for(loop = start_block; loop <= end_block; loop++)
    {
        if((wr_point >= access_tag.true_size) && (wr_point != 0))
        {
            //分配一个新块
            block_no = __DFFSD_allocate_block(DBX_flash_tag);
            if(block_no == cn_limit_uint32) //分配失败(无空闲块)
                break;
        }
        //计算本次写入的数据长度
        if(buffed_data - completed > chip->block_size - offset_start)
            write_len = chip->block_size - offset_start;
        else
            write_len = buffed_data - completed;
        ring_read(fp->p_write_buf,chip->block_buf+offset_start,write_len);
        if(wr_point >= access_tag.true_size)    //追加数据
        {
            if(offset_start == 0)   //待写入的块内尚无有效数据
            {
                //写入目标块
                true_block = __DFFSD_write_new_block(DBX_flash_tag,block_no,
                                                        0,write_len);
                if(true_block != cn_limit_uint32)       //正确写入
                {
                    if(wr_point != 0)
                        __DFFSD_add_MAT_item(DBX_flash_tag,last_block,true_block);
                }else       //写入错误
                    break;
            }else                   //虽是追加,但待写入的块已经有部分有效数据
            {
                //写入目标块
                true_block = __DFFSD_write_append_block(DBX_flash_tag,block_no,
                                                offset_start,write_len);
                if(true_block != cn_limit_uint32)
                {//正确写入
                    if(true_block != block_no)   //写入时发生了块替换
                        __DFFSD_update_MAT_item(DBX_flash_tag,block_no,true_block);
                }else       //写入错误
                    break;
            }
            last_block = true_block;
            access_tag.true_size += write_len;
            chip->erase_block(DBX_flash_tag->PCRB_no
                              + DBX_flash_tag->start_block);
        }else   //在文件的中间写入,若需擦除就需要使用PCRB块进行保护
        {
            //写入目标块
            true_block = __DFFSD_write_update_block(DBX_flash_tag,block_no,
                                            offset_start,write_len);
            if(true_block != cn_limit_uint32)   //正确写入
            {
                if(true_block != block_no)   //写入时发生了块替换
                    __DFFSD_update_MAT_item(DBX_flash_tag,block_no,true_block);
            }else       //写入错误
                break;
            //确定下一循环写入点的块号,文件柜内的相对块号。
            block_no = DBX_flash_tag->DDR_MAT[block_no].next;
            chip->erase_block(DBX_flash_tag->PCRB_no
                              + DBX_flash_tag->start_block);
        }

⌨️ 快捷键说明

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