mirror of
https://github.com/eclipse-threadx/levelx.git
synced 2026-09-14 20:48:51 +08:00
Initial commit
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user