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

📄 ddr.c

📁 新一代基于事件的嵌入式操作系统dyos在三星的s3c44b0的arm芯片上的完整移植代码
💻 C
📖 第 1 页 / 共 5 页
字号:
//----------------------------------------------------
//Copyright (C), 2004-2009,  lst.
//版权所有 (C), 2004-2009,   lst.
//所属模块:flash文件系统
//作者:lst
//版本:V1.0.0
//文件描述:flash文件系统中DDR表的部分
//其他说明:
//修订历史:
//    2. ...
//    1. 日期:
//       作者:
//       新版本号:
//       修改说明:
//------------------------------------------------------
#include "inc_os.h"
#include "flashfile.h"
#include "ddr.h"
#include <string.h>

//----重构DDR_bak--------------------------------------------------------------
//功能:正确读取DDR_main到内存后后,如果校验发现flash中的DDR_bak与内存中的DDR表
//      不一致,将调用本函数。除DBL部分外,两份DDR表的其余部分是相同的,故只需
//      根据DDR表中的MAT表重构出一份DDR_DBL_bak即可,然后把整个DDR_bak表标记为
//      需要写入。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//返回:无
//-----------------------------------------------------------------------------
void __DFFSD_rebuild_DDR_bak(struct st_DBX_flash_tag *DBX_flash_tag)
{
    uint32_t i,loop,DBL_offset,DDR_blocks;
    struct flash_chip *chip = DBX_flash_tag->chip;
    bool_t *writed = DBX_flash_tag->writed_DDR_bak; //指向是否完成写入的指针
    uint32_t *DBL_buf;
    DDR_blocks = (DBX_flash_tag->DDR_size + chip->block_size -1)
                                / chip->block_size;    //计算DDR表占用的块数
    DBL_buf = DBX_flash_tag->DDR_DBL+DDR_blocks;
    for(loop = 0; loop < DDR_blocks; loop++)    //设置整个DDR_bak需写入
        writed[loop] = false;
    //以下几行扫描整个文件柜,初始化DBL_bak表
    DBL_offset = 0;
    for(loop = 0; loop < DBX_flash_tag->block_sum; loop++)
    {
        if(DBX_flash_tag->DDR_MAT[loop].attr == cn_DDR_bak_block)
        {
            DBL_buf[DBL_offset] = loop;     //第loop块是DDR_bak块
            DBL_offset ++;                  //DBL偏移增量
        }
    }
    //异常断电的特殊情况下,可能造成MAT中的DDR_bak块数不够的情况,详见文档
    //《DDR表异常断电算法》
    //为所缺少的DBL块分配新块
    //此时初始化还未完成,不能使用正常的块分配算法,直接找free块,
    if(DBL_offset < DDR_blocks)
    {
        for(loop = 0; loop < DBX_flash_tag->block_sum; loop++)
        {
            if(DBX_flash_tag->DDR_MAT[loop].attr == cn_free_block)
            {
                //第loop块是空闲块,改为DDR_bak块
                DBL_buf[DBL_offset] = loop;
                //把MAT表中第loop块的属性改为DDR_bak块
                DBX_flash_tag->DDR_MAT[loop].attr = cn_DDR_bak_block;
                //计算MAT表中第loop项的地址在DDR表中的偏移量
                i = DBX_flash_tag->DDR_size-(DBX_flash_tag->block_sum-loop)*4*2;
                //计算MAT表中第loop项的地址在DDR表中的偏移块号
                i = i / chip->block_size;
                //第loop块的用途被修改,MAT第koop项位置DDR_main也被修改,重写之
                DBX_flash_tag->writed_DDR_main[i] = false;
                DBL_offset ++;      //DBL偏移增量
                if(DBL_offset == DDR_blocks)
                    break;
            }
        }
    }
}

//----重构DDR_main-------------------------------------------------------------
//功能:正确读取DDR_main到内存后后,肯定DDR_main是有问题的,将调用本函数重构
//      DDR_main表。除DBL部分外,两份DDR表的其余部分是相同的,故只需根据DDR表中
//      的MAT表重构出一份DDR_DBL_main即可,然后把整个DDR_main表标记为需要写入。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//返回:无
//-----------------------------------------------------------------------------
void __DFFSD_rebuild_DDR_main(struct st_DBX_flash_tag *DBX_flash_tag)
{
    uint32_t i,loop,DBL_offset,DDR_blocks;
    struct flash_chip *chip = DBX_flash_tag->chip;
    bool_t *writed = DBX_flash_tag->writed_DDR_bak; //指向是否完成写入的指针
    uint32_t *DBL_buf;
    DDR_blocks = (DBX_flash_tag->DDR_size + chip->block_size -1)
                                / chip->block_size;    //计算DDR表占用的块数
    DBL_buf = DBX_flash_tag->DDR_DBL;
    for(loop = 0; loop < DDR_blocks; loop++)    //置整个DDR_main需写入
        writed[loop] = false;
    //以下几行扫描整个文件柜,初始化DBL_main表
    DBL_offset = 0;
    for(loop = 0; loop < DBX_flash_tag->block_sum; loop++)
    {
        if(DBX_flash_tag->DDR_MAT[loop].attr == cn_DDR_main_block)
        {
            DBL_buf[DBL_offset] = loop;     //第loop块是DDR_main块
            DBL_offset ++;                  //DBL偏移增量
        }
    }
    //异常断电的特殊情况下,可能造成MAT中的DDR_main块数不够的情况,详见文档
    //《DDR表异常断电算法》
    //为所缺少的DBL块分配新块
    //此时初始化还未完成,不能使用正常的块分配算法,直接找free块,
    if(DBL_offset < DDR_blocks)
    {
        for(loop = 0; loop < DBX_flash_tag->block_sum; loop++)
        {
            if(DBX_flash_tag->DDR_MAT[loop].attr == cn_free_block)
            {
                //第loop块是空闲块,改为DDR_bak块
                DBL_buf[DBL_offset] = loop;
                //把MAT表中第loop块的属性改为DDR_main块
                DBX_flash_tag->DDR_MAT[loop].attr = cn_DDR_bak_block;
                //计算MAT表中第loop项的地址在DDR表中的偏移量
                i = DBX_flash_tag->DDR_size -(DBX_flash_tag->block_sum-loop)*4*2;
                //计算MAT表中第loop项的地址在DDR表中的偏移块号
                i = i / chip->block_size;
                //第loop块的用途被修改,MAT第koop项位置DDR_main也被修改,重写之
                DBX_flash_tag->writed_DDR_main[i] = false;
                DBL_offset ++;      //DBL偏移增量
                if(DBL_offset == DDR_blocks)
                    break;
            }
        }
    }
}

//----计算MAT表起始偏移--------------------------------------------------------
//功能: 计算DDR表中MAT表的起始偏移地址,如果DDR_size不超过1块,则ART表后直接存
//      MAT表,否则MAT表要做8字节对齐以免单个MAT表项跨块。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//返回: MAT表起始地址偏移
//-----------------------------------------------------------------------------
uint32_t __DFFSD_MAT_start(struct st_DBX_flash_tag *DBX_flash_tag)
{
    uint32_t MAT_start;
    struct flash_chip *chip = DBX_flash_tag->chip;
    MAT_start=(DBX_flash_tag->DDR_size+chip->block_size -1)/chip->block_size*4
                +4 +4 + DBX_flash_tag->block_sum*2;
    if(DBX_flash_tag->DDR_size > chip->block_size)
    {
        MAT_start = align_up_8(MAT_start);
    }
    return MAT_start;
}

//----读DDR表------------------------------------------------------------------
//功能:本函数被__DFFSD_scan_DDR函数调用,扫描一个DDR表,读取DDR表的内容,然后
//      初始化DBX_flash_tag与DDR表有关的成员。
//参数: DBX_flash_tag,被操作的文件柜,flash文件柜的专有数据结构指针
//      which,读取哪一个DDR表,0=DDR_main,1=DDR_bak
//返回:true=完全无错,flash中DDR表被读入到DBX_flash_tag中。
//      false=有错误,flash中DDR表有任何错误,__DFFSD_scan_DDR函数会调用
//      __rebuild_DDR_bak或__rebuild_DDR_main函数重构DDR表
//-----------------------------------------------------------------------------
bool_t __DFFSD_read_DDR(struct st_DBX_flash_tag *DBX_flash_tag,
                            ufast_t which)
{
    uint32_t block_no;      //DDR表的块号
    uint32_t DDR_blocks;    //DDR表占用的块数
    uint32_t loop,read_size;
    uint32_t offset = 0,completed = 0;
    uint32_t FDSB_start,ARB_start,ART_start,ART_end,MAT_start;
    uint32_t temp;
    struct MAT_table *MAT_item;
    struct flash_chip *chip = DBX_flash_tag->chip;  //获取文件柜对应的芯片
    uint32_t *DBL_buf;

    DDR_blocks = (DBX_flash_tag->DDR_size+chip->block_size-1)/chip->block_size;
    if(which == 0)
    {
        DBL_buf = DBX_flash_tag->DDR_DBL;  //取DBL_main缓冲区指针
        DBL_buf[0] = DBX_flash_tag->DDR_main;
    }else
    {
        DBL_buf = DBX_flash_tag->DDR_DBL+DDR_blocks;   //取DBL_bak缓冲区指针
        DBL_buf[0] = DBX_flash_tag->DDR_bak;
    }
    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);
    MAT_item = DBX_flash_tag->DDR_MAT;
    for(loop = 0; loop < DDR_blocks; loop++)  //从首块到末块循环
    {
        block_no = DBL_buf[loop] + DBX_flash_tag->start_block;
        if(loop == DDR_blocks-1)
            read_size = DBX_flash_tag->DDR_size - completed;
        else
            read_size = chip->block_size;
        if(chip->read_data_with_ecc(block_no,0,chip->block_buf,read_size)
                                    != read_size)
        {
            return false;   //读函数返回错误
        }else
        {
            while(offset - completed < read_size)
            {
                if(offset < FDSB_start)         //DBL
                {
                    DBL_buf[offset/4] = __pick_little_32bit(
                                        chip->block_buf+(offset-completed),0);
                    offset +=4;
                }else if(offset < ARB_start)  //FDSB
                {
                    DBX_flash_tag->DDR_FDSB = __pick_little_32bit(
                                        chip->block_buf+(offset-completed),0);
                    offset +=4;
                }else if(offset < ART_start) //ARB
                {
                    DBX_flash_tag->DDR_ARB = __pick_little_32bit(
                                        chip->block_buf+(offset-completed),0);
                    offset +=4;
                }else if(offset < ART_end)   //ART
                {
                    temp = (offset-ART_start)/2;
                    DBX_flash_tag->ART_times[temp] = __pick_little_16bit(
                                        chip->block_buf+(offset-completed),0);

                    DBX_flash_tag->ART_position[temp] = temp;
                    DBX_flash_tag->ART_block_no[temp] = temp;
                    offset +=2;
                }else if(offset < MAT_start)    //跳过对齐填充
                {
                    offset = MAT_start;
                }else if(offset <= DBX_flash_tag->DDR_size)
                {
                    temp = __pick_little_32bit(
                                        chip->block_buf+(offset-completed),0);
                    MAT_item->attr = temp >>30;
                    //向前指针
                    MAT_item->previous = temp & 0x3fffffff;
                    temp = __pick_little_32bit(
                                        chip->block_buf+(offset-completed),1);
                    MAT_item->attr += (temp >>30)<<2;
                    //向后指针
                    MAT_item->next = temp & 0x3fffffff;
                    offset +=8;
                    MAT_item++;
                }
            }
            completed += chip->block_size;
        }
    }
    for(loop = 0; loop < DBX_flash_tag->block_sum; loop++)  //磨损表不排序
    {
        DBX_flash_tag->ART_block_no[loop] = loop;
        DBX_flash_tag->ART_position[loop] = loop;
    }
    return true;        //哈哈,如果有任何错误,函数走不到这里
}

//----校验DDR_bak-------------------------------------------------------------

⌨️ 快捷键说明

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