GCC Code Coverage Report


Directory: common/src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 62.2% 61 / 0 / 98
Functions: 100.0% 1 / 0 / 1
Branches: 64.2% 79 / 0 / 123

lx_nand_flash_sector_release.c
Line Branch Exec Source
1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 * Copyright (c) 2026-present Eclipse ThreadX contributors
4 *
5 * This program and the accompanying materials are made available under the
6 * terms of the MIT License which is available at
7 * https://opensource.org/licenses/MIT.
8 *
9 * SPDX-License-Identifier: MIT
10 **************************************************************************/
11
12 // Portions of this file were generated with AI assistance.
13
14 /**************************************************************************/
15 /**************************************************************************/
16 /** */
17 /** LevelX Component */
18 /** */
19 /** NAND Flash */
20 /** */
21 /**************************************************************************/
22 /**************************************************************************/
23
24 #define LX_SOURCE_CODE
25
26
27 /* Disable ThreadX error checking. */
28
29 #ifndef LX_DISABLE_ERROR_CHECKING
30 #define LX_DISABLE_ERROR_CHECKING
31 #endif
32
33
34 /* Include necessary system files. */
35
36 #include "lx_api.h"
37
38
39 /**************************************************************************/
40 /* */
41 /* FUNCTION RELEASE */
42 /* */
43 /* _lx_nand_flash_sector_release PORTABLE C */
44 /* 6.2.1 */
45 /* AUTHOR */
46 /* */
47 /* Xiuwen Cai, Microsoft Corporation */
48 /* */
49 /* DESCRIPTION */
50 /* */
51 /* This function releases a logical sector from being managed in the */
52 /* NAND flash. */
53 /* */
54 /* INPUT */
55 /* */
56 /* nand_flash NAND flash instance */
57 /* logical_sector Logical sector number */
58 /* */
59 /* OUTPUT */
60 /* */
61 /* return status */
62 /* */
63 /* CALLS */
64 /* */
65 /* _lx_nand_flash_block_find Find the mapped block */
66 /* lx_nand_flash_driver_pages_read Read pages */
67 /* _lx_nand_flash_block_allocate Allocate block */
68 /* _lx_nand_flash_mapped_block_list_remove */
69 /* Remove mapped block */
70 /* _lx_nand_flash_data_page_copy Copy data pages */
71 /* _lx_nand_flash_free_block_list_add Add free block to list */
72 /* _lx_nand_flash_block_mapping_set Set block mapping */
73 /* _lx_nand_flash_driver_block_erase Erase block */
74 /* _lx_nand_flash_erase_count_set Set erase count */
75 /* _lx_nand_flash_block_data_move Move block data */
76 /* _lx_nand_flash_block_status_set Set block status */
77 /* _lx_nand_flash_mapped_block_list_add Add mapped block to list */
78 /* _lx_nand_flash_system_error Internal system error handler */
79 /* tx_mutex_get Get thread protection */
80 /* tx_mutex_put Release thread protection */
81 /* */
82 /* CALLED BY */
83 /* */
84 /* Application Code */
85 /* */
86 /**************************************************************************/
87 67380 UINT _lx_nand_flash_sector_release(LX_NAND_FLASH *nand_flash, ULONG logical_sector)
88 {
89
90 UINT status;
91 ULONG block;
92 USHORT block_status;
93 UCHAR *spare_buffer_ptr;
94 ULONG available_pages;
95 LONG page;
96 67380 UINT release_sector = LX_FALSE;
97 ULONG new_block;
98 USHORT new_block_status;
99
100 #ifdef LX_THREAD_SAFE_ENABLE
101
102 /* Obtain the thread safe mutex. */
103 6738 tx_mutex_get(&nand_flash -> lx_nand_flash_mutex, TX_WAIT_FOREVER);
104 #endif
105
106 /* Increment the number of release requests. */
107 67380 nand_flash -> lx_nand_flash_diagnostic_sector_release_requests++;
108
109
110 /* See if we can find the sector in the current mapping. */
111 67380 status = _lx_nand_flash_block_find(nand_flash, logical_sector, &block, &block_status);
112
113 /* Check return status. */
114
2/4
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 7 taken 60642 times.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 9 taken 6738 times.
67380 if (status != LX_SUCCESS)
115 {
116
117 /* Call system error handler. */
118 ✗ _lx_nand_flash_system_error(nand_flash, status, block, 0);
119
120 /* Determine if the error is fatal. */
121 ✗ if (status != LX_NAND_ERROR_CORRECTED)
122 {
123 #ifdef LX_THREAD_SAFE_ENABLE
124
125 /* Release the thread safe mutex. */
126 ✗ tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
127 #endif
128
129 /* Return an error. */
130 ✗ return(LX_ERROR);
131 }
132 }
133
134 /* Determine if the block is mapped. */
135
5/5
✓ Branch 7 → 8 taken 3222 times.
✓ Branch 7 → 77 taken 19140 times.
✓ Branch 7 → 80 taken 38280 times.
✓ Branch 9 → 10 taken 358 times.
✓ Branch 9 → 92 taken 6380 times.
67380 if (block != LX_NAND_BLOCK_UNMAPPED)
136 {
137
138 /* Setup spare buffer pointer. */
139 3580 spare_buffer_ptr = (UCHAR*)nand_flash -> lx_nand_flash_page_buffer;
140
141 /* Get available pages in this block. */
142
4/4
✓ Branch 8 → 9 taken 18 times.
✓ Branch 8 → 10 taken 3204 times.
✓ Branch 10 → 11 taken 2 times.
✓ Branch 10 → 12 taken 356 times.
3580 available_pages = block_status & LX_NAND_BLOCK_STATUS_FULL ? nand_flash -> lx_nand_flash_pages_per_block : block_status & LX_NAND_BLOCK_STATUS_PAGE_NUMBER_MASK;
143
144 /* Determine if the pages are recorded sequentially. */
145
4/4
✓ Branch 11 → 12 taken 3204 times.
✓ Branch 11 → 22 taken 18 times.
✓ Branch 13 → 14 taken 356 times.
✓ Branch 13 → 25 taken 2 times.
3580 if (block_status & LX_NAND_BLOCK_STATUS_NON_SEQUENTIAL)
146 {
147
148 /* Loop to search the logical page. */
149
4/4
✓ Branch 21 → 13 taken 102717 times.
✓ Branch 21 → 24 taken 3204 times.
✓ Branch 24 → 15 taken 11413 times.
✓ Branch 24 → 27 taken 356 times.
117690 for (page = (LONG)available_pages - 1; page >= 0; page--)
150 {
151
152 /* Read a page. */
153 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
154 11413 status = (nand_flash -> lx_nand_flash_driver_pages_read)(nand_flash, block, (ULONG)page, LX_NULL, spare_buffer_ptr, 1);
155 #else
156 102717 status = (nand_flash -> lx_nand_flash_driver_pages_read)(block, (ULONG)page, LX_NULL, spare_buffer_ptr, 1);
157 #endif
158
159 /* Check for an error from flash driver. */
160
2/4
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 17 taken 102717 times.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 20 taken 11413 times.
114130 if (status)
161 {
162
163 /* Call system error handler. */
164 ✗ _lx_nand_flash_system_error(nand_flash, status, block, 0);
165 #ifdef LX_THREAD_SAFE_ENABLE
166
167 /* Release the thread safe mutex. */
168 ✗ tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
169 #endif
170
171 /* Return an error. */
172 ✗ return(LX_ERROR);
173 }
174
175 /* Get the logical sector number from spare bytes, and check if it matches the addressed sector number. */
176
4/4
✓ Branch 17 → 18 taken 468 times.
✓ Branch 17 → 20 taken 102249 times.
✓ Branch 20 → 21 taken 52 times.
✓ Branch 20 → 23 taken 11361 times.
114130 if ((LX_UTILITY_LONG_GET(&spare_buffer_ptr[nand_flash -> lx_nand_flash_spare_data1_offset]) & LX_NAND_PAGE_TYPE_USER_DATA_MASK) == logical_sector)
177 {
178
179 /* Make sure the sector is not released. */
180
2/4
✓ Branch 18 → 19 taken 468 times.
✗ Branch 18 → 20 not taken.
✓ Branch 21 → 22 taken 52 times.
✗ Branch 21 → 23 not taken.
520 if ((LX_UTILITY_LONG_GET(&spare_buffer_ptr[nand_flash -> lx_nand_flash_spare_data1_offset]) & (~LX_NAND_PAGE_TYPE_USER_DATA_MASK)) == (LX_NAND_PAGE_TYPE_USER_DATA))
181 {
182
183 /* Set release sector flag. */
184 520 release_sector = LX_TRUE;
185 }
186 }
187 }
188 }
189 else
190 {
191
192 /* Check if the logical sector is available. */
193
2/4
✓ Branch 22 → 23 taken 18 times.
✗ Branch 22 → 24 not taken.
✓ Branch 25 → 26 taken 2 times.
✗ Branch 25 → 27 not taken.
20 if (logical_sector % nand_flash -> lx_nand_flash_pages_per_block < available_pages)
194 {
195
196 /* Set release sector flag. */
197 20 release_sector = LX_TRUE;
198 }
199 }
200
201 /* Determine if the sector needs to be released. */
202
5/5
✓ Branch 24 → 25 taken 486 times.
✓ Branch 24 → 77 taken 912 times.
✓ Branch 24 → 80 taken 1824 times.
✓ Branch 27 → 28 taken 54 times.
✓ Branch 27 → 92 taken 304 times.
3580 if (release_sector)
203 {
204
205 /* Check if the block is full. */
206
4/4
✓ Branch 25 → 26 taken 18 times.
✓ Branch 25 → 65 taken 468 times.
✓ Branch 28 → 29 taken 2 times.
✓ Branch 28 → 75 taken 52 times.
540 if (block_status & LX_NAND_BLOCK_STATUS_FULL)
207 {
208
209 #ifdef LX_NAND_FLASH_ENABLE_LAZY_SECTOR_RELEASE
210 /* Lazy path: defer the copy+erase when enough free blocks are available.
211 The old block is kept as a compaction source; a new block holds only
212 the tombstone for the released sector. */
213 if (nand_flash -> lx_nand_flash_free_block_list_tail >
214 (ULONG)LX_NAND_FLASH_SECTOR_RELEASE_LAZY_THRESHOLD)
215 {
216
217 /* Allocate a new block for the tombstone. */
218 status = _lx_nand_flash_block_allocate(nand_flash, &new_block);
219
220 /* Check return status. */
221 if (status != LX_SUCCESS)
222 {
223
224 /* Call system error handler. */
225 _lx_nand_flash_system_error(nand_flash, status, new_block, 0);
226 #ifdef LX_THREAD_SAFE_ENABLE
227
228 /* Release the thread safe mutex. */
229 tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
230 #endif
231 /* Return an error. */
232 return(LX_ERROR);
233 }
234
235 /* Set page buffer to all 0xFF (data = erased, sector is released). */
236 LX_MEMSET(nand_flash -> lx_nand_flash_page_buffer, 0xFF,
237 nand_flash -> lx_nand_flash_bytes_per_page +
238 nand_flash -> lx_nand_flash_spare_total_length);
239
240 /* Setup spare buffer pointer. */
241 spare_buffer_ptr = nand_flash -> lx_nand_flash_page_buffer +
242 nand_flash -> lx_nand_flash_bytes_per_page;
243
244 /* Save metadata block number in spare bytes if space allows. */
245 if (nand_flash -> lx_nand_flash_spare_data2_length >= sizeof(USHORT))
246 {
247 LX_UTILITY_SHORT_SET(&spare_buffer_ptr[nand_flash -> lx_nand_flash_spare_data2_offset],
248 nand_flash -> lx_nand_flash_metadata_block_number);
249 }
250
251 /* Set page type to USER_DATA_RELEASED. */
252 LX_UTILITY_LONG_SET(&spare_buffer_ptr[nand_flash -> lx_nand_flash_spare_data1_offset],
253 LX_NAND_PAGE_TYPE_USER_DATA_RELEASED | logical_sector);
254
255 /* Write the tombstone page to page 0 of the new block. */
256 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
257 status = (nand_flash -> lx_nand_flash_driver_pages_write)(nand_flash, new_block, 0,
258 (UCHAR*)nand_flash -> lx_nand_flash_page_buffer, spare_buffer_ptr, 1);
259 #else
260 status = (nand_flash -> lx_nand_flash_driver_pages_write)(new_block, 0,
261 (UCHAR*)nand_flash -> lx_nand_flash_page_buffer, spare_buffer_ptr, 1);
262 #endif
263
264 /* Check for an error from flash driver. */
265 if (status)
266 {
267 _lx_nand_flash_system_error(nand_flash, status, new_block, 0);
268 #ifdef LX_THREAD_SAFE_ENABLE
269 tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
270 #endif
271 return(LX_ERROR);
272 }
273
274 /* Set new block status: allocated, non-sequential, 1 page written. */
275 new_block_status = (USHORT)(LX_NAND_BLOCK_STATUS_ALLOCATED |
276 LX_NAND_BLOCK_STATUS_NON_SEQUENTIAL | 1u);
277 status = _lx_nand_flash_block_status_set(nand_flash, new_block, new_block_status);
278 if (status)
279 {
280 _lx_nand_flash_system_error(nand_flash, status, new_block, 0);
281 #ifdef LX_THREAD_SAFE_ENABLE
282 tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
283 #endif
284 return(LX_ERROR);
285 }
286
287 /* Mark old block as compaction-pending (persisted to flash).
288 Write order: tombstone written → new_block status set →
289 COMPACTION_PENDING set → mapping updated.
290 This ordering ensures safe crash recovery at open time. */
291 status = _lx_nand_flash_block_status_set(nand_flash, block,
292 (USHORT)(block_status | LX_NAND_BLOCK_STATUS_COMPACTION_PENDING));
293 if (status)
294 {
295 _lx_nand_flash_system_error(nand_flash, status, block, 0);
296 #ifdef LX_THREAD_SAFE_ENABLE
297 tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
298 #endif
299 return(LX_ERROR);
300 }
301
302 /* Remove old mapping before updating to new block. */
303 _lx_nand_flash_mapped_block_list_remove(nand_flash,
304 logical_sector / nand_flash -> lx_nand_flash_pages_per_block);
305
306 /* Update logical-to-physical mapping to the new tombstone block. */
307 _lx_nand_flash_block_mapping_set(nand_flash, logical_sector, new_block);
308
309 /* Record the old block as the compaction source (RAM only; rebuilt at open). */
310 nand_flash -> lx_nand_flash_block_compaction_table[logical_sector / nand_flash -> lx_nand_flash_pages_per_block] = (USHORT)block;
311
312 /* Add new tombstone block to the mapped list. */
313 _lx_nand_flash_mapped_block_list_add(nand_flash,
314 logical_sector / nand_flash -> lx_nand_flash_pages_per_block);
315 }
316 else
317 #endif /* LX_NAND_FLASH_ENABLE_LAZY_SECTOR_RELEASE */
318 {
319
320 /* Eager path (existing): allocate a new block and copy + erase immediately. */
321
322 /* Allocate a new block. */
323 20 status = _lx_nand_flash_block_allocate(nand_flash, &new_block);
324
325 /* Check return status. */
326
2/4
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 30 taken 18 times.
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 34 taken 2 times.
20 if (status != LX_SUCCESS)
327 {
328 /* Call system error handler. */
329 ✗ _lx_nand_flash_system_error(nand_flash, status, new_block, 0);
330 #ifdef LX_THREAD_SAFE_ENABLE
331
332 /* Release the thread safe mutex. */
333 ✗ tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
334 #endif
335
336 /* Return an error. */
337 ✗ return(LX_ERROR);
338
339 }
340
341 /* Set new block status to allocated. */
342 20 new_block_status = LX_NAND_BLOCK_STATUS_ALLOCATED;
343
344 /* Remove the old block from mapped block list. */
345 20 _lx_nand_flash_mapped_block_list_remove(nand_flash, logical_sector / nand_flash -> lx_nand_flash_pages_per_block);
346
347 /* Copy valid sector to new block. */
348 20 status = _lx_nand_flash_data_page_copy(nand_flash, logical_sector - (logical_sector % nand_flash -> lx_nand_flash_pages_per_block), block, block_status, new_block, &new_block_status, (logical_sector % nand_flash -> lx_nand_flash_pages_per_block));
349
350 /* Check for an error from flash driver. */
351
2/4
✗ Branch 32 → 33 not taken.
✓ Branch 32 → 35 taken 18 times.
✗ Branch 36 → 37 not taken.
✓ Branch 36 → 40 taken 2 times.
20 if (status)
352 {
353
354 /* Call system error handler. */
355 ✗ _lx_nand_flash_system_error(nand_flash, status, new_block, 0);
356 #ifdef LX_THREAD_SAFE_ENABLE
357
358 /* Release the thread safe mutex. */
359 ✗ tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
360 #endif
361
362 /* Return an error. */
363 ✗ return(LX_ERROR);
364 }
365
366 /* Determine if there are sectors after the addressed sector need to be copied. */
367
2/4
✓ Branch 35 → 36 taken 18 times.
✗ Branch 35 → 40 not taken.
✓ Branch 40 → 41 taken 2 times.
✗ Branch 40 → 46 not taken.
20 if (logical_sector % nand_flash -> lx_nand_flash_pages_per_block < nand_flash -> lx_nand_flash_pages_per_block - 1)
368 {
369
370 /* Copy valid sector to new block. */
371 20 status = _lx_nand_flash_data_page_copy(nand_flash, logical_sector + 1, block, block_status, new_block, &new_block_status, (nand_flash -> lx_nand_flash_pages_per_block - 1) - (logical_sector % nand_flash -> lx_nand_flash_pages_per_block));
372
373 /* Check for an error from flash driver. */
374
2/4
✗ Branch 37 → 38 not taken.
✓ Branch 37 → 40 taken 18 times.
✗ Branch 42 → 43 not taken.
✓ Branch 42 → 46 taken 2 times.
20 if (status)
375 {
376
377 /* Call system error handler. */
378 ✗ _lx_nand_flash_system_error(nand_flash, status, new_block, 0);
379 #ifdef LX_THREAD_SAFE_ENABLE
380
381 /* Release the thread safe mutex. */
382 ✗ tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
383 #endif
384
385 /* Return an error. */
386 ✗ return(LX_ERROR);
387 }
388 }
389
390 /* Check new block status to see if there is valid pages in the block. */
391
2/4
✗ Branch 40 → 41 not taken.
✓ Branch 40 → 43 taken 18 times.
✗ Branch 46 → 47 not taken.
✓ Branch 46 → 49 taken 2 times.
20 if ((new_block_status & LX_NAND_BLOCK_STATUS_PAGE_NUMBER_MASK) == 0)
392 {
393
394 /* Add the block to free block list. */
395 ✗ _lx_nand_flash_free_block_list_add(nand_flash, new_block);
396
397 /* Set new block to unmapped. */
398 ✗ new_block = LX_NAND_BLOCK_UNMAPPED;
399 }
400 else
401 {
402
403 /* Set new block status. */
404 20 status = _lx_nand_flash_block_status_set(nand_flash, new_block, new_block_status);
405
406 /* Check for an error from flash driver. */
407
2/4
✗ Branch 44 → 45 not taken.
✓ Branch 44 → 47 taken 18 times.
✗ Branch 50 → 51 not taken.
✓ Branch 50 → 54 taken 2 times.
20 if (status)
408 {
409
410 /* Call system error handler. */
411 ✗ _lx_nand_flash_system_error(nand_flash, status, block, 0);
412 #ifdef LX_THREAD_SAFE_ENABLE
413
414 /* Release the thread safe mutex. */
415 ✗ tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
416 #endif
417
418 /* Return an error. */
419 ✗ return(LX_ERROR);
420 }
421 }
422
423 /* Update block mapping. */
424 20 _lx_nand_flash_block_mapping_set(nand_flash, logical_sector, new_block);
425
426 /* Erase old block. */
427 20 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);
428
429 /* Check for an error from flash driver. */
430
2/4
✗ Branch 49 → 50 not taken.
✓ Branch 49 → 52 taken 18 times.
✗ Branch 56 → 57 not taken.
✓ Branch 56 → 60 taken 2 times.
20 if (status)
431 {
432
433 /* Call system error handler. */
434 ✗ _lx_nand_flash_system_error(nand_flash, status, block, 0);
435 #ifdef LX_THREAD_SAFE_ENABLE
436
437 /* Release the thread safe mutex. */
438 ✗ tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
439 #endif
440
441 /* Return an error. */
442 ✗ return(LX_ERROR);
443 }
444
445 /* Update erase count for the old block. */
446 20 status = _lx_nand_flash_erase_count_set(nand_flash, block, (UCHAR)(nand_flash -> lx_nand_flash_erase_count_table[block] + 1));
447
448 /* Check for an error from flash driver. */
449
2/4
✗ Branch 53 → 54 not taken.
✓ Branch 53 → 56 taken 18 times.
✗ Branch 61 → 62 not taken.
✓ Branch 61 → 65 taken 2 times.
20 if (status)
450 {
451
452 /* Call system error handler. */
453 ✗ _lx_nand_flash_system_error(nand_flash, status, block, 0);
454 #ifdef LX_THREAD_SAFE_ENABLE
455
456 /* Release the thread safe mutex. */
457 ✗ tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
458 #endif
459
460 /* Return an error. */
461 ✗ return(LX_ERROR);
462 }
463
464 /* Check if the block has too many erases. */
465
2/4
✗ Branch 56 → 57 not taken.
✓ Branch 56 → 58 taken 18 times.
✗ Branch 65 → 66 not taken.
✓ Branch 65 → 67 taken 2 times.
20 if (nand_flash -> lx_nand_flash_erase_count_table[block] > LX_NAND_FLASH_MAX_ERASE_COUNT_DELTA)
466 {
467
468 /* Move data from less worn block. */
469 ✗ _lx_nand_flash_block_data_move(nand_flash, block);
470 }
471 else
472 {
473
474 /* Set the block status to free. */
475 20 status = _lx_nand_flash_block_status_set(nand_flash, block, LX_NAND_BLOCK_STATUS_FREE);
476
477 /* Check for an error from flash driver. */
478
2/4
✗ Branch 59 → 60 not taken.
✓ Branch 59 → 62 taken 18 times.
✗ Branch 68 → 69 not taken.
✓ Branch 68 → 72 taken 2 times.
20 if (status)
479 {
480
481 /* Call system error handler. */
482 ✗ _lx_nand_flash_system_error(nand_flash, status, block, 0);
483 #ifdef LX_THREAD_SAFE_ENABLE
484
485 /* Release the thread safe mutex. */
486 ✗ tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
487 #endif
488
489 /* Return an error. */
490 ✗ return(LX_ERROR);
491 }
492
493 /* Add the block to free block list. */
494 20 _lx_nand_flash_free_block_list_add(nand_flash, block);
495 }
496
497 /* Check if there is valid pages in the new block. */
498
2/5
✓ Branch 63 → 64 taken 18 times.
✗ Branch 63 → 77 not taken.
✗ Branch 63 → 80 not taken.
✓ Branch 73 → 74 taken 2 times.
✗ Branch 73 → 92 not taken.
20 if ((new_block_status & LX_NAND_BLOCK_STATUS_PAGE_NUMBER_MASK) != 0)
499 {
500
501 /* Add the new block to mapped block list. */
502 20 _lx_nand_flash_mapped_block_list_add(nand_flash, logical_sector / nand_flash -> lx_nand_flash_pages_per_block);
503 }
504 } /* end eager path else block */
505 }
506 else
507 {
508
509 /* Set page buffer to all 0xFF bytes. */
510
4/4
✓ Branch 67 → 66 taken 164736 times.
✓ Branch 67 → 68 taken 312 times.
✓ Branch 77 → 76 taken 27456 times.
✓ Branch 77 → 78 taken 52 times.
192712 LX_MEMSET(nand_flash -> lx_nand_flash_page_buffer, 0xFF, nand_flash -> lx_nand_flash_bytes_per_page + nand_flash -> lx_nand_flash_spare_total_length);
511
512 /* Setup spare buffer pointer. */
513 520 spare_buffer_ptr = nand_flash -> lx_nand_flash_page_buffer + nand_flash -> lx_nand_flash_bytes_per_page;
514
515 /* Check if there is enough spare data for metadata block number. */
516
3/6
✓ Branch 65 → 66 taken 156 times.
✗ Branch 65 → 67 not taken.
✓ Branch 68 → 69 taken 312 times.
✗ Branch 68 → 70 not taken.
✓ Branch 78 → 79 taken 52 times.
✗ Branch 78 → 80 not taken.
520 if (nand_flash -> lx_nand_flash_spare_data2_length >= sizeof(USHORT))
517 {
518
519 /* Save metadata block number in spare bytes. */
520 520 LX_UTILITY_SHORT_SET(&spare_buffer_ptr[nand_flash -> lx_nand_flash_spare_data2_offset], nand_flash -> lx_nand_flash_metadata_block_number);
521 }
522
523 /* Set page type and sector address. */
524 520 LX_UTILITY_LONG_SET(&spare_buffer_ptr[nand_flash -> lx_nand_flash_spare_data1_offset], LX_NAND_PAGE_TYPE_USER_DATA_RELEASED | logical_sector);
525
526 /* Write the page. */
527 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
528 52 status = (nand_flash -> lx_nand_flash_driver_pages_write)(nand_flash, block, available_pages, (UCHAR*)nand_flash -> lx_nand_flash_page_buffer, spare_buffer_ptr, 1);
529 #else
530 468 status = (nand_flash -> lx_nand_flash_driver_pages_write)(block, available_pages, (UCHAR*)nand_flash -> lx_nand_flash_page_buffer, spare_buffer_ptr, 1);
531 #endif
532
533 /* Check for an error from flash driver. */
534
3/6
✗ Branch 68 → 69 not taken.
✓ Branch 68 → 71 taken 156 times.
✗ Branch 71 → 72 not taken.
✓ Branch 71 → 74 taken 312 times.
✗ Branch 81 → 82 not taken.
✓ Branch 81 → 85 taken 52 times.
520 if (status)
535 {
536
537 /* Call system error handler. */
538 ✗ _lx_nand_flash_system_error(nand_flash, status, block, 0);
539 #ifdef LX_THREAD_SAFE_ENABLE
540
541 /* Release the thread safe mutex. */
542 ✗ tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
543 #endif
544
545 /* Return an error. */
546 ✗ return(LX_ERROR);
547 }
548
549 /* Increase available pages count. */
550 520 available_pages++;
551
552 /* Check if available pages count reaches total pages per block. */
553
6/6
✓ Branch 71 → 72 taken 6 times.
✓ Branch 71 → 73 taken 150 times.
✓ Branch 74 → 75 taken 12 times.
✓ Branch 74 → 76 taken 300 times.
✓ Branch 85 → 86 taken 2 times.
✓ Branch 85 → 87 taken 50 times.
520 if (available_pages == nand_flash -> lx_nand_flash_pages_per_block)
554 {
555
556 /* Set block full status flag. */
557 20 block_status |= LX_NAND_BLOCK_STATUS_FULL;
558 }
559
560 /* Build block status word. */
561 520 block_status = (USHORT)(available_pages | (block_status & ~LX_NAND_BLOCK_STATUS_PAGE_NUMBER_MASK));
562
563 /* Set non sequential status flag. */
564 520 block_status |= LX_NAND_BLOCK_STATUS_NON_SEQUENTIAL;
565
566 /* Set block status. */
567 520 status = _lx_nand_flash_block_status_set(nand_flash, block, block_status);
568
569 /* Check for an error from flash driver. */
570
3/6
✗ Branch 74 → 75 not taken.
✓ Branch 74 → 77 taken 156 times.
✗ Branch 77 → 78 not taken.
✓ Branch 77 → 80 taken 312 times.
✗ Branch 88 → 89 not taken.
✓ Branch 88 → 92 taken 52 times.
520 if (status)
571 {
572
573 /* Call system error handler. */
574 ✗ _lx_nand_flash_system_error(nand_flash, status, block, 0);
575 #ifdef LX_THREAD_SAFE_ENABLE
576
577 /* Release the thread safe mutex. */
578 ✗ tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
579 #endif
580
581 /* Return an error. */
582 ✗ return(LX_ERROR);
583 }
584 }
585 }
586 }
587 #ifdef LX_THREAD_SAFE_ENABLE
588
589 /* Release the thread safe mutex. */
590 6738 tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
591 #endif
592
593 /* Return status. */
594 67380 return(status);
595 }
596
597