mirror of
https://github.com/eclipse-threadx/levelx.git
synced 2026-09-15 04:55:33 +08:00
183 lines
7.8 KiB
C
183 lines
7.8 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 TX_DISABLE_ERROR_CHECKING
|
|
#define TX_DISABLE_ERROR_CHECKING
|
|
#endif
|
|
|
|
|
|
/* Include necessary system files. */
|
|
|
|
#include "lx_api.h"
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _lx_nand_flash_256byte_ecc_check PORTABLE C */
|
|
/* 6.0 */
|
|
/* 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 */
|
|
/* */
|
|
/**************************************************************************/
|
|
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);
|
|
}
|
|
}
|
|
|