GCC Code Coverage Report


Directory: common/src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 53.6% 74 / 0 / 138
Functions: 100.0% 1 / 0 / 1
Branches: 56.4% 106 / 0 / 188

lx_nor_flash_block_reclaim.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 /** */
18 /** LevelX Component */
19 /** */
20 /** NOR Flash */
21 /** */
22 /**************************************************************************/
23 /**************************************************************************/
24
25 #define LX_SOURCE_CODE
26
27
28 /* Disable ThreadX error checking. */
29
30 #ifndef LX_DISABLE_ERROR_CHECKING
31 #define LX_DISABLE_ERROR_CHECKING
32 #endif
33
34
35 /* Include necessary system files. */
36
37 #include "lx_api.h"
38
39
40 /**************************************************************************/
41 /* */
42 /* FUNCTION RELEASE */
43 /* */
44 /* _lx_nor_flash_block_reclaim PORTABLE C */
45 /* 6.3.0 */
46 /* AUTHOR */
47 /* */
48 /* William E. Lamie, Microsoft Corporation */
49 /* */
50 /* DESCRIPTION */
51 /* */
52 /* This function reclaims one block from the NOR flash. */
53 /* */
54 /* INPUT */
55 /* */
56 /* nor_flash NOR flash instance */
57 /* */
58 /* OUTPUT */
59 /* */
60 /* return status */
61 /* */
62 /* CALLS */
63 /* */
64 /* _lx_nor_flash_driver_block_erase Driver erase block */
65 /* _lx_nor_flash_driver_write Driver flash sector write */
66 /* _lx_nor_flash_driver_read Driver flash sector read */
67 /* _lx_nor_flash_next_block_to_erase_find */
68 /* Find next block to erase */
69 /* _lx_nor_flash_physical_sector_allocate */
70 /* Allocate new logical sector */
71 /* _lx_nor_flash_sector_mapping_cache_invalidate */
72 /* Invalidate cache entry */
73 /* _lx_nor_flash_system_error Internal system error handler */
74 /* */
75 /* CALLED BY */
76 /* */
77 /* Internal LevelX */
78 /* */
79 /**************************************************************************/
80 11620 UINT _lx_nor_flash_block_reclaim(LX_NOR_FLASH *nor_flash)
81 {
82
83 ULONG *block_word_ptr;
84 ULONG *list_word_ptr;
85 ULONG list_word;
86 ULONG i;
87 ULONG erase_block;
88 ULONG erase_count;
89 ULONG temp_erase_count;
90 ULONG erase_started_value;
91 ULONG mapped_sectors;
92 ULONG obsolete_sectors;
93 ULONG free_sectors;
94 ULONG logical_sector;
95 ULONG *new_mapping_address;
96 ULONG *new_sector_address;
97 ULONG new_mapping_entry;
98 UINT status;
99
100
101 /* Determine the next block to erase. */
102 11620 _lx_nor_flash_next_block_to_erase_find(nor_flash, &erase_block, &erase_count, &mapped_sectors, &obsolete_sectors);
103
104 /* Determine if the search pointer is set for this block. */
105
2/2
✓ Branch 3 → 4 taken 1980 times.
✓ Branch 3 → 6 taken 9640 times.
11620 if (nor_flash -> lx_nor_flash_free_block_search == erase_block)
106 {
107
108 /* Ensure the search block is not the block we are trying to free. */
109 1980 nor_flash -> lx_nor_flash_free_block_search = erase_block + 1;
110
111 /* Check for wrap condition. */
112
2/2
✓ Branch 4 → 5 taken 220 times.
✓ Branch 4 → 6 taken 1760 times.
1980 if (nor_flash -> lx_nor_flash_free_block_search >= nor_flash -> lx_nor_flash_total_blocks)
113 220 nor_flash -> lx_nor_flash_free_block_search = 0;
114 }
115
116 /* Setup the block word pointer to the first word of the search block. */
117 11620 block_word_ptr = nor_flash -> lx_nor_flash_base_address + (nor_flash -> lx_nor_flash_words_per_block * erase_block);
118
119 /* Determine if this block is completely obsolete. */
120
2/3
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 34 taken 9296 times.
✓ Branch 6 → 35 taken 2324 times.
11620 if (obsolete_sectors == nor_flash -> lx_nor_flash_physical_sectors_per_block)
121 {
122
123 /* Write the erased started indication. */
124 ✗ erase_started_value = LX_BLOCK_ERASE_STARTED;
125 ✗ status = _lx_nor_flash_driver_write(nor_flash, block_word_ptr, &erase_started_value, 1);
126
127 /* Check for an error from flash driver. Drivers should never return an error.. */
128 ✗ if (status)
129 {
130
131 /* Call system error handler. */
132 ✗ _lx_nor_flash_system_error(nor_flash, status);
133
134 /* Return the error. */
135 ✗ return(status);
136 }
137
138 /* Erase the entire block. */
139 ✗ status = _lx_nor_flash_driver_block_erase(nor_flash, erase_block, erase_count+1);
140
141 /* Check for an error from flash driver. Drivers should never return an error.. */
142 ✗ if (status)
143 {
144
145 /* Call system error handler. */
146 ✗ _lx_nor_flash_system_error(nor_flash, status);
147
148 /* Return the error. */
149 ✗ return(status);
150 }
151
152 /* Determine if the erase count is at the minimum. */
153 ✗ if (erase_count == nor_flash -> lx_nor_flash_minimum_erase_count)
154 {
155
156 /* Yes, decrement the minimum erased block count. */
157 ✗ nor_flash -> lx_nor_flash_minimum_erased_blocks--;
158 }
159
160 /* Increment the erase count. */
161 ✗ erase_count++;
162
163 /* Determine if the new erase count exceeds the maximum. */
164 ✗ if (erase_count > ((ULONG) LX_BLOCK_ERASE_COUNT_MAX))
165 {
166
167 /* Yes, erase count is in overflow. Stay at the maximum count. */
168 ✗ erase_count = ((ULONG) LX_BLOCK_ERASE_COUNT_MAX);
169 }
170
171 /* Determine if we need to update the maximum erase count. */
172 ✗ if (erase_count > nor_flash -> lx_nor_flash_maximum_erase_count)
173 {
174
175 /* Yes, a new maximum is present. */
176 ✗ nor_flash -> lx_nor_flash_maximum_erase_count = erase_count;
177 }
178
179 /* Setup the free bit map that corresponds to the free physical sectors in this
180 block. Note that we only need to setup the portion of the free bit map that doesn't
181 have sectors associated with it. */
182 ✗ status = _lx_nor_flash_driver_write(nor_flash, block_word_ptr+(nor_flash -> lx_nor_flash_block_free_bit_map_offset + (nor_flash -> lx_nor_flash_block_bit_map_words - 1)),
183 &(nor_flash -> lx_nor_flash_block_bit_map_mask), 1);
184
185 /* Check for an error from flash driver. Drivers should never return an error.. */
186 ✗ if (status)
187 {
188
189 /* Call system error handler. */
190 ✗ _lx_nor_flash_system_error(nor_flash, status);
191
192 /* Return the error. */
193 ✗ return(status);
194 }
195
196 /* Write the initial erase count for the block with upper bit set. */
197 ✗ temp_erase_count = (erase_count | LX_BLOCK_ERASED);
198 ✗ status = _lx_nor_flash_driver_write(nor_flash, block_word_ptr, &temp_erase_count, 1);
199
200 /* Check for an error from flash driver. Drivers should never return an error.. */
201 ✗ if (status)
202 {
203
204 /* Call system error handler. */
205 ✗ _lx_nor_flash_system_error(nor_flash, status);
206
207 /* Return the error. */
208 ✗ return(status);
209 }
210
211 /* Write the final initial erase count for the block. */
212 ✗ status = _lx_nor_flash_driver_write(nor_flash, block_word_ptr, &erase_count, 1);
213
214 /* Check for an error from flash driver. Drivers should never return an error.. */
215 ✗ if (status)
216 {
217
218 /* Call system error handler. */
219 ✗ _lx_nor_flash_system_error(nor_flash, status);
220
221 /* Return the error. */
222 ✗ return(status);
223 }
224
225 /* Update parameters of this flash. */
226 ✗ nor_flash -> lx_nor_flash_free_physical_sectors = nor_flash -> lx_nor_flash_free_physical_sectors + obsolete_sectors;
227 ✗ nor_flash -> lx_nor_flash_obsolete_physical_sectors = nor_flash -> lx_nor_flash_obsolete_physical_sectors - obsolete_sectors;
228 #ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE
229
230 /* Check if the block is cached by obsolete count cache. */
231 ✗ if (erase_block < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block)
232 {
233
234 /* Yes, clear the obsolete count for this block. */
235 ✗ nor_flash -> lx_nor_flash_extended_cache_obsolete_count[erase_block] = 0;
236 }
237 #endif
238 }
239 else
240 {
241
242 /* Calculate the number of free sectors in this block. */
243 11620 free_sectors = nor_flash -> lx_nor_flash_physical_sectors_per_block - (obsolete_sectors + mapped_sectors);
244
245 /* Determine if there are enough free sectors outside of this block to reclaim this block. */
246
2/5
✓ Branch 34 → 35 taken 9296 times.
✗ Branch 34 → 105 not taken.
✗ Branch 34 → 113 not taken.
✓ Branch 35 → 36 taken 2324 times.
✗ Branch 35 → 115 not taken.
11620 if (mapped_sectors <= (nor_flash -> lx_nor_flash_free_physical_sectors - free_sectors))
247 {
248
249 /* Setup a pointer to the mapped list. */
250 11620 list_word_ptr = block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset;
251
252 /* Now search through the list to find mapped sectors to move. */
253
3/6
✓ Branch 77 → 36 taken 34216 times.
✗ Branch 77 → 78 not taken.
✓ Branch 85 → 36 taken 102648 times.
✗ Branch 85 → 86 not taken.
✓ Branch 86 → 37 taken 34216 times.
✗ Branch 86 → 87 not taken.
171080 for (i = 0; i < nor_flash -> lx_nor_flash_physical_sectors_per_block; i++)
254 {
255
256 /* Pickup the mapped sector list entry. */
257 #ifdef LX_DIRECT_READ
258
259 /* Read the word directly. */
260 34216 list_word = *(list_word_ptr);
261 #else
262 136864 status = _lx_nor_flash_driver_read(nor_flash, list_word_ptr, &list_word, 1);
263
264 /* Check for an error from flash driver. Drivers should never return an error.. */
265
2/4
✗ Branch 37 → 38 not taken.
✓ Branch 37 → 40 taken 102648 times.
✗ Branch 38 → 39 not taken.
✓ Branch 38 → 41 taken 34216 times.
136864 if (status)
266 {
267
268 /* Call system error handler. */
269 ✗ _lx_nor_flash_system_error(nor_flash, status);
270
271 /* Return the error. */
272 ✗ return(status);
273 }
274 #endif
275
276 /* Determine if the entry hasn't been used. */
277
3/6
✗ Branch 36 → 37 not taken.
✓ Branch 36 → 38 taken 34216 times.
✗ Branch 40 → 41 not taken.
✓ Branch 40 → 42 taken 102648 times.
✗ Branch 41 → 42 not taken.
✓ Branch 41 → 43 taken 34216 times.
171080 if (list_word == LX_NOR_PHYSICAL_SECTOR_FREE)
278 {
279
280 /* Since allocations are done sequentially in the block, we know nothing
281 else exists after this point. */
282 ✗ break;
283 }
284
285 /* Is this entry mapped? */
286
6/6
✓ Branch 38 → 39 taken 30240 times.
✓ Branch 38 → 76 taken 3976 times.
✓ Branch 42 → 43 taken 90720 times.
✓ Branch 42 → 84 taken 11928 times.
✓ Branch 43 → 44 taken 30240 times.
✓ Branch 43 → 85 taken 3976 times.
171080 if (list_word & LX_NOR_PHYSICAL_SECTOR_VALID)
287 {
288
289 /* Pickup the logical sector associated with this mapped physical sector. */
290 151200 logical_sector = list_word & LX_NOR_LOGICAL_SECTOR_MASK;
291
292 /* Invalidate the old sector mapping cache entry. */
293 151200 _lx_nor_flash_sector_mapping_cache_invalidate(nor_flash, logical_sector);
294
295 /* Allocate a new physical sector for this write. */
296 151200 _lx_nor_flash_physical_sector_allocate(nor_flash, logical_sector, &new_mapping_address, &new_sector_address);
297
298 /* Check to see if the new sector is also in the erase block. */
299
11/11
✓ Branch 41 → 42 taken 30238 times.
✓ Branch 41 → 51 taken 2 times.
✓ Branch 42 → 43 taken 14422 times.
✓ Branch 42 → 51 taken 15816 times.
✓ Branch 45 → 46 taken 90714 times.
✓ Branch 45 → 55 taken 6 times.
✓ Branch 46 → 47 taken 73504 times.
✓ Branch 46 → 55 taken 47448 times.
✓ Branch 46 → 56 taken 2 times.
✓ Branch 47 → 48 taken 14422 times.
✓ Branch 47 → 56 taken 15816 times.
151200 if ((new_mapping_address != LX_NULL) && (new_sector_address >= block_word_ptr) &&
300
6/6
✓ Branch 43 → 44 taken 2 times.
✓ Branch 43 → 51 taken 14420 times.
✓ Branch 47 → 48 taken 6 times.
✓ Branch 47 → 55 taken 43260 times.
✓ Branch 48 → 49 taken 2 times.
✓ Branch 48 → 56 taken 14420 times.
72110 (new_sector_address < (block_word_ptr + nor_flash -> lx_nor_flash_words_per_block)))
301 {
302
303 /* Yes, the new sector was found in the block to be erased. Simply move the search pointer
304 to the block after the erase block and search for another sector from there. */
305 10 nor_flash -> lx_nor_flash_free_block_search = erase_block + 1;
306
307 /* Check for wrap condition. */
308
3/6
✗ Branch 44 → 45 not taken.
✓ Branch 44 → 46 taken 2 times.
✗ Branch 48 → 49 not taken.
✓ Branch 48 → 50 taken 6 times.
✗ Branch 49 → 50 not taken.
✓ Branch 49 → 51 taken 2 times.
10 if (nor_flash -> lx_nor_flash_free_block_search >= nor_flash -> lx_nor_flash_total_blocks)
309 ✗ nor_flash -> lx_nor_flash_free_block_search = 0;
310
311 /* Allocate a new physical sector for this write. */
312 10 _lx_nor_flash_physical_sector_allocate(nor_flash, logical_sector, &new_mapping_address, &new_sector_address);
313
314 /* Check again for the new sector inside of the block to erase. This should be impossible, since
315 we check previously if there are enough free sectors outside of this block needed to reclaim
316 this block. */
317
3/11
✗ Branch 47 → 48 not taken.
✓ Branch 47 → 51 taken 2 times.
✗ Branch 48 → 49 not taken.
✗ Branch 48 → 51 not taken.
✗ Branch 51 → 52 not taken.
✓ Branch 51 → 55 taken 6 times.
✗ Branch 52 → 53 not taken.
✗ Branch 52 → 55 not taken.
✓ Branch 52 → 56 taken 2 times.
✗ Branch 53 → 54 not taken.
✗ Branch 53 → 56 not taken.
10 if ((new_mapping_address != LX_NULL) && (new_sector_address >= block_word_ptr) &&
318 ✗ (new_sector_address < (block_word_ptr + LX_NOR_SECTOR_SIZE)))
319 {
320
321 /* System error, a new sector is not available outside of the erase block.
322 Clear the new sector so we fall through to the error handling. */
323 ✗ new_mapping_address = LX_NULL;
324 }
325 }
326
327 /* Determine if the new sector allocation was successful. */
328
6/6
✓ Branch 51 → 52 taken 30236 times.
✓ Branch 51 → 72 taken 4 times.
✓ Branch 55 → 56 taken 90708 times.
✓ Branch 55 → 80 taken 12 times.
✓ Branch 56 → 57 taken 30236 times.
✓ Branch 56 → 81 taken 4 times.
151200 if (new_mapping_address)
329 {
330
331 /* Yes, we were able to allocate a new physical sector. */
332
333 #ifdef LX_DIRECT_READ
334 /* First, write the sector data to the new physical sector. */
335 30236 status = _lx_nor_flash_driver_write(nor_flash, new_sector_address, (block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_offset) +
336 (i * LX_NOR_SECTOR_SIZE), LX_NOR_SECTOR_SIZE);
337
338 /* Check for an error from flash driver. Drivers should never return an error.. */
339
1/2
✗ Branch 53 → 54 not taken.
✓ Branch 53 → 56 taken 30236 times.
30236 if (status)
340 {
341
342 /* Call system error handler. */
343 ✗ _lx_nor_flash_system_error(nor_flash, status);
344
345 /* Return the error. */
346 ✗ return(status);
347 }
348 #else
349
350 /* First, read the sector data into the internal memory of the NOR flash instance. This internal memory
351 is supplied by the underlying driver during initialization. */
352 120944 status = _lx_nor_flash_driver_read(nor_flash, (block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_offset) +
353 (i * LX_NOR_SECTOR_SIZE), nor_flash -> lx_nor_flash_sector_buffer,
354 LX_NOR_SECTOR_SIZE);
355
356 /* Check for an error from flash driver. Drivers should never return an error.. */
357
2/4
✗ Branch 57 → 58 not taken.
✓ Branch 57 → 60 taken 90708 times.
✗ Branch 58 → 59 not taken.
✓ Branch 58 → 61 taken 30236 times.
120944 if (status)
358 {
359
360 /* Call system error handler. */
361 ✗ _lx_nor_flash_system_error(nor_flash, status);
362
363 /* Return the error. */
364 ✗ return(status);
365 }
366
367 /* Next, write the sector data from the internal buffer to the new physical sector. */
368 120944 status = _lx_nor_flash_driver_write(nor_flash, new_sector_address, nor_flash -> lx_nor_flash_sector_buffer, LX_NOR_SECTOR_SIZE);
369
370 /* Check for an error from flash driver. Drivers should never return an error.. */
371
2/4
✗ Branch 61 → 62 not taken.
✓ Branch 61 → 64 taken 90708 times.
✗ Branch 62 → 63 not taken.
✓ Branch 62 → 65 taken 30236 times.
120944 if (status)
372 {
373
374 /* Call system error handler. */
375 ✗ _lx_nor_flash_system_error(nor_flash, status);
376
377 /* Return the error. */
378 ✗ return(status);
379 }
380 #endif
381
382 /* Now deprecate the old sector mapping. */
383
384 /* Clear bit 30, which indicates this sector is superceded. */
385 151180 list_word = list_word & ~((ULONG) LX_NOR_PHYSICAL_SECTOR_SUPERCEDED);
386
387 /* Write the value back to the flash to clear bit 30. */
388 151180 status = _lx_nor_flash_driver_write(nor_flash, list_word_ptr, &list_word, 1);
389
390 /* Check for an error from flash driver. Drivers should never return an error.. */
391
3/6
✗ Branch 57 → 58 not taken.
✓ Branch 57 → 60 taken 30236 times.
✗ Branch 65 → 66 not taken.
✓ Branch 65 → 68 taken 90708 times.
✗ Branch 66 → 67 not taken.
✓ Branch 66 → 69 taken 30236 times.
151180 if (status)
392 {
393
394 /* Call system error handler. */
395 ✗ _lx_nor_flash_system_error(nor_flash, status);
396
397 /* Return the error. */
398 ✗ return(status);
399 }
400
401 /* Now build the new mapping entry - with the not valid bit set initially. */
402 151180 new_mapping_entry = ((ULONG) LX_NOR_PHYSICAL_SECTOR_VALID) | ((ULONG) LX_NOR_PHYSICAL_SECTOR_SUPERCEDED) | (ULONG) LX_NOR_PHYSICAL_SECTOR_MAPPING_NOT_VALID | logical_sector;
403
404 /* Write out the new mapping entry. */
405 151180 status = _lx_nor_flash_driver_write(nor_flash, new_mapping_address, &new_mapping_entry, 1);
406
407 /* Check for an error from flash driver. Drivers should never return an error.. */
408
3/6
✗ Branch 61 → 62 not taken.
✓ Branch 61 → 64 taken 30236 times.
✗ Branch 69 → 70 not taken.
✓ Branch 69 → 72 taken 90708 times.
✗ Branch 70 → 71 not taken.
✓ Branch 70 → 73 taken 30236 times.
151180 if (status)
409 {
410
411 /* Call system error handler. */
412 ✗ _lx_nor_flash_system_error(nor_flash, status);
413
414 /* Return the error. */
415 ✗ return(status);
416 }
417
418 /* Now clear the not valid bit to make this sector mapping valid. This is done because the writing of the extra bytes itself can
419 be interrupted and we need to make sure this can be detected when the flash is opened again. */
420 151180 new_mapping_entry = new_mapping_entry & ~((ULONG) LX_NOR_PHYSICAL_SECTOR_MAPPING_NOT_VALID);
421
422 /* Clear the not valid bit. */
423 151180 status = _lx_nor_flash_driver_write(nor_flash, new_mapping_address, &new_mapping_entry, 1);
424
425 /* Check for an error from flash driver. Drivers should never return an error.. */
426
3/6
✗ Branch 65 → 66 not taken.
✓ Branch 65 → 68 taken 30236 times.
✗ Branch 73 → 74 not taken.
✓ Branch 73 → 76 taken 90708 times.
✗ Branch 74 → 75 not taken.
✓ Branch 74 → 77 taken 30236 times.
151180 if (status)
427 {
428
429 /* Call system error handler. */
430 ✗ _lx_nor_flash_system_error(nor_flash, status);
431
432 /* Return the error. */
433 ✗ return(status);
434 }
435
436 /* Now clear bit 31, which indicates this sector is now obsoleted. */
437 151180 list_word = list_word & ~((ULONG) LX_NOR_PHYSICAL_SECTOR_VALID);
438
439 /* Write the value back to the flash to clear bit 31. */
440 151180 status = _lx_nor_flash_driver_write(nor_flash, list_word_ptr, &list_word, 1);
441
442 /* Check for an error from flash driver. Drivers should never return an error.. */
443
3/6
✗ Branch 69 → 70 not taken.
✓ Branch 69 → 74 taken 30236 times.
✗ Branch 77 → 78 not taken.
✓ Branch 77 → 82 taken 90708 times.
✗ Branch 78 → 79 not taken.
✓ Branch 78 → 83 taken 30236 times.
151180 if (status)
444 {
445
446 /* Call system error handler. */
447 ✗ _lx_nor_flash_system_error(nor_flash, status);
448
449 /* Return the error. */
450 ✗ return(status);
451 }
452 }
453 else
454 {
455
456 /* Call system error handler - the allocation should always succeed at this point. */
457 20 _lx_nor_flash_system_error(nor_flash, LX_SYSTEM_ALLOCATION_FAILED);
458
459 /* Return the error. */
460 20 return(LX_SYSTEM_ALLOCATION_FAILED);
461 }
462
463 /* Decrement the number of mapped sectors. */
464 151180 mapped_sectors--;
465
466 /* Determine if we are done. */
467
6/6
✓ Branch 74 → 75 taken 2320 times.
✓ Branch 74 → 76 taken 27916 times.
✓ Branch 82 → 83 taken 6960 times.
✓ Branch 82 → 84 taken 83748 times.
✓ Branch 83 → 84 taken 2320 times.
✓ Branch 83 → 85 taken 27916 times.
151180 if (mapped_sectors == 0)
468 11600 break;
469 }
470
471 /* Move the list pointer ahead. */
472 159460 list_word_ptr++;
473 }
474
475 /* Write the erased started indication. */
476 11600 erase_started_value = LX_BLOCK_ERASE_STARTED;
477 11600 status = _lx_nor_flash_driver_write(nor_flash, block_word_ptr, &erase_started_value, 1);
478
479 /* Check for an error from flash driver. Drivers should never return an error.. */
480
3/6
✗ Branch 79 → 80 not taken.
✓ Branch 79 → 82 taken 2320 times.
✗ Branch 87 → 88 not taken.
✓ Branch 87 → 90 taken 6960 times.
✗ Branch 88 → 89 not taken.
✓ Branch 88 → 91 taken 2320 times.
11600 if (status)
481 {
482
483 /* Call system error handler. */
484 ✗ _lx_nor_flash_system_error(nor_flash, status);
485
486 /* Return the error. */
487 ✗ return(status);
488 }
489
490 /* Erase the entire block. */
491 11600 status = _lx_nor_flash_driver_block_erase(nor_flash, erase_block, erase_count+1);
492
493 /* Check for an error from flash driver. Drivers should never return an error.. */
494
3/6
✗ Branch 83 → 84 not taken.
✓ Branch 83 → 86 taken 2320 times.
✗ Branch 91 → 92 not taken.
✓ Branch 91 → 94 taken 6960 times.
✗ Branch 92 → 93 not taken.
✓ Branch 92 → 95 taken 2320 times.
11600 if (status)
495 {
496
497 /* Call system error handler. */
498 ✗ _lx_nor_flash_system_error(nor_flash, status);
499
500 /* Return the error. */
501 ✗ return(status);
502 }
503
504 /* Determine if the erase count is at the minimum. */
505
6/6
✓ Branch 86 → 87 taken 1164 times.
✓ Branch 86 → 88 taken 1156 times.
✓ Branch 94 → 95 taken 3492 times.
✓ Branch 94 → 96 taken 3468 times.
✓ Branch 95 → 96 taken 1164 times.
✓ Branch 95 → 97 taken 1156 times.
11600 if (erase_count == nor_flash -> lx_nor_flash_minimum_erase_count)
506 {
507
508 /* Yes, decrement the minimum erased block count. */
509 5820 nor_flash -> lx_nor_flash_minimum_erased_blocks--;
510 }
511
512 /* Increment the erase count. */
513 11600 erase_count++;
514
515 /* Determine if the new erase count exceeds the maximum. */
516
3/6
✗ Branch 88 → 89 not taken.
✓ Branch 88 → 90 taken 2320 times.
✗ Branch 96 → 97 not taken.
✓ Branch 96 → 98 taken 6960 times.
✗ Branch 97 → 98 not taken.
✓ Branch 97 → 99 taken 2320 times.
11600 if (erase_count > ((ULONG) LX_BLOCK_ERASE_COUNT_MAX))
517 {
518
519 /* Yes, erase count is in overflow. Stay at the maximum count. */
520 ✗ erase_count = ((ULONG) LX_BLOCK_ERASE_COUNT_MAX);
521 }
522
523 /* Determine if we need to update the maximum erase count. */
524
6/6
✓ Branch 90 → 91 taken 300 times.
✓ Branch 90 → 92 taken 2020 times.
✓ Branch 98 → 99 taken 900 times.
✓ Branch 98 → 100 taken 6060 times.
✓ Branch 99 → 100 taken 300 times.
✓ Branch 99 → 101 taken 2020 times.
11600 if (erase_count > nor_flash -> lx_nor_flash_maximum_erase_count)
525 {
526
527 /* Yes, a new maximum is present. */
528 1500 nor_flash -> lx_nor_flash_maximum_erase_count = erase_count;
529 }
530
531 /* Setup the free bit map that corresponds to the free physical sectors in this
532 block. Note that we only need to setup the portion of the free bit map that doesn't
533 have sectors associated with it. */
534 11600 status = _lx_nor_flash_driver_write(nor_flash, block_word_ptr+(nor_flash -> lx_nor_flash_block_free_bit_map_offset + (nor_flash -> lx_nor_flash_block_bit_map_words - 1)) ,
535 &(nor_flash -> lx_nor_flash_block_bit_map_mask), 1);
536
537 /* Check for an error from flash driver. Drivers should never return an error.. */
538
3/6
✗ Branch 93 → 94 not taken.
✓ Branch 93 → 96 taken 2320 times.
✗ Branch 101 → 102 not taken.
✓ Branch 101 → 104 taken 6960 times.
✗ Branch 102 → 103 not taken.
✓ Branch 102 → 105 taken 2320 times.
11600 if (status)
539 {
540
541 /* Call system error handler. */
542 ✗ _lx_nor_flash_system_error(nor_flash, status);
543
544 /* Return the error. */
545 ✗ return(status);
546 }
547
548 /* Write the initial erase count for the block with the upper bit set. */
549 11600 temp_erase_count = (erase_count | LX_BLOCK_ERASED);
550 11600 status = _lx_nor_flash_driver_write(nor_flash, block_word_ptr, &temp_erase_count, 1);
551
552 /* Check for an error from flash driver. Drivers should never return an error.. */
553
3/6
✗ Branch 97 → 98 not taken.
✓ Branch 97 → 100 taken 2320 times.
✗ Branch 105 → 106 not taken.
✓ Branch 105 → 108 taken 6960 times.
✗ Branch 106 → 107 not taken.
✓ Branch 106 → 109 taken 2320 times.
11600 if (status)
554 {
555
556 /* Call system error handler. */
557 ✗ _lx_nor_flash_system_error(nor_flash, status);
558
559 /* Return the error. */
560 ✗ return(status);
561 }
562
563 /* Write the final initial erase count for the block. */
564 11600 status = _lx_nor_flash_driver_write(nor_flash, block_word_ptr, &erase_count, 1);
565
566 /* Check for an error from flash driver. Drivers should never return an error.. */
567
3/6
✗ Branch 101 → 102 not taken.
✓ Branch 101 → 104 taken 2320 times.
✗ Branch 109 → 110 not taken.
✓ Branch 109 → 112 taken 6960 times.
✗ Branch 110 → 111 not taken.
✓ Branch 110 → 113 taken 2320 times.
11600 if (status)
568 {
569
570 /* Call system error handler. */
571 ✗ _lx_nor_flash_system_error(nor_flash, status);
572
573 /* Return the error. */
574 ✗ return(status);
575 }
576
577 /* Update parameters of this flash. */
578 11600 nor_flash -> lx_nor_flash_free_physical_sectors = nor_flash -> lx_nor_flash_free_physical_sectors + obsolete_sectors;
579 11600 nor_flash -> lx_nor_flash_obsolete_physical_sectors = nor_flash -> lx_nor_flash_obsolete_physical_sectors - obsolete_sectors;
580 #ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE
581
582 /* Check if the block is cached by obsolete count cache. */
583
2/2
✓ Branch 113 → 114 taken 1160 times.
✓ Branch 113 → 115 taken 1160 times.
2320 if (erase_block < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block)
584 {
585
586 /* Yes, clear the obsolete count for this block. */
587 1160 nor_flash -> lx_nor_flash_extended_cache_obsolete_count[erase_block] = 0;
588 }
589 #endif
590 }
591 }
592
593 /* Return status. */
594 11600 return(LX_SUCCESS);
595 }
596
597