|
1 | 1 | /*************************************************************************** |
2 | 2 | * Copyright (c) 2024 Microsoft Corporation |
| 3 | + * Copyright (c) 2025 STMicroelectronics |
3 | 4 | * |
4 | 5 | * This program and the accompanying materials are made available under the |
5 | 6 | * terms of the MIT License which is available at |
|
39 | 40 | /* FUNCTION RELEASE */ |
40 | 41 | /* */ |
41 | 42 | /* _lx_nand_flash_format PORTABLE C */ |
42 | | -/* 6.3.0 */ |
| 43 | +/* */ |
43 | 44 | /* AUTHOR */ |
44 | 45 | /* */ |
45 | 46 | /* Xiuwen Cai, Microsoft Corporation */ |
|
64 | 65 | /* return status */ |
65 | 66 | /* */ |
66 | 67 | /* CALLS */ |
67 | | -/* */ |
68 | | -/* (nand_driver_initialize) Driver initialize */ |
69 | | -/* LX_MEMSET Initialize memory */ |
70 | | -/* _lx_nand_flash_memory_initialize Initialize buffer */ |
71 | | -/* _lx_nand_flash_driver_block_status_get */ |
72 | | -/* Driver block status get */ |
73 | | -/* _lx_nand_flash_driver_block_status_set */ |
74 | | -/* Driver block status set */ |
75 | | -/* _lx_nand_flash_metadata_build Build metadata */ |
76 | | -/* _lx_nand_flash_metadata_write Write metadata */ |
77 | | -/* _lx_nand_flash_driver_block_erase Driver block erase */ |
78 | | -/* _lx_nand_flash_system_error System error handler */ |
79 | | -/* tx_mutex_create Create thread-safe mutex */ |
80 | | -/* */ |
| 68 | +/* _lx_nand_flash_format_extended */ |
| 69 | +/* */ |
81 | 70 | /* CALLED BY */ |
82 | 71 | /* */ |
83 | 72 | /* Application Code */ |
84 | 73 | /* */ |
85 | | -/* RELEASE HISTORY */ |
86 | | -/* */ |
87 | | -/* DATE NAME DESCRIPTION */ |
88 | | -/* */ |
89 | | -/* 03-08-2023 Xiuwen Cai Initial Version 6.2.1 */ |
90 | | -/* 10-31-2023 Xiuwen Cai Modified comment(s), */ |
91 | | -/* avoided clearing user */ |
92 | | -/* extension in flash control */ |
93 | | -/* block, */ |
94 | | -/* resulting in version 6.3.0 */ |
95 | | -/* */ |
96 | 74 | /**************************************************************************/ |
97 | 75 | UINT _lx_nand_flash_format(LX_NAND_FLASH* nand_flash, CHAR* name, |
98 | 76 | UINT(*nand_driver_initialize)(LX_NAND_FLASH*), |
99 | 77 | ULONG* memory_ptr, UINT memory_size) |
100 | 78 | { |
101 | 79 |
|
102 | | -ULONG block; |
103 | | -UCHAR block_status; |
104 | | -UINT status; |
105 | | -UCHAR *page_buffer_ptr; |
106 | | - |
107 | | - LX_PARAMETER_NOT_USED(name); |
108 | | - |
109 | | - /* Clear the NAND flash control block. User extension is not cleared. */ |
110 | | - LX_MEMSET(nand_flash, 0, (ULONG)((UCHAR*)&(nand_flash -> lx_nand_flash_open_previous) - (UCHAR*)nand_flash) + sizeof(nand_flash -> lx_nand_flash_open_previous)); |
111 | | - |
112 | | - /* Call the flash driver's initialization function. */ |
113 | | - (nand_driver_initialize)(nand_flash); |
114 | | - |
115 | | - /* Determine if we can support this NAND flash size. */ |
116 | | - if (nand_flash -> lx_nand_flash_pages_per_block > LX_NAND_MAX_PAGE_PER_BLOCK || nand_flash -> lx_nand_flash_total_blocks > LX_NAND_MAX_BLOCK_COUNT) |
117 | | - { |
118 | | - return(LX_ERROR); |
119 | | - } |
120 | | - |
121 | | - /* Check if it is new LevelX NAND driver. */ |
122 | | - if (nand_flash -> lx_nand_flash_driver_pages_read == LX_NULL || nand_flash -> lx_nand_flash_driver_pages_write == LX_NULL || nand_flash -> lx_nand_flash_driver_pages_copy == LX_NULL) |
123 | | - { |
124 | | - return(LX_ERROR); |
125 | | - } |
126 | | - |
127 | | - /* Check the spare data length. */ |
128 | | - if (nand_flash -> lx_nand_flash_spare_data1_length < sizeof(ULONG)) |
129 | | - { |
130 | | - return(LX_ERROR); |
131 | | - } |
132 | | - |
133 | | - /* Calculate the number of words per block and per page. */ |
134 | | - nand_flash -> lx_nand_flash_words_per_page = (nand_flash -> lx_nand_flash_bytes_per_page / sizeof(ULONG)); |
135 | | - nand_flash -> lx_nand_flash_words_per_block = (nand_flash -> lx_nand_flash_words_per_page * nand_flash -> lx_nand_flash_pages_per_block); |
136 | | - |
137 | | - /* Calculate the total pages. */ |
138 | | - nand_flash -> lx_nand_flash_total_pages = nand_flash -> lx_nand_flash_total_blocks * nand_flash -> lx_nand_flash_pages_per_block; |
139 | | - |
140 | | - /* Initialize memory buffer. */ |
141 | | - status = _lx_nand_flash_memory_initialize(nand_flash, memory_ptr, memory_size); |
142 | | - if (status != LX_SUCCESS) |
143 | | - { |
144 | | - return(status); |
145 | | - } |
146 | | - |
147 | | - /* Initialize block numbers. */ |
148 | | - nand_flash -> lx_nand_flash_metadata_block_number = LX_NAND_BLOCK_UNMAPPED; |
149 | | - nand_flash -> lx_nand_flash_metadata_block_number_next = LX_NAND_BLOCK_UNMAPPED; |
150 | | - nand_flash -> lx_nand_flash_backup_metadata_block_number = LX_NAND_BLOCK_UNMAPPED; |
151 | | - nand_flash -> lx_nand_flash_backup_metadata_block_number_next = LX_NAND_BLOCK_UNMAPPED; |
152 | | - |
153 | | - /* Initialize the block status buffer. */ |
154 | | - LX_MEMSET(nand_flash -> lx_nand_flash_block_status_table, 0xFF, nand_flash -> lx_nand_flash_block_status_table_size); |
155 | | - |
156 | | - /* Loop through the blocks to check for bad blocks and determine the minimum and maximum erase count for each good block. */ |
157 | | - for (block = 0; block < nand_flash -> lx_nand_flash_total_blocks; block++) |
158 | | - { |
159 | | - |
160 | | - /* First, check to make sure this block is good. */ |
161 | | - status = _lx_nand_flash_driver_block_status_get(nand_flash, block, &block_status); |
162 | | - |
163 | | - /* Check for an error from flash driver. */ |
164 | | - if (status) |
165 | | - { |
166 | | - |
167 | | - /* Call system error handler. */ |
168 | | - _lx_nand_flash_system_error(nand_flash, status, block, 0); |
169 | | - |
170 | | - /* Return an error. */ |
171 | | - return(LX_ERROR); |
172 | | - } |
| 80 | +UINT status; |
173 | 81 |
|
174 | | - /* Is this block bad? */ |
175 | | - if (block_status != LX_NAND_GOOD_BLOCK) |
176 | | - { |
| 82 | + status = _lx_nand_flash_format_extended(nand_flash, name, nand_driver_initialize, NULL, memory_ptr, memory_size); |
177 | 83 |
|
178 | | - /* Yes, this block is bad. */ |
179 | | - |
180 | | - /* Increment the number of bad blocks. */ |
181 | | - nand_flash -> lx_nand_flash_bad_blocks++; |
182 | | - |
183 | | - /* Save the block status. */ |
184 | | - nand_flash -> lx_nand_flash_block_status_table[block] = LX_NAND_BLOCK_STATUS_BAD; |
185 | | - |
186 | | - /* Continue to the next block. */ |
187 | | - continue; |
188 | | - } |
189 | | - |
190 | | - /* Erase the block. */ |
191 | | - status = _lx_nand_flash_driver_block_erase(nand_flash, block, 0); |
192 | | - |
193 | | - /* Check for an error from flash driver. */ |
194 | | - if (status) |
195 | | - { |
196 | | - |
197 | | - /* Call system error handler. */ |
198 | | - _lx_nand_flash_system_error(nand_flash, status, block, 0); |
199 | | - |
200 | | - /* Attempt to mark this block as bad. */ |
201 | | - status = _lx_nand_flash_driver_block_status_set(nand_flash, block, LX_NAND_BAD_BLOCK); |
202 | | - |
203 | | - /* Check for error in setting the block status. */ |
204 | | - if (status) |
205 | | - { |
206 | | - |
207 | | - /* Call system error handler. */ |
208 | | - _lx_nand_flash_system_error(nand_flash, status, block, 0); |
209 | | - } |
210 | | - |
211 | | - /* Increment the bad block count. */ |
212 | | - nand_flash -> lx_nand_flash_bad_blocks++; |
213 | | - |
214 | | - /* Save the block status. */ |
215 | | - nand_flash -> lx_nand_flash_block_status_table[block] = LX_NAND_BLOCK_STATUS_BAD; |
216 | | - } |
217 | | - else |
218 | | - { |
219 | | - |
220 | | - /* Allocate blocks for metadata. */ |
221 | | - if (nand_flash -> lx_nand_flash_metadata_block_number == LX_NAND_BLOCK_UNMAPPED) |
222 | | - { |
223 | | - nand_flash -> lx_nand_flash_metadata_block_number = block; |
224 | | - nand_flash -> lx_nand_flash_metadata_block_number_current = block; |
225 | | - } |
226 | | - else if (nand_flash -> lx_nand_flash_backup_metadata_block_number == LX_NAND_BLOCK_UNMAPPED) |
227 | | - { |
228 | | - nand_flash -> lx_nand_flash_backup_metadata_block_number = block; |
229 | | - nand_flash -> lx_nand_flash_backup_metadata_block_number_current = block; |
230 | | - } |
231 | | - else if (nand_flash -> lx_nand_flash_metadata_block_number_next == LX_NAND_BLOCK_UNMAPPED) |
232 | | - { |
233 | | - nand_flash -> lx_nand_flash_metadata_block_number_next = block; |
234 | | - } |
235 | | - else if (nand_flash -> lx_nand_flash_backup_metadata_block_number_next == LX_NAND_BLOCK_UNMAPPED) |
236 | | - { |
237 | | - nand_flash -> lx_nand_flash_backup_metadata_block_number_next = block; |
238 | | - } |
239 | | - } |
240 | | - } |
241 | | - |
242 | | - /* There should be enough blocks for metadata. */ |
243 | | - if (nand_flash -> lx_nand_flash_backup_metadata_block_number_next == LX_NAND_BLOCK_UNMAPPED) |
244 | | - { |
245 | | - return (LX_NO_BLOCKS); |
246 | | - } |
247 | | - |
248 | | - /* Save the block status for metadata. */ |
249 | | - nand_flash -> lx_nand_flash_block_status_table[nand_flash -> lx_nand_flash_backup_metadata_block_number_next] = LX_NAND_BLOCK_STATUS_ALLOCATED; |
250 | | - nand_flash -> lx_nand_flash_block_status_table[nand_flash -> lx_nand_flash_metadata_block_number_next] = LX_NAND_BLOCK_STATUS_ALLOCATED; |
251 | | - nand_flash -> lx_nand_flash_block_status_table[nand_flash -> lx_nand_flash_backup_metadata_block_number] = (USHORT)nand_flash -> lx_nand_flash_backup_metadata_block_number_next; |
252 | | - nand_flash -> lx_nand_flash_block_status_table[nand_flash -> lx_nand_flash_metadata_block_number] = (USHORT)nand_flash -> lx_nand_flash_metadata_block_number_next; |
253 | | - |
254 | | - /* Initialize the mapping table. */ |
255 | | - LX_MEMSET(nand_flash -> lx_nand_flash_block_mapping_table, 0xFF, nand_flash -> lx_nand_flash_block_mapping_table_size); |
256 | | - |
257 | | - /* Build initial metadata. */ |
258 | | - status = _lx_nand_flash_metadata_build(nand_flash); |
259 | | - if (status != LX_SUCCESS) |
260 | | - { |
261 | | - /* Return error status. */ |
262 | | - return(status); |
263 | | - } |
264 | | - |
265 | | - /* Get buffer for page data. */ |
266 | | - page_buffer_ptr = nand_flash -> lx_nand_flash_page_buffer; |
267 | | - |
268 | | - /* Initialize the page buffer. */ |
269 | | - LX_MEMSET(page_buffer_ptr, 0xFF, nand_flash -> lx_nand_flash_bytes_per_page); |
270 | | - |
271 | | - /* Set the next block numbers. */ |
272 | | - LX_UTILITY_LONG_SET(&page_buffer_ptr[LX_NAND_BLOCK_LINK_MAIN_METADATA_OFFSET], nand_flash -> lx_nand_flash_metadata_block_number_next); |
273 | | - LX_UTILITY_LONG_SET(&page_buffer_ptr[LX_NAND_BLOCK_LINK_BACKUP_METADATA_OFFSET], nand_flash -> lx_nand_flash_backup_metadata_block_number_next); |
274 | | - |
275 | | - /* Save the next block numbers to metadata block. */ |
276 | | - status = _lx_nand_flash_metadata_write(nand_flash, page_buffer_ptr, LX_NAND_PAGE_TYPE_BLOCK_LINK); |
277 | | - |
278 | | - if (status != LX_SUCCESS) |
279 | | - { |
280 | | - /* Return error status. */ |
281 | | - return(status); |
282 | | - } |
283 | | - |
284 | | - /* Return a successful completion. */ |
285 | | - return(LX_SUCCESS); |
| 84 | + return status; |
286 | 85 | } |
287 | | - |
0 commit comments