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