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_block_data_move                      PORTABLE C      */
43 /*                                                           6.2.1       */
44 /*  AUTHOR                                                                */
45 /*                                                                        */
46 /*    Xiuwen Cai, Microsoft Corporation                                   */
47 /*                                                                        */
48 /*  DESCRIPTION                                                           */
49 /*                                                                        */
50 /*    This function finds a block with less erase count and copies pages  */
51 /*    into new block.                                                     */
52 /*                                                                        */
53 /*  INPUT                                                                 */
54 /*                                                                        */
55 /*    nand_flash                            NAND flash instance           */
56 /*    new_block                             New block number              */
57 /*                                                                        */
58 /*  OUTPUT                                                                */
59 /*                                                                        */
60 /*    return status                                                       */
61 /*                                                                        */
62 /*  CALLS                                                                 */
63 /*                                                                        */
64 /*    _lx_nand_flash_mapped_block_list_get  Get mapped block index        */
65 /*    _lx_nand_flash_block_find             Find the mapped block         */
66 /*    _lx_nand_flash_data_page_copy         Copy data pages               */
67 /*    _lx_nand_flash_free_block_list_add    Add free block to list        */
68 /*    _lx_nand_flash_block_status_set       Set block status              */
69 /*    _lx_nand_flash_block_mapping_set      Set block mapping             */
70 /*    _lx_nand_flash_mapped_block_list_add  Add mapped block to list      */
71 /*    _lx_nand_flash_driver_block_erase     Erase block                   */
72 /*    _lx_nand_flash_erase_count_set        Set erase count               */
73 /*    _lx_nand_flash_free_block_list_add    Add free block to list        */
74 /*    _lx_nand_flash_system_error           Internal system error handler */
75 /*    tx_mutex_get                          Get thread protection         */
76 /*    tx_mutex_put                          Release thread protection     */
77 /*                                                                        */
78 /*  CALLED BY                                                             */
79 /*                                                                        */
80 /*    Application Code                                                    */
81 /*                                                                        */
82 /*  RELEASE HISTORY                                                       */
83 /*                                                                        */
84 /*    DATE              NAME                      DESCRIPTION             */
85 /*                                                                        */
86 /*  03-08-2023     Xiuwen Cai               Initial Version 6.2.1        */
87 /*                                                                        */
88 /**************************************************************************/
_lx_nand_flash_block_data_move(LX_NAND_FLASH * nand_flash,ULONG new_block)89 UINT  _lx_nand_flash_block_data_move(LX_NAND_FLASH *nand_flash, ULONG new_block)
90 {
91 
92 UINT        status;
93 ULONG       block;
94 USHORT      block_status;
95 USHORT      new_block_status;
96 ULONG       block_mapping_index;
97 
98 
99     /* Get the mapped address to move the data.  */
100     status = _lx_nand_flash_mapped_block_list_get(nand_flash, &block_mapping_index);
101 
102     if (status)
103     {
104 
105         /* Return an error.  */
106         return(LX_ERROR);
107     }
108 
109     /* Find the block number to be moved.  */
110     status = _lx_nand_flash_block_find(nand_flash, block_mapping_index * nand_flash -> lx_nand_flash_pages_per_block, &block, &block_status);
111 
112     /* Check the status.  */
113     if (status)
114     {
115 
116         /* Return an error.  */
117         return(LX_ERROR);
118     }
119 
120     /* Set new block status to allocated for now.  */
121     new_block_status = LX_NAND_BLOCK_STATUS_ALLOCATED;
122 
123     /* Copy data from old block to new block.  */
124     status = _lx_nand_flash_data_page_copy(nand_flash, block_mapping_index * nand_flash -> lx_nand_flash_pages_per_block, block, block_status, new_block, &new_block_status, nand_flash -> lx_nand_flash_pages_per_block);
125 
126     /* Check the status.  */
127     if (status)
128     {
129 
130         /* Call system error handler.  */
131         _lx_nand_flash_system_error(nand_flash, status, new_block, 0);
132 
133         /* Return an error.  */
134         return(LX_ERROR);
135     }
136 
137     /* Check if no page was written.  */
138     if ((new_block_status & LX_NAND_BLOCK_STATUS_PAGE_NUMBER_MASK) == 0)
139     {
140 
141         /* Mark the new block as free.  */
142         new_block_status = LX_NAND_BLOCK_STATUS_FREE;
143 
144         /* Add the new block to free list.  */
145         _lx_nand_flash_free_block_list_add(nand_flash, new_block);
146 
147     }
148 
149     /* Set the block status for the new block.  */
150     status = _lx_nand_flash_block_status_set(nand_flash, new_block, new_block_status);
151 
152     /* Check for an error from flash driver.   */
153     if (status)
154     {
155 
156         /* Call system error handler.  */
157         _lx_nand_flash_system_error(nand_flash, status, new_block, 0);
158 
159         /* Return an error.  */
160         return(LX_ERROR);
161     }
162 
163     /* Check if the block is actually mapped.  */
164     if (new_block_status == LX_NAND_BLOCK_STATUS_FREE)
165     {
166 
167         /* Unmap the block.  */
168         new_block = LX_NAND_BLOCK_UNMAPPED;
169     }
170 
171     /* Update block mapping.  */
172     _lx_nand_flash_block_mapping_set(nand_flash, block_mapping_index * nand_flash -> lx_nand_flash_pages_per_block, new_block);
173 
174     /* Check if the block is actually mapped.  */
175     if (new_block != LX_NAND_BLOCK_UNMAPPED)
176     {
177 
178         /* Add the block to mapped list.  */
179         _lx_nand_flash_mapped_block_list_add(nand_flash, block_mapping_index);
180     }
181 
182     /* Erase the old block.  */
183     status = _lx_nand_flash_driver_block_erase(nand_flash, block, nand_flash -> lx_nand_flash_base_erase_count + nand_flash -> lx_nand_flash_erase_count_table[block] + 1);
184 
185     /* Check for an error from flash driver.   */
186     if (status)
187     {
188 
189         /* Call system error handler.  */
190         _lx_nand_flash_system_error(nand_flash, status, block, 0);
191 
192         /* Return an error.  */
193         return(LX_ERROR);
194     }
195 
196     /* Update the erase count for the erased block.  */
197     status = _lx_nand_flash_erase_count_set(nand_flash, block, (UCHAR)(nand_flash -> lx_nand_flash_erase_count_table[block] + 1));
198 
199     /* Check for an error from flash driver.   */
200     if (status)
201     {
202 
203         /* Call system error handler.  */
204         _lx_nand_flash_system_error(nand_flash, status, block, 0);
205 
206         /* Return an error.  */
207         return(LX_ERROR);
208     }
209 
210     /* Set the block status to free.  */
211     status = _lx_nand_flash_block_status_set(nand_flash, block, LX_NAND_BLOCK_STATUS_FREE);
212 
213     /* Check for an error from flash driver.   */
214     if (status)
215     {
216 
217         /* Call system error handler.  */
218         _lx_nand_flash_system_error(nand_flash, status, block, 0);
219 
220 
221         /* Return an error.  */
222         return(LX_ERROR);
223     }
224 
225     /* Add the block to free block list.  */
226     status = _lx_nand_flash_free_block_list_add(nand_flash, block);
227 
228     /* Return status.  */
229     return(status);
230 }
231 
232