Files
levelx/common/src/lx_nand_flash_256byte_ecc_check.c
T
2021-06-02 06:46:59 +00:00

187 lines
8.1 KiB
C

/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** 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 */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
/* 09-30-2020 William E. Lamie Modified comment(s), */
/* resulting in version 6.1 */
/* 06-02-2021 Bhupendra Naphade Modified comment(s), */
/* resulting in version 6.1.7 */
/* */
/**************************************************************************/
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);
}
}