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

📄 ecc.c

📁 Windows CE 6.0 BSP for the Beagle Board.
💻 C
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//
// Copyright (c) Texas Instruments.  All rights reserved. 
//
//------------------------------------------------------------------------------
//
//  File: ecc.c
//
//  This file implements ECC algorithm used on OMAP2420 NAND flash. 
//
#include <windows.h>

//------------------------------------------------------------------------------

#define DATA_BUFF_LEN           512
#define ECC_BUFF_LEN            3               // # of bytes in ECC

#define NO_DATA_ERROR           0
#define ECC_ERROR               1
#define CORRECTABLE_ERROR       12              // half of the ECC bits are 1

//------------------------------------------------------------------------------

static const BYTE ByteToNumberOfOnes[256] = {
    0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};

#define CountNumberOfOnes(num) ByteToNumberOfOnes[num]

//------------------------------------------------------------------------------
//
//  Function:  ECC_CorrectData()
//
//  Corrects any errors (if possible) in the specified data.
//
//  This implemention uses 3 bytes of ECC info for every 512 bytes of data.
//  Furthermore, a only single-bit error can be corrected for every 512 bytes
//  of data.
//
//  This code is based on the ECC algorithm publicly available on Samsung's
//  FLASH media website.
//

//BOOL ECC_CorrectData(LPBYTE pData, LPBYTE pExistingECC, LPBYTE pNewECC)
BOOL ECC_CorrectData(LPBYTE pData, DWORD dwDataBuffLen, LPBYTE pExistingECC, DWORD dwECCBuffLen)
{
    DWORD i, numOnes, byteLocation, bitLocation;
    BYTE xorECC[ECC_BUFF_LEN];

    //----- 1. Check the parameters -----
    if ((pData == NULL) || (pExistingECC == NULL)) {
        return FALSE;
    }

    //----- 2. First, determine if this is a single-bit, correctable, error ----
    //         NOTE: To answer this question, the two ECC values are XOR'd 
    //               together and the total # of 1 bits is counted, which 
    //               then tell us if we can correct the erroneous single-bit 
    //               transition in the data.
    numOnes = 0;
    for (i = 0; i < ECC_BUFF_LEN; i++) {
        xorECC[i] = pExistingECC[i] ^ pExistingECC[i+ECC_BUFF_LEN];
        numOnes += CountNumberOfOnes(xorECC[i]);
    }

    switch (numOnes) {
    case NO_DATA_ERROR:                 // Data doesn't contain an error
        return TRUE;

    case ECC_ERROR:                     // Existing ECC value has gone bad!
        return FALSE;

    case CORRECTABLE_ERROR:             // Single-bit error
        break;

    default:                            // More than a single-bit error
        return FALSE;
    }
        
    //----- 3. Compute the location of the single-bit error -----
    byteLocation = ((xorECC[2]&0xf0)<<1) | ((xorECC[1]&0xf8)>>3);
    bitLocation  = xorECC[1] & 0x7;

    //----- 4. Correct the single-bit error -----
    if (pData[byteLocation] & (0x01 << bitLocation)) {
        pData[byteLocation] &= ~(0x01 << bitLocation);      // 0->1 error
    } else {
        pData[byteLocation] |= (0x01 <<  bitLocation);      // 1->0 error
    }

    return TRUE;
}

//------------------------------------------------------------------------------
//
//  Function:  ECC_Compute()
//
//  Compute ECC for passed data.
//
//VOID ECC_Compute(BYTE data[512], LPBYTE ecc_gen)
BOOL ECC_ComputeECC(LPBYTE pData, DWORD dwDataBuffLen, LPBYTE pECC, DWORD dwECCBuffLen)
{
    ULONG   i;
    ULONG   paritc = 0;
    BYTE    parity_bit;
    BYTE    bitmask[6] = {0x55, 0xaa, 0x33, 0xcc, 0xf, 0xf0};
    ULONG   ulEcc;
    
    ulEcc = 0;
    for ( i = 0; i < 512; i++) {
        paritc = paritc ^ pData[i];
        if ((CountNumberOfOnes(pData[i] ) & 1) != 0) {
            ulEcc = ulEcc ^ i;
        }
    }

    pECC[1] = (BYTE)(ulEcc << 3);
    pECC[2] = (BYTE)(ulEcc >> 1) & 0xf0;

    if ((CountNumberOfOnes( paritc ) & 1) != 0) {
        // Invert copied bits
        pECC[0] = pECC[1] ^ 0xf8;
        pECC[2] |= (((~pECC[2]) >> 4) & 0x0f) ;
    } else {
        pECC[0] = pECC[1];
        pECC[2] |= (pECC[2] >> 4);
    }

    for (i = 0; i < 6; i++) {
        parity_bit = CountNumberOfOnes(paritc & bitmask[i]) & 1;
        parity_bit <<= (i >> 1);
        pECC[(i & 1)] |= parity_bit;
    }
    return( TRUE );
}

/*
------------------------------------------------------------------------------
Function:		ECC_IsDataValid()

Description:	Determines if the specfied buffer of data is valid.  

Notes:			To determine if the data is valid, new ECC information is 
				generated for the specified data and then compared to the  
				specified (a.k.a. existing) ECC information.  

Returns:		Boolean indicating success.
-------------------------------------------------------------------------------
*/

BOOL ECC_IsDataValid(LPBYTE pData, DWORD dwDataBuffLen, LPBYTE pExistingECC, DWORD dwECCBuffLen)
{
	static UCHAR i = 0;
	static UCHAR newECC[ECC_BUFF_LEN];


    //----- 0. Compare ECC buf lengths
    if( dwECCBuffLen != ECC_BUFF_LEN )
    {
        return FALSE;
    }

	//----- 1. Compute the new ECC information for the data -----
	//         NOTE: We assume that the input data buffer is a sector (512 bytes)
	if(!ECC_ComputeECC(pData, dwDataBuffLen, newECC, ECC_BUFF_LEN))
	{
		return FALSE;
	}

	//----- 2. Compare the generated ECC info with the existing ECC info  -----
	//         NOTE: The data is valid if XORing all the ECC info together equals zero
	for(i=0; i<ECC_BUFF_LEN; i++)
	{
		if((newECC[i] != *(pExistingECC+i)))
		{
			return FALSE;
		}
	}

	return TRUE;	
}

⌨️ 快捷键说明

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