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