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

📄 ddr.c

📁 新一代基于事件的嵌入式操作系统dyos在三星的s3c44b0的arm芯片上的完整移植代码
💻 C
📖 第 1 页 / 共 5 页
字号:
            block_no_tab[busy_region[loop]] = block_no;
            pos_tab[block_no] = busy_region[loop];
        }
        busy_region[8]--;  //busy_region8指针指向原busy7.end的位置
        //下面把free8.invalid_num块copy到busy_region8.0的位置
        times_tab[busy_region[8]] = times_tab[free_region[8] + invalid_num]+1;
        block_no = block_no_tab[free_region[8] + invalid_num];
        block_no_tab[busy_region[8]] = block_no;
        pos_tab[block_no] = busy_region[8];
        //下面把保存的原busy0.end的信息copy到free8.invalid_num块
        times_tab[free_region[8] + invalid_num] = times_bak;
        block_no_tab[free_region[8]+invalid_num] = block_no_bak;
        pos_tab[block_no_bak] = free_region[8]+invalid_num;
        //下面根据块交换结果修改MAT表,block_no_bak保存的是原busy0.end的块号,
        //block_no保存的是该块被交换到的目标块号。
        __DFFSD_update_MAT_item(DBX_flash_tag,block_no_bak,block_no);
    }
    for(loop = 0; loop < invalid_num; loop++)//本循环把所有坏块转移到invalid_region
    {
        block_no = block_no_tab[free_region[8]+loop];
        __DFFSD_register_invalid(DBX_flash_tag,block_no);
    }
    return true;
}

//----简单分配一块------------------------------------------------------------
//功能: 与__allocate_block函数类似,但是不做任何块交换,而是直接从free[0]区取出
//      一块。如果free[0]空,则实际取到的可能是free[1]或更高区的块
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//返回: 块号,是文件柜的相对块号,若没有空闲块,返回-1
//----------------------------------------------------------------------------
uint32_t __DFFSD_allocate_block_simple(struct st_DBX_flash_tag *DBX_flash_tag)
{
    uint32_t block_no;
    uint32_t *block_no_tab;
    uint16_t *times_tab,times_bak;
    uint32_t *free_region;
    uint32_t target_region;
    if(DBX_flash_tag->free_sum== 0)
        return cn_limit_uint32;
    else
        DBX_flash_tag->free_sum--;
    block_no_tab = DBX_flash_tag->ART_block_no;   //取磨损块号表,与次数表同列
    times_tab = DBX_flash_tag->ART_times;         //取磨损次数表
    free_region = DBX_flash_tag->balance_region;  //第一个空闲分区
    times_bak =times_tab[0];        //读取free表0区第一块磨损次数
    //该块变成忙块后插入相应忙区,由于free[0]开始可能会有若干个空闲区,故不
    //能简单地认为free[0]区取出的块不改变磨损次数会出现在busy[0]区
    target_region = times_bak/128 + 9;      //取忙区的目标区号
    //读取free表0区第一块块号
    block_no = block_no_tab[0];
    //从第0区的位置0跳到第target_region区
    __DFFSD_ART_flip(DBX_flash_tag,0,target_region,0);
    return block_no;
}

//----分配一块----------------------------------------------------------------
//功能: 从free表中取出一块,并把该块放到busy表中。目标块的磨损次数不增量。如果:
//      1.空闲块全部集中在free_region[8]区,且busy_region[0]非空,就要进行坏块
//        磨损平衡替换。从busy_region[0]中取一块A,再从free_region[8]中取一块B,
//        A块的内容copy到B块,把B块放到busy_region[8]中。注意这个过程要涉及到
//        修改MAT表。
//      2.如果同时出现busy_region[0]和free_region[0]均空的现象,磨损表整体轮转
//        一圈,使busy_region[8]和free_region[8]均空。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//返回: 块号,是文件柜的相对块号,若没有空闲块,返回-1
//----------------------------------------------------------------------------
uint32_t __DFFSD_allocate_block(struct st_DBX_flash_tag *DBX_flash_tag)
{
    uint32_t block_no;
    uint32_t *block_no_tab;
    uint16_t *times_tab,times_bak;
    uint32_t *free_region;
    uint32_t target_region;
    if(DBX_flash_tag->free_sum== 0)
        return cn_limit_uint32;
    else
        DBX_flash_tag->free_sum--;
    block_no_tab = DBX_flash_tag->ART_block_no;   //取磨损块号表,与次数表同列
    times_tab = DBX_flash_tag->ART_times;   //取磨损次数表
    free_region = DBX_flash_tag->balance_region;        //第一个空闲分区
    if(free_region[0] == free_region[8])    //free[0~7]已经空
        __DFFSD_exchange_busy0_free8(DBX_flash_tag);  //调用写磨损平衡块交换函数
    times_bak =times_tab[0];//读取free表0区第一块磨损次数
//    times_bak++;    //磨损次数加1,注释掉,改为实际发生擦写时再增加。
    //该块变成忙块后插入end_region区,由于free[0]开始可能会有若干个空闲区,故不
    //能简单地认为free[0]区取出的块不改变磨损次数会出现在busy[0]区
    target_region = times_bak/128 + 9;
    //读取free表0区第一块块号
    block_no = block_no_tab[0];
    //从第0区的位置0跳到第target_region区
    __DFFSD_ART_flip(DBX_flash_tag,0,target_region,0);
    return block_no;
}

//----写DDR表到flash-----------------------------------------------------------
//功能: 根据DBX_flash_tag->writed_main表中的内容,把DDR表中需要写入的内容写
//      入到flash中DDR_main表中。
//      1.把DDR表写入到flash中,存储位置由DBL_main提供
//      2.如果产生坏块,则申请新块,并在DBL_main、MAT_main、MAT_bak中标记。
//      3.如果产生坏块,MAT_bak和MAT_main的内容都有修改,但只有which参数指定的
//        那个MAT表修改后的内容会在本次写入flash,而另一份在__DFFSD_write_DDR函
//        数中再次调用本函数完成写入
//      4.为简化算法,即使发生坏块替换,也不修改磨损次数,只在mat表中把标示坏块,把
//        新块标示为DDR块.这样,发生坏块替换时,只需要修改MAT表和DBL表就可以了.由于
//        模式次数无需精确平衡,这样做是允许的。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//      which,读取哪一个DDR表,0=DDR_main,1=DDR_bak
//返回: true=成功写入
//      false=失败,当写入遇到坏块,又没有空闲块可供分配时,会失败
//特注: 用循环写入,
//----------------------------------------------------------------------------
bool_t __DFFSD_write_DDR_exe(struct st_DBX_flash_tag *DBX_flash_tag,
                             ufast_t which)
{
    struct flash_chip *chip;    //芯片指针
    uint32_t loop,DDR_blocks,DDR_no,write_result;
    uint32_t write_len,completed = 0;
    uint32_t block_no,block_new,temp;
    bool_t *writed;         //指向是否完成写入的指针
    bool_t finished;
    struct MAT_table *MAT_item;
    uint32_t *DBL_buf;
    uint8_t *buf;
    uint32_t FDSB_start,ARB_start,ART_start,ART_end,MAT_start,offset;
    uint8_t block_attr;
    chip = DBX_flash_tag->chip; //取得文件柜所属芯片
    buf = chip->block_buf;
    //1份DDR表占用的块数,
    DDR_blocks = (DBX_flash_tag->DDR_size+chip->block_size-1)/chip->block_size;
    if(which == 0)
    {
        writed = DBX_flash_tag->writed_DDR_main;
        block_attr = cn_DDR_main_block;
        DBL_buf = DBX_flash_tag->DDR_DBL;
    }else
    {
        writed = DBX_flash_tag->writed_DDR_bak;
        block_attr = cn_DDR_bak_block;
        DBL_buf = DBX_flash_tag->DDR_DBL + DDR_blocks;
    }
    MAT_item = DBX_flash_tag->DDR_MAT;
    FDSB_start = DDR_blocks*4;
    ARB_start = FDSB_start + 4;
    ART_start = ARB_start +4;
    ART_end = ART_start + DBX_flash_tag->block_sum *2;
    MAT_start = __DFFSD_MAT_start(DBX_flash_tag);
    do
    {
        finished = true;    //假定本循环可以完成全部写入操作
        for(loop = 0; loop < DDR_blocks; loop++)
        {
            if(writed[loop] == true)
            {
                continue;                       //本块已经写入,跳过。
            }
            completed = loop * chip->block_size;
            offset = completed;
            if(loop == DDR_blocks-1)
                write_len = DBX_flash_tag->DDR_size - completed;
            else
                write_len = chip->block_size;

            while(offset - completed < write_len)
            {
                if(offset < FDSB_start)         //DBL
                {
                    __fill_little_32bit(buf+(offset-completed),0,
                                        DBL_buf[offset/4]);
                    offset +=4;
                }else if(offset < ARB_start)  //FDSB
                {
                    __fill_little_32bit(buf+(offset-completed),0,
                                        DBX_flash_tag->DDR_FDSB);
                    offset +=4;
                }else if(offset < ART_start) //ARB
                {
                    __fill_little_32bit(buf+(offset-completed),0,
                                        DBX_flash_tag->DDR_ARB);
                    offset +=4;
                }else if(offset < ART_end)   //ART
                {
                    __fill_little_16bit(buf+(offset-completed),0,
                                DBX_flash_tag->ART_times[(offset-ART_start)/2]);
                    offset +=2;
                }else if(offset < MAT_start)    //跳过对齐填充
                {
                    offset = MAT_start;
                }else if(offset <= DBX_flash_tag->DDR_size)
                {
                    temp = MAT_item->previous & 0x3fffffff;
                    temp += (uint32_t)MAT_item->attr<<30;
                    //向前指针
                    __fill_little_32bit(buf+(offset-completed),0,temp);
                    temp = MAT_item->next & 0x3fffffff;
                    temp += (uint32_t)MAT_item->attr>>2<<30;
                    //向后指针
                    __fill_little_32bit(buf+(offset-completed),1,temp);
                    MAT_item++;
                    offset +=8;
                }
            }

            block_no = DBL_buf[loop];
            //擦除目标块
            chip->erase_block(block_no + DBX_flash_tag->start_block);
            write_result = chip->write_data_with_ecc(
                                     block_no + DBX_flash_tag->start_block,
                                     0,chip->block_buf,write_len);    //块写入
            if( write_result == write_len)    //检测是否正确写入
            {
                __DFFSD_inc_abrasion_times(DBX_flash_tag,block_no);
                writed[loop] = true;    //正确写入则标记本块已经写入
            }else
            {//写入错误,产生了坏块,做下列处理:---db,此处未调试
                //block_no是新产生坏块的块号,block_new是替换坏块的好块块号
                block_new = __DFFSD_allocate_block(DBX_flash_tag);
                if(block_new == cn_limit_uint32)
                    return false;       //文件柜满,这种情况不多见
                writed[loop] = false;   //标记第loop块未写入
                finished = false;       //本循环没有完成写入
                //把坏块登记到擦除平衡表中,但没有写入到flash
                __DFFSD_register_invalid(DBX_flash_tag,block_no);

                //坏块在DBL中的位置,被新块块号覆盖
                DBL_buf[loop] = block_new;
                //计算DBL中存放block_new的位置在DDR表中的块号
                DDR_no = 4 * loop/chip->block_size;
                writed[DDR_no] = false;

                //更新MAT表中block_new块的属性
                MAT_item[block_new].attr = block_attr;
                //计算block_new在MAT表中位置处在DDR表中是第几块
                DDR_no = (MAT_start+block_new*8) / chip->block_size;
                //DDR_main中标记该块为未写入
                DBX_flash_tag->writed_DDR_main[DDR_no] = false;
                //DDR_bak中标记该块为未写入
                DBX_flash_tag->writed_DDR_bak[DDR_no] = false;

                //该MAT表中block_no块的属性为坏块
                MAT_item[block_no].attr = cn_invalid_block;
                //计算block_no在MAT表中位置处在DDR表中是第几块
                DDR_no=(MAT_start+block_no*8) / chip->block_size;
                //DDR_main中标记该块为未写入
                DBX_flash_tag->writed_DDR_main[DDR_no] = false;
                //DDR_bak中标记该块为未写入
                DBX_flash_tag->writed_DDR_bak[DDR_no] = false;
            }
        }
    }while(finished == false);
    return true;
}

//----写一个文件柜的DDR表-----------------------------------------------------
//功能:将buf缓冲区中的DDR表写入指定文件柜的DDR区
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//返回:true=成功执行,false=写入错误
//---------------------------------------------------------------------------
bool_t __DFFSD_write_DDR(struct st_DBX_flash_tag *DBX_flash_tag)
{

⌨️ 快捷键说明

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