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

📄 zlg_ffs.c

📁 zlg nand flash 写平衡 在LINUX XIA
💻 C
📖 第 1 页 / 共 3 页
字号:
    bufa = malloc(i * sizeof(uint8));
    if (bufa == NULL)
    {
        return DISK_INIT_NOT_OK;
    }
    Index->BlockState = bufa;

    /* 初始化内存空间 */
    do
    {
        *bufa++ = BAD_BLOCK;
    } while (--i != 0);

    /* 获取必须的内存空间 */
    i = Drive->BlockPreDisk;
    VBlockInfo = malloc(i * sizeof(uint32));
    if (VBlockInfo == NULL)
    {
        free(Index->BlockState);
        Index->BlockState = NULL;
        return DISK_INIT_NOT_OK;
    }
    Index->BlockEaseSum = VBlockInfo;

    /* 初始化内存空间 */
    do
    {
        *VBlockInfo++ = ~1;
    } while (--i != 0);

    /* 获得有效块数  */
    bufa = Drive->BufA;
    j = Drive->BlockPreDisk;
    i = 0;
    k = 0;
    temp = 0;
    BytsPerSec = Drive->BytsPerSec;
    Drive->SectorRead(Drive->Index, bufa, 0);
   
    do
    {
        if ((bufa[(i / 8) % BytsPerSec] & (1 << (i % 8))) != 0)
        {
            temp++;
        }
        i++;
        if ((i % (BytsPerSec * 8)) == 0)
        {
            k++;
            Drive->ExSectorRead(Index, bufa, k);
        }
    } while (--j != 0) ;

    if (temp <= 1)
    {
        return DISK_INIT_NOT_OK;
    }

    /* 获取必须的内存空间 */
    temp--;                                                  /* 1个保留块 */
    Index->BlockSum = temp;
    VBlockInfo = malloc(temp * sizeof(uint32));
    if (VBlockInfo == NULL)
    {
        free(Index->BlockState);
        Index->BlockState = NULL;
        free(Index->BlockEaseSum);
        Index->BlockEaseSum = NULL;
        return DISK_INIT_NOT_OK;
    }
    Index->VBlockInfo = VBlockInfo;

    /* 初始化内存空间 */
    do
    {
        *VBlockInfo++ = 0;
    } while (--temp != 0);
    
    /* 获取虚拟块与物理块的映射表、物理块擦除计数表和物理块状态表 */
    VBlockInfo = (Index->VBlockInfo) - 1;
    bufa = Drive->BufA;
    k = 0;
    j = Index->BlockSum;
    
    Drive->SectorRead(Drive->Index, bufa, 0);
    for (i = 1; i < j; i++)
    {
        if ((i % (BytsPerSec * 8)) == 0)
        {
            k++;
            Drive->ExSectorRead(Drive->Index, bufa, k);
        }

        if ((bufa[(i / 8) % BytsPerSec] & (1 << (i % 8))) != 0)
        {
            Index->BlockState[i] = FREE_BLOCK;

            m = Drive->SecsPreBlock;
            n = m * i;
            temp2 = 0;
            temp1 = 0;
            do
            {
                Drive->ExSectorRead(Drive->Index, bufa, n++);
                temp = bufa[2] | bufa[3] << 8;
                temp = temp << 16;
                temp |= (bufa[0] | bufa[1] << 8);

                temp3 = bufa[10] | bufa[11] << 8;
                temp3 = temp3 << 16;
                temp3 |= (bufa[8] | bufa[9] << 8);
                if (temp3 != ~0)
                {
                    temp1 = temp3;
                }
            
                if (temp < j && temp != 0)
                {
                    VBlockInfo[temp] = i;
                    Index->BlockState[i] = USR_BLOCK;
                    temp2 = USR_BLOCK_ADD;
                    break;
                }
            } while (--m != 0);
            Index->BlockEaseSum[i] = temp1 + temp2;
            Drive->SectorRead(Drive->Index, bufa, k);
        }
    }
    return DISK_INIT_OK;
}

/*********************************************************************************************************
        关闭
*********************************************************************************************************/
        static uint8 FFSDiskClose(FFSDisk *Index)
{
    if (Index != NULL)
    {
        if (Index->BlockState != NULL)
        {
            free(Index->BlockState);
        }
        Index->BlockState = NULL;
        if (Index->BlockEaseSum != NULL)
        {
            free(Index->BlockEaseSum);
        }
        Index->BlockEaseSum = NULL;
        if (Index->VBlockInfo != NULL)
        {
            free(Index->VBlockInfo);
        }
        Index->VBlockInfo = NULL;
        Index->BlockSum = 0;
    }
    return DISK_RETURN_OK;
}

/*********************************************************************************************************
        释放扇区
*********************************************************************************************************/
        static uint8 FFSFreeSector(FFSDisk *Index, uint32 SecIndex)
{
    uint32 VBlockIndex, BlockIndex;
    unsigned int i;
    const FlashDriver *Drive;
    uint8 *Buf;

    Drive = Index->Drive;
    VBlockIndex = SecIndex / Drive->SecsPreBlock;
    Buf = Drive->BufA;
    if (Index != NULL)
    if (Drive != NULL)
    if (VBlockIndex < Index->BlockSum)
    {
        BlockIndex = Index->VBlockInfo[VBlockIndex];                /* 获得物理块号     */
        if (BlockIndex < Index->BlockSum)
        if (BlockIndex != 0)
        {
            SecIndex = SecIndex % Drive->SecsPreBlock;              /* 获得块内偏移     */
            SecIndex = SecIndex + BlockIndex * Drive->SecsPreBlock; /* 获得物理扇区号   */
            if (Drive->ExSectorRead(Drive->Index, Buf, SecIndex) == TRUE)
            {
                if (Buf[0] != 0xff ||
                    Buf[1] != 0xff ||
                    Buf[2] != 0xff ||
                    Buf[3] != 0xff)
                {
                    Buf[0] = 0x00;
                    Buf[1] = 0x00;
                    Buf[2] = 0x00;
                    Buf[3] = 0x00;
                    
                    if (Drive->ExSectorWrite(Drive->Index, Buf, SecIndex) != TRUE)
                    {
                        goto err;
                    }
                    if (Drive->ExSectorCheck(Drive->Index, Buf, SecIndex) != TRUE)
                    {
                        goto err;
                    }
                }
                SecIndex = BlockIndex * Drive->SecsPreBlock;
                i = Drive->SecsPreBlock;
                do
                {
                    if (Drive->ExSectorRead(Drive->Index, Buf, SecIndex) == FALSE)
                    {
                        goto err;
                    }
                    if (Buf[0] == 0x00 &&
                        Buf[1] == 0x00 &&
                        Buf[2] == 0x00 &&
                        Buf[3] == 0x00)
                    {
                        SecIndex++;
                        continue;
                    }
                    if (Buf[0] == 0xff &&
                        Buf[1] == 0xff &&
                        Buf[2] == 0xff &&
                        Buf[3] == 0xff)
                    {
                        SecIndex++;
                        continue;
                    }
                    break;
                } while (--i != 0);
                if (i == 0)
                {
                    Index->VBlockInfo[VBlockIndex] = 0x00000000;
                    Index->BlockState[BlockIndex] = FREE_BLOCK;
                    if (FFSBlockErase(Index, BlockIndex) != TRUE)
                    {
                        FFSSetBadBlock(Index, BlockIndex);
                        return FALSE;
                    }
                }
            }
        }
    }
    return TRUE;
err:
    Index->VBlockInfo[VBlockIndex] = 0x00000000;
    FFSSetBadBlock(Index, BlockIndex);
    return FALSE;
}

/*********************************************************************************************************
        读扇区
*********************************************************************************************************/
        static uint8 FFSDiskRead(FFSDisk *Index, uint8 *Buf, uint32 SecIndex)
{
    uint32 BlockIndex;
    const FlashDriver *Drive;
    uint16 Rt;
    
    Rt = DISK_READ_NOT_OK;
    
    Drive = Index->Drive;
    
    BlockIndex = SecIndex / Drive->SecsPreBlock;
    if (Index != NULL)
    if (Drive != NULL)
    if (BlockIndex < Index->BlockSum)
    {
        Rt = DISK_READ_OK;
        BlockIndex = Index->VBlockInfo[BlockIndex];                 /* 获得物理块号     */
        if (BlockIndex < Index->BlockSum)
        if (BlockIndex != 0)
        {
            SecIndex = SecIndex % Drive->SecsPreBlock;              /* 获得块内偏移     */
            SecIndex = SecIndex + BlockIndex * Drive->SecsPreBlock; /* 获得物理扇区号   */
            if (Drive->SectorRead(Drive->Index, Buf, SecIndex) != TRUE)
            {
                Rt = DISK_READ_NOT_OK;
            }
        }
    }
    return Rt;
}

/*********************************************************************************************************
        查找空闲块中擦除次数最少的块)
*********************************************************************************************************/
        static uint32 FildBockB(FFSDisk *Index)
{
    uint32 BlockIndex;
    uint32 i, j, temp2;
    uint32 min;
    uint8  *BlockState, temp1;
    uint32 *BlockEaseSum;
    uint8 *Buf;

    j = Index->Drive->BlockPreDisk;
    Buf = Index->Drive->BufA;

    min = ~0;
    BlockIndex = 0;
    i = j - 1;
    BlockState = Index->BlockState + 1;
    BlockEaseSum = Index->BlockEaseSum + 1;
    
    do
    {
        temp1 = *BlockState++;
        temp2 = *BlockEaseSum++;

        if (temp1 == FREE_BLOCK)
        if (temp2 < min)
        {
            min = temp2;
            BlockIndex = j - i;
            if (min == 0)
            {
                break;
            }
        }
    } while (--i != 0);

    if (BlockIndex < j)
    {
        return BlockIndex;
    }
    return 0;
}

/*********************************************************************************************************
        查找擦除次数最少的块(非空闲块要加权,以尽量在空闲块重分配)
*********************************************************************************************************/
        static uint32 FildBockA(FFSDisk *Index)
{
    uint32 BlockIndex;
    uint32 i, j, temp2;
    uint32 min;
    uint8  *BlockState, temp1;
    uint32 *BlockEaseSum;
    uint8 *Buf;

    j = Index->Drive->BlockPreDisk;
    Buf = Index->Drive->BufA;

    min = ~0;
    BlockIndex = 0;
    i = j - 1;
    BlockState = Index->BlockState + 1;
    BlockEaseSum = Index->BlockEaseSum + 1;
    
    do
    {
        temp1 = *BlockState++;
        temp2 = *BlockEaseSum++;

        if (temp1 != BAD_BLOCK)
        if (temp2 < min)
        {
            min = temp2;
            BlockIndex = j - i;
            if (min == 0)
            {
                break;
            }
        }
    } while (--i != 0);

    if (BlockIndex < j)
    {
        return BlockIndex;
    }
    return 0;
}

/*********************************************************************************************************
        增加虚拟块
*********************************************************************************************************/
        static uint32 AddVBlock(FFSDisk *Index)
{
    uint32 BlockIndex, k, temp, temp1, temp2;
    const FlashDriver *Drive;
    uint8 *BufA;
    uint8 C[4];

    BlockIndex = FildBockA(Index);
    if (BlockIndex == 0)
    {
        goto err;
    }
    if (Index->BlockState[BlockIndex] == USR_BLOCK)        /* 此块已被使用 */
    {
        temp = FildBockB(Index);            /* 找空闲块  */
        if (temp == 0)
        {
            goto err;
        }

        /* 拷贝数据到空闲块  */
        Drive = Index->Drive;
        k = Drive->SecsPreBlock;
        temp1 = BlockIndex * k;
        temp2 = temp * k;

        BufA = Drive->BufA;
        do
        {
            Drive->ExSectorRead(Drive->Index, BufA, temp1);
            if (BufA[5] == 0)
            {
                C[0] = BufA[0];
                C[1] = BufA[1];
                C[2] = BufA[2];
                C[3] = BufA[3];
                Drive->ExSectorRead(Drive->Index, BufA, temp2);
                if (BufA[0] != 0xff)
                {
                    goto err1;
                }
                if (BufA[1] != 0xff)
                {
                    goto err1;
                }
                if (BufA[2] != 0xff)
                {
                    goto err1;
                }
                if (BufA[3] != 0xff)
                {
                    goto err1;
                }

⌨️ 快捷键说明

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