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

📄 ddr.c

📁 新一代基于事件的嵌入式操作系统dyos在三星的s3c44b0的arm芯片上的完整移植代码
💻 C
📖 第 1 页 / 共 5 页
字号:
                u32_temp = DBX_flash_tag->DDR_DBL[temp];
                if(u32_temp == old_block_no)
                {
                    DBX_flash_tag->DDR_DBL[temp] = new_block_no;
                    break;
                }
            }
            //计算DBL表被修改的位置处在DDR表中是第几块
            temp= temp*4 / chip->block_size;
            //DDR_main中标记该块为未写入
            DBX_flash_tag->writed_DDR_main[temp] = false;
        }break;
        case cn_DDR_bak_block : //原old_block_no块是DDR_bak块
        {
            //new_block_no设置为DDR_main块
            MAT_item[new_block_no].attr = cn_DDR_bak_block;
            DDR_blocks = (DBX_flash_tag->DDR_size + chip->block_size -1)
                                / chip->block_size;     //计算DDR表所占的块数
            for(temp = 0; temp < DDR_blocks; temp++)
            {
                u32_temp = DBX_flash_tag->DDR_DBL[DDR_blocks + temp];
                if(u32_temp == old_block_no)
                    DBX_flash_tag->DDR_DBL[DDR_blocks + temp] = new_block_no;
            }
            //计算DDR表被修改的位置处在DDR表中是第几块
            temp= (DDR_blocks+ temp)*4 / chip->block_size;
            //DDR_main中标记该块为未写入
            DBX_flash_tag->writed_DDR_bak[temp] = false;
        }break;
        case cn_PCRB_block :     //原old_block_no块是掉电恢复块,再说吧
        {
        }break;
        default : break;
    }
    //如果原old_block_no是某文件的首块,还要修改fdt(目录)表中该文件对应的条目
    //如果原old_block_no是fdt表的首块,还要修改DDR表中的FDSB
}

//----磨损平衡表轮转-----------------------------------------------------------
//功能:busy_region[0]和free_region[0]均空的时候,磨损平衡表便轮转一圈,使
//      busy_region[8]和free_region[8]变成空的。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//返回:无
//-----------------------------------------------------------------------------
void __DFFSD_whirl_ART_table(struct st_DBX_flash_tag *DBX_flash_tag)
{
    struct flash_chip *chip = DBX_flash_tag->chip;
    uint32_t *busy_region,*free_region,*balance_region;
    uint32_t loop,ARB_block;
    uint16_t whirl_regions;
    uint16_t *times_tab;
    times_tab = DBX_flash_tag->ART_times;               //取磨损次数表
    busy_region = &DBX_flash_tag->balance_region[9];    //第一个忙分区
    free_region = DBX_flash_tag->balance_region;        //第一个空闲分区
    balance_region = DBX_flash_tag->balance_region;
    for(whirl_regions = 0; whirl_regions < 8; whirl_regions++)
    {//检查需轮转的区的数量,即从busy和free的0区开始,检查free和busy同时为空的
     //区的数量,直到第一个不同时为空的区为止。
        if((busy_region[whirl_regions] != busy_region[whirl_regions+1])
              || (free_region[whirl_regions] != free_region[whirl_regions+1]))
            break;
    }
    if(whirl_regions == 0)
        return;
    DBX_flash_tag->DDR_ARB += whirl_regions * 128;//磨损次数基数增加轮转区数
    //计算DDR_ARB在MAT表中位置处在DDR表中是第几块
    ARB_block = (DBX_flash_tag->DDR_size + chip->block_size -1)
                    / chip->block_size * 4 + 4;
    ARB_block = ARB_block / chip->block_size;
    //DDR_bak中标记该块为未写入
    DBX_flash_tag->writed_DDR_bak[ARB_block] = false;
    //DDR_main中标记该块为未写入
    DBX_flash_tag->writed_DDR_main[ARB_block] = false;
    for(loop = 0; loop < balance_region[18]; loop++)
    {
        times_tab[loop] -= whirl_regions*128;   //所有块的磨损次数减少轮转区数
    }
    for(loop = 1; loop <= 9 - whirl_regions; loop++)
    {
        busy_region[loop] = busy_region[loop+whirl_regions];
        free_region[loop] = free_region[loop+whirl_regions];
    }
    for(; loop < 9; loop++)
    {
        busy_region[loop] = balance_region[18];
        free_region[loop] = busy_region[0];
    }
}

//----磨损次数加1--------------------------------------------------------------
//功能: 当某块的磨损次数增加时,调用本函数,把这种变化登记到内存中磨损平衡表中,
//      但并不写入到flash。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//      block_no,被增加次数的块
//返回: 无
//----------------------------------------------------------------------------
void __DFFSD_inc_abrasion_times(struct st_DBX_flash_tag *DBX_flash_tag,
                                uint32_t block_no)
{
    uint32_t temp,block_position;
    uint32_t *pos_tab;
    uint16_t *times_tab;
    uint32_t *busy_region,*free_region;
    uint16_t block_times;

    pos_tab = DBX_flash_tag->ART_position;      //取磨损位置表
    times_tab = DBX_flash_tag->ART_times;       //取磨损次数表
    //取目标块在磨损块号表(次数表)中的位置
    block_position = pos_tab[block_no];
    times_tab[block_position]++;   //目标块的磨损次数增量
    block_times = times_tab[block_position];  //取目标块的磨损次数
    if((block_times % 128 != 0)||(block_times >= 1024))
    {
        return;                         //增加次数后不跨区,直接返回。
    }
    //下面处理需要跨区的情况,block_no块要放到磨损次数高一区
    busy_region = &DBX_flash_tag->balance_region[9];    //第一个忙分区
    temp = block_times/128 - 1;                    //取block_no块所在的磨损分区
    //看block_no是忙块还是闲块,只有忙块才会增加次数,这个判断只是容错而已
    if(block_position >= busy_region[0])
        temp += 9;     //block_no是忙块,跳过9个闲区
    __DFFSD_ART_flip(DBX_flash_tag,temp,temp+1,block_position);

    busy_region = &DBX_flash_tag->balance_region[9];    //第一个忙分区
    free_region = DBX_flash_tag->balance_region;        //第一个空闲分区
    if((busy_region[0] == busy_region[1]) &&(free_region[0] == free_region[1]))
        //当出现free[0]和busy[0]同时空的情况,磨损表就轮转一圈
        __DFFSD_whirl_ART_table(DBX_flash_tag);
}

//----登记一个坏块-------------------------------------------------------------
//功能:把一个坏块登记到内存中的磨损平衡表中,本函数只修改内存中的擦除平衡表,
//      并不写入flash,用户须确保调用本函数后,在适当的时间写入flash。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//      block_no,坏块块号
//返回:无
//-----------------------------------------------------------------------------
void __DFFSD_register_invalid(struct st_DBX_flash_tag *DBX_flash_tag,
                            uint32_t block_no)
{
    struct flash_chip *chip = DBX_flash_tag->chip;    //取得文件柜所属芯片
    uint32_t loop,block_position,block_no_temp;
    uint32_t *pos_tab,*block_no_tab;
    uint16_t *times_tab;
    uint32_t *balance_region,*busy_region;
    uint16_t block_times;

    pos_tab = DBX_flash_tag->ART_position;        //取磨损位置表
    block_no_tab = DBX_flash_tag->ART_block_no;   //取磨损块号表,与次数表同列
    times_tab = DBX_flash_tag->ART_times;         //取磨损次数表
    balance_region = DBX_flash_tag->balance_region; //磨损分区表首址
    busy_region = &DBX_flash_tag->balance_region[9];    //第一个忙分区
    //取坏块在磨损块号表(次数表)中的位置
    block_position = pos_tab[block_no];
    block_times = times_tab[block_position];   //暂存坏块的磨损次数
    loop = block_times/128 +1;        //取坏块的磨损分区的下一分区号
    //看坏块原是忙块还是闲块,由于总是先分配再使用,坏块总是在使用中产生,使用
    //中的块肯定是忙块,故一般不会有闲块变成坏块的情况,容一下错吧
    if(block_position >= busy_region[0])
        loop += 9;     //坏块是忙块,跳过9个区
    for(; loop < 19; loop++)      //遍历所有磨损分区表,把坏块从原分区转移到坏块分区
    {
        balance_region[loop] -= 1;    //分区指针上移一格
        if(balance_region[loop] == balance_region[loop-1])
        {//相连的两分区指针重叠,说明第i-1分区是空的。
            balance_region[loop]--;
            continue;   //无需搬动块,进行下一轮比较。
        }
        //取第i分区的第一个单元的块号(即在pos表中的偏移量)
        block_no_temp = block_no_tab[balance_region[loop]];
        //第i分区第一个单元的磨损次数copy到上次循环移空的单元
        times_tab[block_position] = times_tab[balance_region[loop]];
        //第i分区第一个单元的块号copy到上次循环移空的单元
        block_no_tab[block_position] = block_no_temp;
        //第i分区第一个单元的位置表指向目标单元号
        pos_tab[block_no_temp] = block_position;
        block_position = balance_region[loop];    //本次清空的单元索引号
    }
    //坏块的擦除次数copy到坏块分区的首单元
    times_tab[block_position] = block_times;
    //坏块块号放到坏块分区首单元的ART_block_no表中
    block_no_tab[block_position] = block_no;
    //pos表的坏块指针指向坏块分区首单元
    pos_tab[block_no] = block_position;

    //设置block_no块为坏块
    DBX_flash_tag->DDR_MAT[block_no].attr = cn_invalid_block;
    //计算block_new在MAT表中位置处在DDR表中是第几块
    loop =(__DFFSD_MAT_start(DBX_flash_tag)+block_no*4*2) / chip->block_size;
    DBX_flash_tag->writed_DDR_bak[loop] = false;     //DDR_bak中标记该块为未写入
    //DDR_main中标记该块为未写入
    DBX_flash_tag->writed_DDR_main[loop] = false;
}

//----释放一块到free表--------------------------------------------------------
//功能: 把一块从busy表转移到free表。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//      block_no,释放的块号
//返回:无
//----------------------------------------------------------------------------
void __DFFSD_free_block(struct st_DBX_flash_tag *DBX_flash_tag,
                        uint32_t block_no)
{
    uint32_t block_position;
    uint32_t *pos_tab;
    uint32_t target_region;

    pos_tab = DBX_flash_tag->ART_position;
    block_position = pos_tab[block_no];
    //与第一个忙分区首块比较
    if(block_position < DBX_flash_tag->balance_region[9])
        return;     //被释放块本来就是闲块,无需释放
    else
        DBX_flash_tag->free_sum++;
    //被释放块的区号。
    target_region = DBX_flash_tag->ART_times[block_position]/128;
    //把目标块移到空闲区
    __DFFSD_ART_flip(DBX_flash_tag,target_region+9,target_region,block_position);
    //只把块属性改为空闲,不修改链表,最大限度保留数据恢复的可能。
    DBX_flash_tag->DDR_MAT[block_no].attr = cn_free_block;
}

//----交换条目-----------------------------------------------------------------
//功能: 交换两个ART条目。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//      pos1,DBX_flash_tag->ART_block_no表的条目号
//      pos2,DBX_flash_tag->ART_block_no表的另一个条目号
//返回: 无
//-----------------------------------------------------------------------------
void __DFFSD_exchange_ART_item(struct st_DBX_flash_tag *DBX_flash_tag,
                                uint32_t pos1,uint32_t pos2)
{
    uint32_t block_no1,block_no2;
    uint16_t ART_times;
    block_no1 = DBX_flash_tag->ART_block_no[pos1];
    block_no2 = DBX_flash_tag->ART_block_no[pos2];
    DBX_flash_tag->ART_block_no[pos1] = block_no2;
    DBX_flash_tag->ART_block_no[pos2] = block_no1;
    DBX_flash_tag->ART_position[block_no1] = pos2;
    DBX_flash_tag->ART_position[block_no2] = pos1;
    ART_times = DBX_flash_tag->ART_times[pos1];
    DBX_flash_tag->ART_times[pos1] = DBX_flash_tag->ART_times[pos2];
    DBX_flash_tag->ART_times[pos2] = ART_times;
}

//----磨损块号表排序-----------------------------------------------------------
//功能: 把从flash芯片中读出的未排序的ART表在内存中排序,把排序结果写到
//      DBX_flash_tag的三个表:ART_position,ART_block_no和ART_times中。
//      在执行前,前磨损表是按块号排序的
//      排序后的块号表:
//      磨损次数   0~127的空闲块起始位置----free_region[0],balance_region[0]
//      磨损次数   0~127的空闲块结束位置
//      磨损次数 128~255的空闲块起始位置----free_region[1],balance_region[1]
//      磨损次数 128~255的空闲块结束位置
//      磨损次数 256~383的空闲块起始位置----free_region[2],balance_region[2]
//      磨损次数 256~383的空闲块结束位置
//      磨损次数 38

⌨️ 快捷键说明

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