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