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

📄 flashfile.c

📁 新一代基于事件的嵌入式操作系统dyos在三星的s3c44b0的arm芯片上的完整移植代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        completed += write_len;
        wr_point += write_len;
        offset_start = 0;   //第二块开始,起始偏移地址肯定是0
    }
    __DFFSD_write_DDR(DBX_flash_tag);//把DDR表的变化写入flash中(DDR表可能没变化)
    return completed;
}

//----读操作前同步文件缓冲区---------------------------------------------------
//功能: 执行文件写操作之前,调用本函数同步缓冲区。
//参数: DBX_flash_tag,被操作的flash文件柜的存储媒体标签
//      fp,目标文件指针
//      read_len,欲读取长度
//返回: true=成功,false=有错误
//特别说明: struct file_rsc中有home_left,通过它也是可以很快找到该文件所属的dbx
//          的,但home_left是左手句柄,而flash_driver处于文件系统的右手,应该禁
//          止它访问左手句柄,故需要文件系统提供DBX_flash_tag指针
//-----------------------------------------------------------------------------
bool_t __DFFSD_sync_buf_before_read(struct st_DBX_flash_tag *DBX_flash_tag,
                              djyfs_file *fp,uint32_t read_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:  //读写位置相同,若写缓冲区有数据,必须写到flash
        case enum_w_wb_plus:  //与en_r_rb_plus处理方式相同
        {
            __DFFSD_write_buf_to_flash(DBX_flash_tag,fp);
        }break;
        case enum_a_ab_plus:  //追加写,可读。如果读位置与写缓冲区有交错则把写缓
                            //冲区写入flash,否则什么也不干
        {
            if(fp->read_ptr + read_len > fp->write_ptr)
                __DFFSD_write_buf_to_flash(DBX_flash_tag,fp);
        }break;
        default:break;
    }
    return true;
}


//----写入flash文件------------------------------------------------------------
//功能:把缓冲区中的数据写入文件,执行下列操作:
//      1、如果写缓冲区有足够的空间,把数据写入写缓冲区即可。
//      2、如果写缓冲区没有足够的空间,连同写缓冲区原有数据和输入缓冲区中的数据
//         一并写入flash
//      3、写入完成后检查读缓冲区是否需要同步并执行之。
//      4、检查FDT表和DDR表是否需要修改并执行之
//参数:buf,输入缓冲区
//      len,本次写入的数据量
//      fp,被操作的文件指针
//返回:本次写入的数据量,不包含写缓冲区中原有的数据
//注:   本函数并没有先调用__DFFSD_write_buf_to_flash函数,再写buf中的内容,那样
//      可能需要多一次调用flash写操作,效率低;而是把写缓冲区的数据与buf中的数据
//      合并一次写入flash.
//-----------------------------------------------------------------------------
uint32_t DFFSD_write_file(struct file_rsc *fp,uint8_t *buf,uint32_t len)
{
    struct flash_chip *chip;
    struct st_DBX_device_tag *DBX_device_tag;
    struct st_DBX_flash_tag *DBX_flash_tag;
    struct file_access_tag access_tag;
    uint32_t completed = 0,write_len,write_sum;
    sint64_t wr_point;
    uint32_t offset_start;
    uint32_t block_no,start_block,end_block,loop,temp;
    uint32_t true_block,last_block;
    uint32_t buffed_data,spare_len; //文件写缓冲区中的数据量和剩余数据量
    if((fp==NULL)||(len==0)||(buf==NULL))
        return 0;
    DBX_device_tag = (struct st_DBX_device_tag *)(fp->home_DBX->private_tag);
    //文件柜指针
    DBX_flash_tag = (struct st_DBX_flash_tag *)DBX_device_tag->DBX_medium_tag;
    chip = DBX_flash_tag->chip;     //取文件柜(文件)所属芯片

    buffed_data = ring_check(fp->p_write_buf); //检查缓冲区中的数据量
    if(ring_capacity(fp->p_write_buf) - buffed_data >= len)
    {//缓冲区内有足够的容量,直接把数据写到缓冲区即可。
        completed = ring_write(fp->p_write_buf,(uint8_t*)buf,len);
    }else
    {
        //如果缓冲区没有足够的容量,则把本次需要写入的数据连同缓冲区原来的数据
        //一并写入flash,下面开始执行写入操作。
        //计算连缓冲区中的数据在一起,一共要写入flash的数据量
        write_sum = len + buffed_data;
        spare_len = buffed_data;        //缓冲区剩余数据量
        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 + len -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(write_sum - completed > chip->block_size - offset_start)
                write_len = chip->block_size - offset_start;
            else
                write_len = write_sum - completed;
            if(spare_len != 0)  //写缓冲区里还有数据
            {
                temp = ring_read(fp->p_write_buf,
                                 chip->block_buf+offset_start,write_len);
                spare_len -= temp;  //写缓冲区减去实际读出的数据量
                //实际读出的数据量比write_len少,说明本次读已经把写缓冲区读空。
                if(temp != write_len)
                {
                    //继续从输入缓冲区中拷贝数据
                    memcpy(chip->block_buf+temp+offset_start,
                                buf,write_len-temp);
                }
            }else   //写缓冲区已经空,从输入缓冲区拷贝数据
                memcpy(chip->block_buf+offset_start,
                                       buf+completed-buffed_data,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;
                wr_point += 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;
                wr_point += write_len;
                if(wr_point > access_tag.true_size)
                    access_tag.true_size = wr_point;
                chip->erase_block(DBX_flash_tag->PCRB_no
                                  + DBX_flash_tag->start_block);
            }
            completed += write_len;
            offset_start = 0;   //第二块开始,起始偏移地址肯定是0
        }
    }
    if((completed - buffed_data) > 0)      //写入有数据
    {
        __DFFSD_sync_buf_after_write(DBX_flash_tag,fp,completed-buffed_data);
        __DFFSD_move_file_write_ptr(DBX_flash_tag,fp,
                                    fp->write_ptr + completed-buffed_data);
    }
    __DFFSD_write_DDR(DBX_flash_tag);//如果DDR表有变化,写入flash中
    return completed - buffed_data;
}
//----读flash文件--------------------------------------------------------------
//功能;把文件中的数据读入到缓冲区中,执行以下操作
//      1、看读缓冲区中有没有数据,有则读入到接收缓冲区中
//      2、若读缓冲区中的数据量不足或没有数据,则从flash中补充读取,并按照不越块
//         边界为限最大限度地填写读缓冲区
//      3、读出完成后看是否需要同步写缓冲区并执行之
//参数:buf,输入缓冲区
//      len,读出的数据量
//      fp,被操作的文件指针
//返回:实际读取的字节数
//-----------------------------------------------------------------------------
uint32_t DFFSD_read_file(struct file_rsc *fp,uint8_t *buf,uint32_t len)
{
    struct flash_chip *chip;
    struct st_DBX_device_tag *DBX_device_tag;
    struct st_DBX_flash_tag *DBX_flash_tag;
    uint32_t completed = 0,read_len,result_len;
    uint32_t offset_start;
    uint32_t block_no,start_block,end_block,loop;
    uint32_t read_result;
    if((fp==NULL)||(len==0)||(buf==NULL))
        return 0;
    DBX_device_tag = (struct st_DBX_device_tag *)(fp->home_DBX->private_tag);
    //文件柜指针
    DBX_flash_tag = (struct st_DBX_flash_tag *)DBX_device_tag->DBX_medium_tag;
    __DFFSD_sync_buf_before_read(DBX_flash_tag,fp,len);
    chip = DBX_flash_tag->chip;     //取文件柜(文件)所属芯片
    //计算起始读写位置处于文件内第几块
    start_block = fp->read_ptr/chip->block_size;
    //计算终止读写位置处于文件内第几块
    end_block = (fp->read_ptr + len -1)/chip->block_size;
    offset_start = fp->read_ptr % chip->block_size;
    if(fp->read_ptr + len >fp->file_size)
        result_len = fp->file_size - fp->read_ptr;
    else
        result_len = len;
    //定位读出点的块号,文件柜内的相对块号。
    block_no = __DFFSD_locate_block(DBX_flash_tag,fp,fp->read_ptr);
    for(loop = start_block; loop <= end_block; loop++)
    {
        if(result_len - completed > chip->block_size - offset_start)
            read_len = chip->block_size - offset_start;
        else
            read_len = result_len - completed;
        //读出目标块
        read_result =chip->read_data_with_ecc(
                                block_no + DBX_flash_tag->start_block,
                                offset_start,buf+completed,read_len);
        if(read_result == 2)    //读出错误,坏块
        {
            return completed;   //读出时发现坏块如何处理呢?---db
        }
        completed += read_len;
        offset_start = 0;   //第二块开始,起始偏移地址肯定是0
        block_no = DBX_flash_tag->DDR_MAT[block_no].next;
    }
    fp->read_ptr += completed;
    return completed;
}

//----刷写缓冲区---------------------------------------------------------------
//功能: 把文件写缓冲区的数据写入flash
//参数:fp,被操作的文件指针
//返回:实际写入flash的字节数
//-----------------------------------------------------------------------------
uint32_t DFFSD_flush_file(struct file_rsc *fp)
{
    struct st_DBX_device_tag *DBX_device_tag;
    struct st_DBX_flash_tag *DBX_flash_tag;
    if(fp==NULL)
        return 0;
    DBX_device_tag = (struct st_DBX_device_tag *)(fp->home_DBX->private_tag);
    //文件柜指针
    DBX_flash_tag = (struct st_DBX_flash_tag *)DBX_device_tag->DBX_medium_tag;
    return __DFFSD_write_buf_to_flash(DBX_flash_tag,fp);
}

//----查询文件可读数据量-------------------------------------------------------

⌨️ 快捷键说明

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