Files
levelx/common/src/lx_nand_flash_256byte_ecc_check.c
T

177 lines
7.0 KiB
C

/***************************************************************************
* Copyright (c) 2024 Microsoft Corporation
* Copyright (c) 2026-present Eclipse ThreadX contributors
*
* This program and the accompanying materials are made available under the
* terms of the MIT License which is available at
* https://opensource.org/licenses/MIT.
*
* SPDX-License-Identifier: MIT
**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** LevelX Component */
/** */
/** NAND Flash */
/** */
/**************************************************************************/
/**************************************************************************/
#define LX_SOURCE_CODE
/* Disable ThreadX error checking. */
#ifndef LX_DISABLE_ERROR_CHECKING
#define LX_DISABLE_ERROR_CHECKING
#endif
/* Include necessary system files. */
#include "lx_api.h"
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _lx_nand_flash_256byte_ecc_check PORTABLE C */
/* 6.1.7 */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function checks 256 bytes of a NAND flash and ECC and */
/* attempts to correct any single bit errors. */
/* */
/* INPUT */
/* */
/* page_buffer Page buffer */
/* ecc_buffer Returned ECC buffer */
/* */
/* OUTPUT */
/* */
/* return status */
/* */
/* CALLS */
/* */
/* _lx_nand_flash_256byte_ecc_compute Compute ECC for 256 bytes */
/* */
/* CALLED BY */
/* */
/* _lx_nand_flash_page_ecc_check NAND page check */
/* */
/**************************************************************************/
UINT _lx_nand_flash_256byte_ecc_check(UCHAR *page_buffer, UCHAR *ecc_buffer)
{
INT i, j;
UCHAR mask;
UCHAR new_ecc_buffer[3];
UCHAR ecc_errors[3];
INT error_count;
USHORT *data;
USHORT byte;
USHORT bit;
ULONG correction_code;
/* Clear the error count. */
ecc_errors[0] = 0;
ecc_errors[1] = 0;
ecc_errors[2] = 0;
/* Calculate a new ECC for the 256 byte buffer. */
_lx_nand_flash_256byte_ecc_compute(page_buffer, new_ecc_buffer);
/* Clear error count. */
error_count = 0;
/* Loop through the ECC bytes to determine if there is an error in the page. */
for (i = 0; i < 3; i++)
{
/* Check for differences in the ECCs. */
ecc_errors[i] = new_ecc_buffer[i] ^ ecc_buffer[i];
/* Are there any errors? */
if (ecc_errors[i])
{
/* Accumulate the count of set bits. */
mask = 1;
for (j = 0; j < 8; j++)
{
/* Is this bit set? */
if (ecc_errors[i] & mask)
{
/* Yes, increment the count. */
error_count++;
}
/* Move mask to next bit. */
mask = (UCHAR) ((mask << 1) & 0xFF);
}
}
}
/* Determine if there are any errors. */
if (error_count == 0)
{
/* Everything is okay, return success. */
return(LX_SUCCESS);
}
/* Was a correctable error discovered? */
else if (error_count == 11)
{
/* Initialize bit and byte offset values. */
bit = 0;
byte = 0;
/* Setup the data pointer. */
data = (USHORT *) page_buffer;
/* Calculate the 32-bit correction code. */
correction_code = (ULONG) (ecc_errors[2] << 16) | (ULONG)(ecc_errors[1] << 8) | (ULONG)ecc_errors[0];
/* Unpack the correction code. */
byte = (USHORT) ((byte | ((correction_code >> (21+2)) & 1) << 6) & 0xFFFF);
byte = (USHORT) ((byte | ((correction_code >> (19+2)) & 1) << 5) & 0xFFFF);
byte = (USHORT) ((byte | ((correction_code >> (17+2)) & 1) << 4) & 0xFFFF);
byte = (USHORT) ((byte | ((correction_code >> (15+2)) & 1) << 3) & 0xFFFF);
byte = (USHORT) ((byte | ((correction_code >> (13+2)) & 1) << 2) & 0xFFFF);
byte = (USHORT) ((byte | ((correction_code >> (11+2)) & 1) << 1) & 0xFFFF);
byte = (USHORT) ((byte | ((correction_code >> (9+2)) & 1) << 0) & 0xFFFF);
bit = (USHORT) ((bit | ((correction_code >> (7+2)) & 1) << 3) & 0xFFFF);
bit = (USHORT) ((bit | ((correction_code >> (5+2)) & 1) << 2) & 0xFFFF);
bit = (USHORT) ((bit | ((correction_code >> (3+2)) & 1) << 1) & 0xFFFF);
bit = (USHORT) ((bit | ((correction_code >> (1+2)) & 1) << 0) & 0xFFFF);
/* Fix the error. */
data[byte] = (USHORT) ((data[byte] ^ (1 << bit)) & 0xFFFF);
/* Return an error corrected status. */
return(LX_NAND_ERROR_CORRECTED);
}
/* Otherwise, an unrecoverable ECC or data error is present. */
else
{
/* Return an error. */
return(LX_NAND_ERROR_NOT_CORRECTED);
}
}