lx_nor_flash_next_block_to_erase_find.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 | |||
| 13 | /**************************************************************************/ | ||
| 14 | /**************************************************************************/ | ||
| 15 | /** */ | ||
| 16 | /** LevelX Component */ | ||
| 17 | /** */ | ||
| 18 | /** NOR 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_nor_flash_next_block_to_erase_find PORTABLE C */ | ||
| 43 | /* 6.3.0 */ | ||
| 44 | /* AUTHOR */ | ||
| 45 | /* */ | ||
| 46 | /* William E. Lamie, Microsoft Corporation */ | ||
| 47 | /* */ | ||
| 48 | /* DESCRIPTION */ | ||
| 49 | /* */ | ||
| 50 | /* This function finds the next block to erase in the NOR flash. */ | ||
| 51 | /* */ | ||
| 52 | /* INPUT */ | ||
| 53 | /* */ | ||
| 54 | /* nor_flash NOR flash instance */ | ||
| 55 | /* return_erase_block Returned block to erase */ | ||
| 56 | /* return_erase_count Returned erase count of block */ | ||
| 57 | /* return_mapped_sectors Returned number of mapped */ | ||
| 58 | /* sectors */ | ||
| 59 | /* return_obsolete_sectors Returned number of obsolete */ | ||
| 60 | /* sectors */ | ||
| 61 | /* */ | ||
| 62 | /* OUTPUT */ | ||
| 63 | /* */ | ||
| 64 | /* return status */ | ||
| 65 | /* */ | ||
| 66 | /* CALLS */ | ||
| 67 | /* */ | ||
| 68 | /* _lx_nor_flash_driver_read Driver flash sector read */ | ||
| 69 | /* _lx_nor_flash_system_error Internal system error handler */ | ||
| 70 | /* */ | ||
| 71 | /* CALLED BY */ | ||
| 72 | /* */ | ||
| 73 | /* Internal LevelX */ | ||
| 74 | /* */ | ||
| 75 | /**************************************************************************/ | ||
| 76 | 11602 | UINT _lx_nor_flash_next_block_to_erase_find(LX_NOR_FLASH *nor_flash, ULONG *return_erase_block, ULONG *return_erase_count, ULONG *return_mapped_sectors, ULONG *return_obsolete_sectors) | |
| 77 | { | ||
| 78 | |||
| 79 | ULONG *block_word_ptr; | ||
| 80 | ULONG *list_word_ptr; | ||
| 81 | ULONG list_word; | ||
| 82 | ULONG i, j; | ||
| 83 | ULONG mapped_sectors; | ||
| 84 | ULONG erase_count; | ||
| 85 | ULONG obsolete_sectors; | ||
| 86 | 11602 | ULONG min_block_erase = 0; | |
| 87 | ULONG min_block_erase_count; | ||
| 88 | 11602 | ULONG min_block_obsolete_count = 0; | |
| 89 | 11602 | ULONG min_block_mapped_count = 0; | |
| 90 | 11602 | ULONG min_block_mapped_count_available = LX_FALSE; | |
| 91 | ULONG max_obsolete_sectors; | ||
| 92 | 11602 | ULONG max_obsolete_block = 0; | |
| 93 | 11602 | ULONG max_obsolete_erase_count = 0; | |
| 94 | 11602 | ULONG max_obsolete_mapped_count = 0; | |
| 95 | 11602 | ULONG max_obsolete_mapped_count_available = LX_FALSE; | |
| 96 | ULONG min_system_block_erase_count; | ||
| 97 | ULONG system_min_erased_blocks; | ||
| 98 | ULONG max_system_block_erase_count; | ||
| 99 | ULONG erase_count_threshold; | ||
| 100 | ULONG min_logical_sector; | ||
| 101 | ULONG max_logical_sector; | ||
| 102 | #ifndef LX_DIRECT_READ | ||
| 103 | UINT status; | ||
| 104 | #endif | ||
| 105 | UINT obsolete_sectors_available; | ||
| 106 | 11602 | UINT mapped_sectors_available = LX_FALSE; | |
| 107 | |||
| 108 | |||
| 109 | /* Setup the block word pointer to the first word of the search block. */ | ||
| 110 | 11602 | block_word_ptr = nor_flash -> lx_nor_flash_base_address; | |
| 111 | |||
| 112 | /* Initialize the minimum erase count. */ | ||
| 113 | 11602 | min_block_erase_count = LX_ALL_ONES; | |
| 114 | |||
| 115 | /* Initialize the system minimum and maximum erase counts. */ | ||
| 116 | 11602 | min_system_block_erase_count = LX_ALL_ONES; | |
| 117 | 11602 | system_min_erased_blocks = 0; | |
| 118 | 11602 | max_system_block_erase_count = 0; | |
| 119 | |||
| 120 | /* Initialize the maximum obsolete sector count. */ | ||
| 121 | 11602 | max_obsolete_sectors = 0; | |
| 122 | |||
| 123 | /* Calculate the erase count threshold. */ | ||
| 124 |
1/2✓ Branch 2 → 3 taken 11602 times.
✗ Branch 2 → 4 not taken.
|
11602 | if (nor_flash -> lx_nor_flash_free_physical_sectors >= nor_flash -> lx_nor_flash_physical_sectors_per_block) |
| 125 | { | ||
| 126 | |||
| 127 | /* Calculate erase count threshold by adding constant to the current minimum. */ | ||
| 128 | 11602 | erase_count_threshold = nor_flash -> lx_nor_flash_minimum_erase_count + LX_NOR_FLASH_MAX_ERASE_COUNT_DELTA; | |
| 129 | } | ||
| 130 | else | ||
| 131 | { | ||
| 132 | |||
| 133 | /* When the number of free sectors is low, simply pick the block that has the most number of obsolete sectors. */ | ||
| 134 | ✗ | erase_count_threshold = LX_ALL_ONES; | |
| 135 | } | ||
| 136 | |||
| 137 | /* Loop through the blocks to attempt to find the mapped logical sector. */ | ||
| 138 |
6/6✓ Branch 40 → 6 taken 18560 times.
✓ Branch 40 → 41 taken 2320 times.
✓ Branch 56 → 6 taken 55680 times.
✓ Branch 56 → 57 taken 6960 times.
✓ Branch 58 → 6 taken 18576 times.
✓ Branch 58 → 59 taken 2322 times.
|
104418 | for (i = 0; i < nor_flash -> lx_nor_flash_total_blocks; i++) |
| 139 | { | ||
| 140 | |||
| 141 | /* Read the erase count of this block. */ | ||
| 142 | #ifdef LX_DIRECT_READ | ||
| 143 | |||
| 144 | /* Read the word directly. */ | ||
| 145 | 18560 | erase_count = *(block_word_ptr); | |
| 146 | #else | ||
| 147 | 74256 | status = _lx_nor_flash_driver_read(nor_flash, block_word_ptr, &erase_count, 1); | |
| 148 | |||
| 149 | /* Check for an error from flash driver. Drivers should never return an error.. */ | ||
| 150 |
1/2✗ Branch 7 → 8 not taken.
✓ Branch 7 → 10 taken 74256 times.
|
74256 | if (status) |
| 151 | { | ||
| 152 | |||
| 153 | /* Call system error handler. */ | ||
| 154 | ✗ | _lx_nor_flash_system_error(nor_flash, status); | |
| 155 | |||
| 156 | /* Return the error. */ | ||
| 157 | ✗ | return(status); | |
| 158 | } | ||
| 159 | #endif | ||
| 160 | |||
| 161 | /* Update the system minimum and maximum erase counts. */ | ||
| 162 |
4/4✓ Branch 6 → 7 taken 5268 times.
✓ Branch 6 → 8 taken 13292 times.
✓ Branch 10 → 11 taken 21086 times.
✓ Branch 10 → 12 taken 53170 times.
|
92816 | if (erase_count == min_system_block_erase_count) |
| 163 | { | ||
| 164 | 26354 | system_min_erased_blocks ++; | |
| 165 | } | ||
| 166 |
4/4✓ Branch 8 → 9 taken 5132 times.
✓ Branch 8 → 10 taken 13428 times.
✓ Branch 12 → 13 taken 20530 times.
✓ Branch 12 → 14 taken 53726 times.
|
92816 | if (erase_count < min_system_block_erase_count) |
| 167 | { | ||
| 168 | 25662 | min_system_block_erase_count = erase_count; | |
| 169 | 25662 | system_min_erased_blocks = 1; | |
| 170 | } | ||
| 171 |
4/4✓ Branch 10 → 11 taken 4068 times.
✓ Branch 10 → 12 taken 14492 times.
✓ Branch 14 → 15 taken 16274 times.
✓ Branch 14 → 16 taken 57982 times.
|
92816 | if (erase_count > max_system_block_erase_count) |
| 172 | 20342 | max_system_block_erase_count = erase_count; | |
| 173 | |||
| 174 | /* Initialize the mapped sector count and the obsolete/mapped sector count availability flags. */ | ||
| 175 | 92816 | obsolete_sectors_available = LX_FALSE; | |
| 176 | 92816 | mapped_sectors_available = LX_FALSE; | |
| 177 | 92816 | mapped_sectors = 0; | |
| 178 | |||
| 179 | #ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE | ||
| 180 | |||
| 181 | /* Determine if the obsolete sector count is available in the cache. */ | ||
| 182 |
2/2✓ Branch 16 → 17 taken 9296 times.
✓ Branch 16 → 18 taken 9280 times.
|
18576 | if (i < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block) |
| 183 | { | ||
| 184 | |||
| 185 | /* Yes, the obsolete sector count is available. */ | ||
| 186 | 9296 | obsolete_sectors_available = LX_TRUE; | |
| 187 | |||
| 188 | /* Pickup the obsolete sector count from the cache. */ | ||
| 189 | 9296 | obsolete_sectors = (ULONG)nor_flash -> lx_nor_flash_extended_cache_obsolete_count[i]; | |
| 190 | } | ||
| 191 | else | ||
| 192 | { | ||
| 193 | #endif | ||
| 194 | /* Read the minimum and maximum logical sector values in this block. */ | ||
| 195 | #ifdef LX_DIRECT_READ | ||
| 196 | |||
| 197 | /* Read the word directly. */ | ||
| 198 | 18560 | min_logical_sector = *(block_word_ptr + LX_NOR_FLASH_MIN_LOGICAL_SECTOR_OFFSET); | |
| 199 | #else | ||
| 200 | 64960 | status = _lx_nor_flash_driver_read(nor_flash, block_word_ptr + LX_NOR_FLASH_MIN_LOGICAL_SECTOR_OFFSET, &min_logical_sector, 1); | |
| 201 | |||
| 202 | /* Check for an error from flash driver. Drivers should never return an error.. */ | ||
| 203 |
2/4✗ Branch 17 → 18 not taken.
✓ Branch 17 → 20 taken 55680 times.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 22 taken 9280 times.
|
64960 | if (status) |
| 204 | { | ||
| 205 | |||
| 206 | /* Call system error handler. */ | ||
| 207 | ✗ | _lx_nor_flash_system_error(nor_flash, status); | |
| 208 | |||
| 209 | /* Return the error. */ | ||
| 210 | ✗ | return(status); | |
| 211 | } | ||
| 212 | #endif | ||
| 213 | |||
| 214 | /* Determine if the minimum logical sector is valid. */ | ||
| 215 |
6/6✓ Branch 12 → 13 taken 16052 times.
✓ Branch 12 → 16 taken 2508 times.
✓ Branch 20 → 21 taken 48156 times.
✓ Branch 20 → 28 taken 7524 times.
✓ Branch 22 → 23 taken 8026 times.
✓ Branch 22 → 30 taken 1254 times.
|
83520 | if (min_logical_sector != LX_ALL_ONES) |
| 216 | { | ||
| 217 | #ifdef LX_DIRECT_READ | ||
| 218 | |||
| 219 | /* Read the word directly. */ | ||
| 220 | 16052 | max_logical_sector = *(block_word_ptr + LX_NOR_FLASH_MAX_LOGICAL_SECTOR_OFFSET); | |
| 221 | #else | ||
| 222 | 56182 | status = _lx_nor_flash_driver_read(nor_flash, block_word_ptr + LX_NOR_FLASH_MAX_LOGICAL_SECTOR_OFFSET, &max_logical_sector, 1); | |
| 223 | |||
| 224 | /* Check for an error from flash driver. Drivers should never return an error.. */ | ||
| 225 |
2/4✗ Branch 22 → 23 not taken.
✓ Branch 22 → 25 taken 48156 times.
✗ Branch 24 → 25 not taken.
✓ Branch 24 → 27 taken 8026 times.
|
56182 | if (status) |
| 226 | { | ||
| 227 | |||
| 228 | /* Call system error handler. */ | ||
| 229 | ✗ | _lx_nor_flash_system_error(nor_flash, status); | |
| 230 | |||
| 231 | /* Return the error. */ | ||
| 232 | ✗ | return(status); | |
| 233 | } | ||
| 234 | #endif | ||
| 235 | |||
| 236 | /* Are the values valid? */ | ||
| 237 | /* Now let's check to see if all the sector are obsoleted. */ | ||
| 238 |
6/12✓ Branch 13 → 14 taken 16052 times.
✗ Branch 13 → 16 not taken.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 16052 times.
✓ Branch 25 → 26 taken 48156 times.
✗ Branch 25 → 28 not taken.
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 28 taken 48156 times.
✓ Branch 27 → 28 taken 8026 times.
✗ Branch 27 → 30 not taken.
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 30 taken 8026 times.
|
72234 | if ((max_logical_sector != LX_ALL_ONES) && (max_logical_sector < min_logical_sector)) |
| 239 | { | ||
| 240 | |||
| 241 | ✗ | obsolete_sectors_available = LX_TRUE; | |
| 242 | ✗ | obsolete_sectors = nor_flash -> lx_nor_flash_physical_sectors_per_block; | |
| 243 | } | ||
| 244 | } | ||
| 245 | #ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE | ||
| 246 | } | ||
| 247 | #endif | ||
| 248 | |||
| 249 | /* Determine if the mapped sector count is available. */ | ||
| 250 |
4/6✓ Branch 16 → 17 taken 18560 times.
✗ Branch 16 → 25 not taken.
✓ Branch 28 → 29 taken 55680 times.
✗ Branch 28 → 41 not taken.
✓ Branch 30 → 31 taken 9280 times.
✓ Branch 30 → 43 taken 9296 times.
|
92816 | if (obsolete_sectors_available == LX_FALSE) |
| 251 | { | ||
| 252 | |||
| 253 | /* Compute the number of obsolete and mapped sectors for this block. */ | ||
| 254 | |||
| 255 | /* Initialize the obsolete and mapped sector counts. */ | ||
| 256 | 83520 | obsolete_sectors = 0; | |
| 257 | 83520 | mapped_sectors = 0; | |
| 258 | |||
| 259 | /* Set the mapped sector count and obsolete sector count available flags. */ | ||
| 260 | 83520 | mapped_sectors_available = LX_TRUE; | |
| 261 | 83520 | obsolete_sectors_available = LX_TRUE; | |
| 262 | |||
| 263 | /* Setup a pointer to the mapped list. */ | ||
| 264 | 83520 | list_word_ptr = block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset; | |
| 265 | |||
| 266 | /* Loop through the mapped list for this block. */ | ||
| 267 |
6/6✓ Branch 24 → 18 taken 243664 times.
✓ Branch 24 → 25 taken 16052 times.
✓ Branch 40 → 30 taken 730992 times.
✓ Branch 40 → 41 taken 48156 times.
✓ Branch 42 → 32 taken 121832 times.
✓ Branch 42 → 43 taken 8026 times.
|
1168722 | for (j = 0; j < nor_flash -> lx_nor_flash_physical_sectors_per_block; j++) |
| 268 | { | ||
| 269 | |||
| 270 | /* Read the current mapping entry. */ | ||
| 271 | #ifdef LX_DIRECT_READ | ||
| 272 | |||
| 273 | /* Read the word directly. */ | ||
| 274 | 243664 | list_word = *(list_word_ptr); | |
| 275 | #else | ||
| 276 | 852824 | status = _lx_nor_flash_driver_read(nor_flash, list_word_ptr, &list_word, 1); | |
| 277 | |||
| 278 | /* Check for an error from flash driver. Drivers should never return an error.. */ | ||
| 279 |
2/4✗ Branch 31 → 32 not taken.
✓ Branch 31 → 34 taken 730992 times.
✗ Branch 33 → 34 not taken.
✓ Branch 33 → 36 taken 121832 times.
|
852824 | if (status) |
| 280 | { | ||
| 281 | |||
| 282 | /* Call system error handler. */ | ||
| 283 | ✗ | _lx_nor_flash_system_error(nor_flash, status); | |
| 284 | |||
| 285 | /* Return the error. */ | ||
| 286 | ✗ | return(status); | |
| 287 | } | ||
| 288 | #endif | ||
| 289 | |||
| 290 | /* Determine if the entry hasn't been used. */ | ||
| 291 |
6/6✓ Branch 18 → 19 taken 2508 times.
✓ Branch 18 → 20 taken 241156 times.
✓ Branch 34 → 35 taken 7524 times.
✓ Branch 34 → 36 taken 723468 times.
✓ Branch 36 → 37 taken 1254 times.
✓ Branch 36 → 38 taken 120578 times.
|
1096488 | if (list_word == LX_NOR_PHYSICAL_SECTOR_FREE) |
| 292 | { | ||
| 293 | |||
| 294 | /* Since allocations are done sequentially in the block, we know nothing | ||
| 295 | else exists after this point. */ | ||
| 296 | 11286 | break; | |
| 297 | } | ||
| 298 | |||
| 299 | /* Is this entry obsolete? */ | ||
| 300 |
6/6✓ Branch 20 → 21 taken 13536 times.
✓ Branch 20 → 22 taken 227620 times.
✓ Branch 36 → 37 taken 40608 times.
✓ Branch 36 → 38 taken 682860 times.
✓ Branch 38 → 39 taken 6768 times.
✓ Branch 38 → 40 taken 113810 times.
|
1085202 | if ((list_word & LX_NOR_PHYSICAL_SECTOR_VALID) == 0) |
| 301 | { | ||
| 302 | |||
| 303 | /* Increment the number of obsolete sectors. */ | ||
| 304 | 60912 | obsolete_sectors++; | |
| 305 | } | ||
| 306 | else | ||
| 307 | { | ||
| 308 | |||
| 309 | /* Increment the number of mapped sectors. */ | ||
| 310 | 1024290 | mapped_sectors++; | |
| 311 | } | ||
| 312 | |||
| 313 | /* Move the list pointer ahead. */ | ||
| 314 | 1085202 | list_word_ptr++; | |
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | /* Determine if this block contains full obsoleted sectors and the erase count is minimum. */ | ||
| 319 |
3/6✗ Branch 25 → 26 not taken.
✓ Branch 25 → 29 taken 18560 times.
✗ Branch 41 → 42 not taken.
✓ Branch 41 → 45 taken 55680 times.
✗ Branch 43 → 44 not taken.
✓ Branch 43 → 47 taken 18576 times.
|
92816 | if ((obsolete_sectors == nor_flash -> lx_nor_flash_physical_sectors_per_block) && |
| 320 | ✗ | (erase_count == nor_flash -> lx_nor_flash_minimum_erase_count) && | |
| 321 | ✗ | (nor_flash -> lx_nor_flash_minimum_erased_blocks > 0)) | |
| 322 | { | ||
| 323 | |||
| 324 | /* Yes, we have a full obsoleted block with minimum erase count. */ | ||
| 325 | ✗ | *return_erase_block = i; | |
| 326 | ✗ | *return_erase_count = erase_count; | |
| 327 | ✗ | *return_obsolete_sectors = obsolete_sectors; | |
| 328 | ✗ | *return_mapped_sectors = mapped_sectors; | |
| 329 | |||
| 330 | ✗ | break; | |
| 331 | } | ||
| 332 | |||
| 333 | |||
| 334 | /* Determine if we have a block with a new maximum number of obsolete sectors. */ | ||
| 335 |
12/12✓ Branch 29 → 30 taken 3480 times.
✓ Branch 29 → 32 taken 15080 times.
✓ Branch 30 → 31 taken 3452 times.
✓ Branch 30 → 32 taken 28 times.
✓ Branch 45 → 46 taken 10440 times.
✓ Branch 45 → 48 taken 45240 times.
✓ Branch 46 → 47 taken 10356 times.
✓ Branch 46 → 48 taken 84 times.
✓ Branch 47 → 48 taken 3482 times.
✓ Branch 47 → 50 taken 15094 times.
✓ Branch 48 → 49 taken 3454 times.
✓ Branch 48 → 50 taken 28 times.
|
92816 | if ((obsolete_sectors > max_obsolete_sectors) && (erase_count <= erase_count_threshold)) |
| 336 | { | ||
| 337 | |||
| 338 | /* Update the new maximum obsolete sectors and related information. */ | ||
| 339 | 17262 | max_obsolete_sectors = obsolete_sectors; | |
| 340 | 17262 | max_obsolete_block = i; | |
| 341 | 17262 | max_obsolete_erase_count = erase_count; | |
| 342 | 17262 | max_obsolete_mapped_count = mapped_sectors; | |
| 343 | 17262 | max_obsolete_mapped_count_available = mapped_sectors_available; | |
| 344 | |||
| 345 | } | ||
| 346 |
17/17✓ Branch 32 → 33 taken 13156 times.
✓ Branch 32 → 37 taken 1952 times.
✓ Branch 33 → 34 taken 4076 times.
✓ Branch 33 → 37 taken 9080 times.
✓ Branch 34 → 35 taken 4048 times.
✓ Branch 34 → 37 taken 28 times.
✓ Branch 48 → 49 taken 39468 times.
✓ Branch 48 → 53 taken 5856 times.
✓ Branch 49 → 50 taken 12228 times.
✓ Branch 49 → 53 taken 27240 times.
✓ Branch 50 → 51 taken 25314 times.
✓ Branch 50 → 53 taken 84 times.
✓ Branch 50 → 55 taken 1952 times.
✓ Branch 51 → 52 taken 4076 times.
✓ Branch 51 → 55 taken 9094 times.
✓ Branch 52 → 53 taken 4048 times.
✓ Branch 52 → 55 taken 28 times.
|
75554 | else if ((max_obsolete_sectors) && (obsolete_sectors == max_obsolete_sectors) && (erase_count <= erase_count_threshold)) |
| 347 | { | ||
| 348 | |||
| 349 | /* Another block has the same number of obsolete sectors. Does this new block have a smaller erase | ||
| 350 | count? */ | ||
| 351 |
6/6✓ Branch 35 → 36 taken 1012 times.
✓ Branch 35 → 37 taken 3036 times.
✓ Branch 51 → 52 taken 3036 times.
✓ Branch 51 → 53 taken 9108 times.
✓ Branch 53 → 54 taken 1012 times.
✓ Branch 53 → 55 taken 3036 times.
|
20240 | if (erase_count < max_obsolete_erase_count) |
| 352 | { | ||
| 353 | |||
| 354 | /* Yes, erase the block with the smaller erase count. */ | ||
| 355 | 5060 | max_obsolete_sectors = obsolete_sectors; | |
| 356 | 5060 | max_obsolete_block = i; | |
| 357 | 5060 | max_obsolete_erase_count = erase_count; | |
| 358 | 5060 | max_obsolete_mapped_count = mapped_sectors; | |
| 359 | 5060 | max_obsolete_mapped_count_available = mapped_sectors_available; | |
| 360 | } | ||
| 361 | } | ||
| 362 | |||
| 363 | /* Determine if we have a new minimum erase count. */ | ||
| 364 |
6/6✓ Branch 37 → 38 taken 5132 times.
✓ Branch 37 → 39 taken 13428 times.
✓ Branch 53 → 54 taken 15396 times.
✓ Branch 53 → 55 taken 40284 times.
✓ Branch 55 → 56 taken 5134 times.
✓ Branch 55 → 57 taken 13442 times.
|
92816 | if (erase_count < min_block_erase_count) |
| 365 | { | ||
| 366 | |||
| 367 | /* Update the new minimum erase count and related information. */ | ||
| 368 | 25662 | min_block_erase_count = erase_count; | |
| 369 | 25662 | min_block_erase = i; | |
| 370 | 25662 | min_block_obsolete_count = obsolete_sectors; | |
| 371 | 25662 | min_block_mapped_count = mapped_sectors; | |
| 372 | 25662 | min_block_mapped_count_available = mapped_sectors_available; | |
| 373 | } | ||
| 374 | |||
| 375 | /* Move to the next block. */ | ||
| 376 | 92816 | block_word_ptr = block_word_ptr + nor_flash -> lx_nor_flash_words_per_block; | |
| 377 | } | ||
| 378 | |||
| 379 | /* Determine if we found a block with full obsoleted sector and the erase count is minimum. */ | ||
| 380 |
3/6✓ Branch 41 → 42 taken 2320 times.
✗ Branch 41 → 46 not taken.
✓ Branch 57 → 58 taken 6960 times.
✗ Branch 57 → 62 not taken.
✓ Branch 59 → 60 taken 2322 times.
✗ Branch 59 → 64 not taken.
|
11602 | if (i == nor_flash -> lx_nor_flash_total_blocks) |
| 381 | { | ||
| 382 | |||
| 383 | /* Determine if we can erase the block with the most obsolete sectors. */ | ||
| 384 |
3/6✓ Branch 42 → 43 taken 2320 times.
✗ Branch 42 → 44 not taken.
✓ Branch 58 → 59 taken 6960 times.
✗ Branch 58 → 60 not taken.
✓ Branch 60 → 61 taken 2322 times.
✗ Branch 60 → 62 not taken.
|
11602 | if (max_obsolete_sectors) |
| 385 | { | ||
| 386 | |||
| 387 | /* Erase the block with the most obsolete sectors. */ | ||
| 388 | 11602 | *return_erase_block = max_obsolete_block; | |
| 389 | 11602 | *return_erase_count = max_obsolete_erase_count; | |
| 390 | 11602 | *return_obsolete_sectors = max_obsolete_sectors; | |
| 391 | 11602 | *return_mapped_sectors = max_obsolete_mapped_count; | |
| 392 | 11602 | mapped_sectors_available = max_obsolete_mapped_count_available; | |
| 393 | } | ||
| 394 | else | ||
| 395 | { | ||
| 396 | |||
| 397 | /* Otherwise, choose the block with the smallest erase count. */ | ||
| 398 | ✗ | *return_erase_block = min_block_erase; | |
| 399 | ✗ | *return_erase_count = min_block_erase_count; | |
| 400 | ✗ | *return_obsolete_sectors = min_block_obsolete_count; | |
| 401 | ✗ | *return_mapped_sectors = min_block_mapped_count; | |
| 402 | ✗ | mapped_sectors_available = min_block_mapped_count_available; | |
| 403 | } | ||
| 404 | |||
| 405 | /* Update the overall minimum and maximum erase count. */ | ||
| 406 | 11602 | nor_flash -> lx_nor_flash_minimum_erase_count = min_system_block_erase_count; | |
| 407 | 11602 | nor_flash -> lx_nor_flash_minimum_erased_blocks = system_min_erased_blocks; | |
| 408 | 11602 | nor_flash -> lx_nor_flash_maximum_erase_count = max_system_block_erase_count; | |
| 409 | } | ||
| 410 | |||
| 411 | /* Determine if the mapped sector count is available. */ | ||
| 412 |
4/6✗ Branch 46 → 47 not taken.
✓ Branch 46 → 55 taken 2320 times.
✗ Branch 62 → 63 not taken.
✓ Branch 62 → 75 taken 6960 times.
✓ Branch 64 → 65 taken 1162 times.
✓ Branch 64 → 77 taken 1160 times.
|
11602 | if (mapped_sectors_available == LX_FALSE) |
| 413 | { | ||
| 414 | |||
| 415 | /* Compute the number of obsolete and mapped sectors for this block. */ | ||
| 416 | 1162 | mapped_sectors = 0; | |
| 417 | |||
| 418 | /* Setup a pointer to the mapped list. */ | ||
| 419 | 1162 | block_word_ptr = nor_flash -> lx_nor_flash_base_address + *return_erase_block * nor_flash -> lx_nor_flash_words_per_block; | |
| 420 | 1162 | list_word_ptr = block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset; | |
| 421 | |||
| 422 | /* Loop through the mapped list for this block. */ | ||
| 423 |
2/6✗ Branch 53 → 48 not taken.
✗ Branch 53 → 54 not taken.
✗ Branch 73 → 64 not taken.
✗ Branch 73 → 74 not taken.
✓ Branch 75 → 66 taken 17392 times.
✓ Branch 75 → 76 taken 1156 times.
|
18548 | for (j = 0; j < nor_flash -> lx_nor_flash_physical_sectors_per_block; j++) |
| 424 | { | ||
| 425 | |||
| 426 | /* Read the current mapping entry. */ | ||
| 427 | #ifdef LX_DIRECT_READ | ||
| 428 | |||
| 429 | /* Read the word directly. */ | ||
| 430 | ✗ | list_word = *(list_word_ptr); | |
| 431 | #else | ||
| 432 | 17392 | status = _lx_nor_flash_driver_read(nor_flash, list_word_ptr, &list_word, 1); | |
| 433 | |||
| 434 | /* Check for an error from flash driver. Drivers should never return an error.. */ | ||
| 435 |
1/4✗ Branch 65 → 66 not taken.
✗ Branch 65 → 68 not taken.
✗ Branch 67 → 68 not taken.
✓ Branch 67 → 70 taken 17392 times.
|
17392 | if (status) |
| 436 | { | ||
| 437 | |||
| 438 | /* Call system error handler. */ | ||
| 439 | ✗ | _lx_nor_flash_system_error(nor_flash, status); | |
| 440 | |||
| 441 | /* Return the error. */ | ||
| 442 | ✗ | return(status); | |
| 443 | } | ||
| 444 | #endif | ||
| 445 | |||
| 446 | /* Determine if the entry hasn't been used. */ | ||
| 447 |
2/6✗ Branch 48 → 49 not taken.
✗ Branch 48 → 50 not taken.
✗ Branch 68 → 69 not taken.
✗ Branch 68 → 70 not taken.
✓ Branch 70 → 71 taken 6 times.
✓ Branch 70 → 72 taken 17386 times.
|
17392 | if (list_word == LX_NOR_PHYSICAL_SECTOR_FREE) |
| 448 | { | ||
| 449 | |||
| 450 | /* Since allocations are done sequentially in the block, we know nothing | ||
| 451 | else exists after this point. */ | ||
| 452 | 6 | break; | |
| 453 | } | ||
| 454 | |||
| 455 | /* Is this entry mapped? */ | ||
| 456 |
2/6✗ Branch 50 → 51 not taken.
✗ Branch 50 → 52 not taken.
✗ Branch 70 → 71 not taken.
✗ Branch 70 → 72 not taken.
✓ Branch 72 → 73 taken 15146 times.
✓ Branch 72 → 74 taken 2240 times.
|
17386 | if ((list_word & LX_NOR_PHYSICAL_SECTOR_VALID) != 0) |
| 457 | { | ||
| 458 | |||
| 459 | /* Increment the number of mapped sectors. */ | ||
| 460 | 15146 | mapped_sectors++; | |
| 461 | } | ||
| 462 | |||
| 463 | /* Move the list pointer ahead. */ | ||
| 464 | 17386 | list_word_ptr++; | |
| 465 | } | ||
| 466 | |||
| 467 | /* Return the mapped sector count. */ | ||
| 468 | 1162 | *return_mapped_sectors = mapped_sectors; | |
| 469 | |||
| 470 | } | ||
| 471 | /* Return success. */ | ||
| 472 | 11602 | return(LX_SUCCESS); | |
| 473 | } | ||
| 474 | |||
| 475 |