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_compute PORTABLE C */
42 /* 6.2.1 */
43 /* AUTHOR */
44 /* */
45 /* William E. Lamie, Microsoft Corporation */
46 /* */
47 /* DESCRIPTION */
48 /* */
49 /* This function computes the ECC for 256 bytes of a NAND flash page. */
50 /* The resulting ECC code is returned in 3 bytes. */
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 /* None */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* _lx_nand_flash_page_ecc_compute NAND page ECC compute */
68 /* _lx_nand_flash_256byte_ecc_check Check 256 bytes and ECC */
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 /* 03-08-2023 Xiuwen Cai Modified comment(s), */
80 /* inverted output, */
81 /* resulting in version 6.2.1 */
82 /* */
83 /**************************************************************************/
_lx_nand_flash_256byte_ecc_compute(UCHAR * page_buffer,UCHAR * ecc_buffer)84 UINT _lx_nand_flash_256byte_ecc_compute(UCHAR *page_buffer, UCHAR *ecc_buffer)
85 {
86
87 USHORT i, j;
88 USHORT *data;
89 USHORT bits, mask;
90 USHORT bit_parity;
91 USHORT even_bit_parity;
92 USHORT odd_bit_parity;
93 USHORT even_byte_parity;
94 USHORT odd_byte_parity;
95
96
97 /* Initialize local variables. */
98 bit_parity = 0;
99 even_bit_parity = 0;
100 odd_bit_parity = 0;
101 even_byte_parity = 0;
102 odd_byte_parity = 0;
103
104 /* Initialize the return ECC code area. */
105 ecc_buffer[0]= 0;
106 ecc_buffer[1]= 0;
107 ecc_buffer[2]= 0;
108
109 /* Setup a 16-bit pointer to the buffer area. */
110 data = (USHORT *) page_buffer;
111
112 /* Loop through the 256 byte buffer, 16 bits at a time. */
113 for (i = 0; i < 128; i++)
114 {
115
116 /* Compute the ECC value. */
117 bit_parity = bit_parity ^ data[i];
118
119 /* Now count the bits in the current data word. */
120 bits = 0;
121 mask = 1;
122 for (j = 0; j < 16; j++)
123 {
124
125 /* Is the bit set? */
126 if (data[i] & mask)
127 {
128
129 /* Yes, increment the bit count. */
130 bits++;
131 }
132
133 /* Move the mask to the next bit. */
134 mask = (USHORT) ((mask << 1) & 0xFFFF);
135 }
136
137 /* Determine if the number of bits is odd. */
138 if ((bits & 1) == 1)
139 {
140
141 /* Odd number of bits. Adjust the odd/even byte parity. */
142 even_byte_parity = (USHORT) ((even_byte_parity ^ (0xffff - i)) & 0xFFFF);
143 odd_byte_parity = odd_byte_parity ^ i;
144 }
145 }
146
147 /* Now look for bits set in the bit parity. */
148 for (i = 0; i < 16; i++)
149 {
150
151 /* Is the bit set? */
152 if (bit_parity & 1)
153 {
154
155 /* Yes, adjust the odd even byte parity. */
156 even_bit_parity = (USHORT) ((even_bit_parity ^ (15 - i)) & 0xFFFF);
157 odd_bit_parity = odd_bit_parity ^ i;
158 }
159
160 /* Look at next bit position. */
161 bit_parity = bit_parity >> 1;
162 }
163
164 /* At this point, we need to pack the 22 ECC bits into the 3 byte return area. */
165
166 /* Pack bit 21. */
167 ecc_buffer[(21+2)/8] = ((UCHAR)(ecc_buffer[(21+2)/8] | ((odd_byte_parity >> 6) & 1) << (21+2)%8) & 0xFF);
168
169 /* Pack bit 20. */
170 ecc_buffer[(20+2)/8] = ((UCHAR)(ecc_buffer[(20+2)/8] | ((even_byte_parity >> 6) & 1) << (20+2)%8) & 0xFF);
171
172 /* Pack bit 19. */
173 ecc_buffer[(19+2)/8] = ((UCHAR)(ecc_buffer[(19+2)/8] | ((odd_byte_parity >> 5) & 1) << (19+2)%8) & 0xFF);
174
175 /* Pack bit 18. */
176 ecc_buffer[(18+2)/8] = ((UCHAR)(ecc_buffer[(18+2)/8] | ((even_byte_parity >> 5) & 1) << (18+2)%8) & 0xFF);
177
178 /* Pack bit 17. */
179 ecc_buffer[(17+2)/8] = ((UCHAR)(ecc_buffer[(17+2)/8] | ((odd_byte_parity >> 4) & 1) << (17+2)%8) & 0xFF);
180
181 /* Pack bit 16. */
182 ecc_buffer[(16+2)/8] = ((UCHAR)(ecc_buffer[(16+2)/8] | ((even_byte_parity >> 4) & 1) << (16+2)%8) & 0xFF);
183
184 /* Pack bit 15. */
185 ecc_buffer[(15+2)/8] = ((UCHAR)(ecc_buffer[(15+2)/8] | ((odd_byte_parity >> 3) & 1) << (15+2)%8) & 0xFF);
186
187 /* Pack bit 14. */
188 ecc_buffer[(14+2)/8] = ((UCHAR)(ecc_buffer[(14+2)/8] | ((even_byte_parity >> 3) & 1) << (14+2)%8) & 0xFF);
189
190 /* Pack bit 13. */
191 ecc_buffer[(13+2)/8] = ((UCHAR)(ecc_buffer[(13+2)/8] | ((odd_byte_parity >> 2) & 1) << (13+2)%8) & 0xFF);
192
193 /* Pack bit 12. */
194 ecc_buffer[(12+2)/8] = ((UCHAR)(ecc_buffer[(12+2)/8] | ((even_byte_parity >> 2) & 1) << (12+2)%8) & 0xFF);
195
196 /* Pack bit 11. */
197 ecc_buffer[(11+2)/8] = ((UCHAR)(ecc_buffer[(11+2)/8] | ((odd_byte_parity >> 1) & 1) << (11+2)%8) & 0xFF);
198
199 /* Pack bit 10. */
200 ecc_buffer[(10+2)/8] = ((UCHAR)(ecc_buffer[(10+2)/8] | ((even_byte_parity >> 1) & 1) << (10+2)%8) & 0xFF);
201
202 /* Pack bit 9. */
203 ecc_buffer[(9+2)/8] = ((UCHAR)(ecc_buffer[(9+2)/8] | ((odd_byte_parity >> 0) & 1) << (9+2)%8) & 0xFF);
204
205 /* Pack bit 8. */
206 ecc_buffer[(8+2)/8] = ((UCHAR)(ecc_buffer[(8+2)/8] | ((even_byte_parity >> 0) & 1) << (8+2)%8) & 0xFF);
207
208 /* Pack bit 7. */
209 ecc_buffer[(7+2)/8] = ((UCHAR)(ecc_buffer[(7+2)/8] | ((odd_bit_parity >> 3) & 1) << (7+2)%8) & 0xFF);
210
211 /* Pack bit 6. */
212 ecc_buffer[(6+2)/8] = ((UCHAR)(ecc_buffer[(6+2)/8] | ((even_bit_parity >> 3) & 1) << (6+2)%8) & 0xFF);
213
214 /* Pack bit 5. */
215 ecc_buffer[(5+2)/8] = ((UCHAR)(ecc_buffer[(5+2)/8] | ((odd_bit_parity >> 2) & 1) << (5+2)%8) & 0xFF);
216
217 /* Pack bit 4. */
218 ecc_buffer[(4+2)/8] = ((UCHAR)(ecc_buffer[(4+2)/8] | ((even_bit_parity >> 2) & 1) << (4+2)%8) & 0xFF);
219
220 /* Pack bit 3. */
221 ecc_buffer[(3+2)/8] = ((UCHAR)(ecc_buffer[(3+2)/8] | ((odd_bit_parity >> 1) & 1) << (3+2)%8) & 0xFF);
222
223 /* Pack bit 2. */
224 ecc_buffer[(2+2)/8] = ((UCHAR)(ecc_buffer[(2+2)/8] | ((even_bit_parity >> 1) & 1) << (2+2)%8) & 0xFF);
225
226 /* Pack bit 1. */
227 ecc_buffer[(1+2)/8] = ((UCHAR)(ecc_buffer[(1+2)/8] | ((odd_bit_parity >> 0) & 1) << (1+2)%8) & 0xFF);
228
229 /* Pack bit 0. */
230 ecc_buffer[(0+2)/8] = ((UCHAR)(ecc_buffer[(0+2)/8] | ((even_bit_parity >> 0) & 1) << (0+2)%8) & 0xFF);
231
232 ecc_buffer[0] = (UCHAR)~ecc_buffer[0];
233 ecc_buffer[1] = (UCHAR)~ecc_buffer[1];
234 ecc_buffer[2] = (UCHAR)~ecc_buffer[2];
235
236 /* Return success! */
237 return(LX_SUCCESS);
238 }
239
240