1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** LevelX Component */
16 /** */
17 /** NAND Flash */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define LX_SOURCE_CODE
23
24
25 /* Disable ThreadX error checking. */
26
27 #ifndef LX_DISABLE_ERROR_CHECKING
28 #define LX_DISABLE_ERROR_CHECKING
29 #endif
30
31
32 /* Include necessary system files. */
33
34 #include "lx_api.h"
35
36
37 /**************************************************************************/
38 /* */
39 /* FUNCTION RELEASE */
40 /* */
41 /* _lx_nand_flash_256byte_ecc_check PORTABLE C */
42 /* 6.1.7 */
43 /* AUTHOR */
44 /* */
45 /* William E. Lamie, Microsoft Corporation */
46 /* */
47 /* DESCRIPTION */
48 /* */
49 /* This function checks 256 bytes of a NAND flash and ECC and */
50 /* attempts to correct any single bit errors. */
51 /* */
52 /* INPUT */
53 /* */
54 /* page_buffer Page buffer */
55 /* ecc_buffer Returned ECC buffer */
56 /* */
57 /* OUTPUT */
58 /* */
59 /* return status */
60 /* */
61 /* CALLS */
62 /* */
63 /* _lx_nand_flash_256byte_ecc_compute Compute ECC for 256 bytes */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* _lx_nand_flash_page_ecc_check NAND page check */
68 /* */
69 /* RELEASE HISTORY */
70 /* */
71 /* DATE NAME DESCRIPTION */
72 /* */
73 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
74 /* 09-30-2020 William E. Lamie Modified comment(s), */
75 /* resulting in version 6.1 */
76 /* 06-02-2021 Bhupendra Naphade Modified comment(s), */
77 /* resulting in version 6.1.7 */
78 /* */
79 /**************************************************************************/
_lx_nand_flash_256byte_ecc_check(UCHAR * page_buffer,UCHAR * ecc_buffer)80 UINT _lx_nand_flash_256byte_ecc_check(UCHAR *page_buffer, UCHAR *ecc_buffer)
81 {
82
83 INT i, j;
84 UCHAR mask;
85 UCHAR new_ecc_buffer[3];
86 UCHAR ecc_errors[3];
87 INT error_count;
88 USHORT *data;
89 USHORT byte;
90 USHORT bit;
91 ULONG correction_code;
92
93
94 /* Clear the error count. */
95 ecc_errors[0] = 0;
96 ecc_errors[1] = 0;
97 ecc_errors[2] = 0;
98
99 /* Calculate a new ECC for the 256 byte buffer. */
100 _lx_nand_flash_256byte_ecc_compute(page_buffer, new_ecc_buffer);
101
102 /* Clear error count. */
103 error_count = 0;
104
105 /* Loop through the ECC bytes to determine if there is an error in the page. */
106 for (i = 0; i < 3; i++)
107 {
108
109 /* Check for differences in the ECCs. */
110 ecc_errors[i] = new_ecc_buffer[i] ^ ecc_buffer[i];
111
112 /* Are there any errors? */
113 if (ecc_errors[i])
114 {
115
116 /* Accumulate the count of set bits. */
117 mask = 1;
118 for (j = 0; j < 8; j++)
119 {
120
121 /* Is this bit set? */
122 if (ecc_errors[i] & mask)
123 {
124
125 /* Yes, increment the count. */
126 error_count++;
127 }
128
129 /* Move mask to next bit. */
130 mask = (UCHAR) ((mask << 1) & 0xFF);
131 }
132 }
133 }
134
135 /* Determine if there are any errors. */
136 if (error_count == 0)
137 {
138
139 /* Everything is okay, return success. */
140 return(LX_SUCCESS);
141 }
142
143 /* Was a correctable error discovered? */
144 else if (error_count == 11)
145 {
146
147 /* Initialize bit and byte offset values. */
148 bit = 0;
149 byte = 0;
150
151 /* Setup the data pointer. */
152 data = (USHORT *) page_buffer;
153
154 /* Calculate the 32-bit correction code. */
155 correction_code = (ULONG) (ecc_errors[2] << 16) | (ULONG)(ecc_errors[1] << 8) | (ULONG)ecc_errors[0];
156
157 /* Unpack the correction code. */
158 byte = (USHORT) ((byte | ((correction_code >> (21+2)) & 1) << 6) & 0xFFFF);
159 byte = (USHORT) ((byte | ((correction_code >> (19+2)) & 1) << 5) & 0xFFFF);
160 byte = (USHORT) ((byte | ((correction_code >> (17+2)) & 1) << 4) & 0xFFFF);
161 byte = (USHORT) ((byte | ((correction_code >> (15+2)) & 1) << 3) & 0xFFFF);
162 byte = (USHORT) ((byte | ((correction_code >> (13+2)) & 1) << 2) & 0xFFFF);
163 byte = (USHORT) ((byte | ((correction_code >> (11+2)) & 1) << 1) & 0xFFFF);
164 byte = (USHORT) ((byte | ((correction_code >> (9+2)) & 1) << 0) & 0xFFFF);
165 bit = (USHORT) ((bit | ((correction_code >> (7+2)) & 1) << 3) & 0xFFFF);
166 bit = (USHORT) ((bit | ((correction_code >> (5+2)) & 1) << 2) & 0xFFFF);
167 bit = (USHORT) ((bit | ((correction_code >> (3+2)) & 1) << 1) & 0xFFFF);
168 bit = (USHORT) ((bit | ((correction_code >> (1+2)) & 1) << 0) & 0xFFFF);
169
170 /* Fix the error. */
171 data[byte] = (USHORT) ((data[byte] ^ (1 << bit)) & 0xFFFF);
172
173 /* Return an error corrected status. */
174 return(LX_NAND_ERROR_CORRECTED);
175 }
176
177 /* Otherwise, an unrecoverable ECC or data error is present. */
178 else
179 {
180
181 /* Return an error. */
182 return(LX_NAND_ERROR_NOT_CORRECTED);
183 }
184 }
185
186