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