GCC Code Coverage Report


Directory: common/src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 75.7% 53 / 0 / 70
Functions: 100.0% 1 / 0 / 1
Branches: 77.5% 62 / 0 / 80

lx_nor_flash_physical_sector_allocate.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_physical_sector_allocate PORTABLE C */
43 /* 6.1.7 */
44 /* AUTHOR */
45 /* */
46 /* William E. Lamie, Microsoft Corporation */
47 /* */
48 /* DESCRIPTION */
49 /* */
50 /* This function allocates a free physical sector for mapping to a */
51 /* logical sector. */
52 /* */
53 /* INPUT */
54 /* */
55 /* nor_flash NOR flash instance */
56 /* logical_sector Logical sector number */
57 /* physical_sector_map_entry Pointer to sector map entry */
58 /* physical_sector_address Address of physical sector */
59 /* */
60 /* OUTPUT */
61 /* */
62 /* return status */
63 /* */
64 /* CALLS */
65 /* */
66 /* _lx_nor_flash_driver_write Driver flash sector write */
67 /* _lx_nor_flash_driver_read Driver flash sector read */
68 /* _lx_nor_flash_system_error Internal system error handler */
69 /* */
70 /* CALLED BY */
71 /* */
72 /* Internal LevelX */
73 /* */
74 /**************************************************************************/
75 178740 UINT _lx_nor_flash_physical_sector_allocate(LX_NOR_FLASH *nor_flash, ULONG logical_sector, ULONG **physical_sector_map_entry, ULONG **physical_sector_address)
76 {
77
78 ULONG search_block;
79 ULONG *block_word_ptr;
80 ULONG block_word;
81 ULONG min_logical_sector;
82 ULONG max_logical_sector;
83 ULONG *list_word_ptr;
84 ULONG list_word;
85 ULONG i, j, k, l;
86 UINT status;
87
88
89 /* Increment the number of physical sector allocation requests. */
90 178740 nor_flash -> lx_nor_flash_physical_block_allocates++;
91
92 /* Initialize the return parameters. */
93 178740 *physical_sector_map_entry = (ULONG *) 0;
94 178740 *physical_sector_address = (ULONG *) 0;
95
96 /* Determine if there are any free physical sectors. */
97
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 178740 times.
178740 if (nor_flash -> lx_nor_flash_free_physical_sectors == 0)
98 {
99
100 /* Increment the number of failed allocations. */
101 ✗ nor_flash -> lx_nor_flash_physical_block_allocate_errors++;
102
103 /* No free physical sectors, return . */
104 ✗ return(LX_NO_SECTORS);
105 }
106
107 /* Pickup the search for a free physical sector at the specified block. */
108 178740 search_block = nor_flash -> lx_nor_flash_free_block_search;
109
110 /* Loop through the blocks to find a free physical sector. */
111
2/4
✓ Branch 44 → 5 taken 41712 times.
✗ Branch 44 → 45 not taken.
✓ Branch 56 → 5 taken 166848 times.
✗ Branch 56 → 57 not taken.
208560 for (i = 0; i < nor_flash -> lx_nor_flash_total_blocks; i++)
112 {
113
114 /* Setup the block word pointer to the first word of the search block. */
115 208560 block_word_ptr = nor_flash -> lx_nor_flash_base_address + (search_block * nor_flash -> lx_nor_flash_words_per_block);
116
117 /* Find the first free physical sector from the free sector bit map of this block. */
118
4/4
✓ Branch 40 → 6 taken 41712 times.
✓ Branch 40 → 41 taken 5964 times.
✓ Branch 52 → 6 taken 166848 times.
✓ Branch 52 → 53 taken 23856 times.
238380 for (j = 0; j < nor_flash -> lx_nor_flash_block_bit_map_words; j++)
119 {
120
121 /* Read this word of the free sector bit map. */
122 #ifdef LX_DIRECT_READ
123
124 /* Read the word directly. */
125 41712 block_word = *(block_word_ptr + nor_flash -> lx_nor_flash_block_free_bit_map_offset + j);
126 #else
127 166848 status = _lx_nor_flash_driver_read(nor_flash, (block_word_ptr + nor_flash -> lx_nor_flash_block_free_bit_map_offset + j), &block_word, 1);
128
129 /* Check for an error from flash driver. Drivers should never return an error.. */
130
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 10 taken 166848 times.
166848 if (status)
131 {
132
133 /* Call system error handler. */
134 ✗ _lx_nor_flash_system_error(nor_flash, status);
135
136 /* Return the error. */
137 ✗ return(status);
138 }
139 #endif
140
141 /* Are there any free sectors in this word? */
142
4/4
✓ Branch 6 → 7 taken 35748 times.
✓ Branch 6 → 39 taken 5964 times.
✓ Branch 10 → 11 taken 142992 times.
✓ Branch 10 → 51 taken 23856 times.
208560 if (block_word)
143 {
144
145 /* Yes, there are free sectors in this word. */
146
2/4
✓ Branch 38 → 8 taken 285518 times.
✗ Branch 38 → 39 not taken.
✓ Branch 50 → 12 taken 1142072 times.
✗ Branch 50 → 51 not taken.
1427590 for (k = 0; k < 32; k++)
147 {
148
149 /* Is this sector free? */
150
4/4
✓ Branch 8 → 9 taken 35748 times.
✓ Branch 8 → 35 taken 249770 times.
✓ Branch 12 → 13 taken 142992 times.
✓ Branch 12 → 47 taken 999080 times.
1427590 if (block_word & 1)
151 {
152
153 /* Yes, this sector is free, clear the bit for this sector in the free sector map. */
154
155 /* Read this word of the free sector bit map again. */
156 #ifdef LX_DIRECT_READ
157
158 /* Read the word directly. */
159 35748 block_word = *(block_word_ptr + nor_flash -> lx_nor_flash_block_free_bit_map_offset + j);
160 #else
161 142992 status = _lx_nor_flash_driver_read(nor_flash, (block_word_ptr + nor_flash -> lx_nor_flash_block_free_bit_map_offset + j), &block_word, 1);
162
163 /* Check for an error from flash driver. Drivers should never return an error.. */
164
1/2
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 17 taken 142992 times.
142992 if (status)
165 {
166
167 /* Call system error handler. */
168 ✗ _lx_nor_flash_system_error(nor_flash, status);
169
170 /* Return the error. */
171 ✗ return(status);
172 }
173 #endif
174
175 /* Clear the bit associated with the free sector to indicate it is not free. */
176 178740 block_word = block_word & ~(((ULONG) 1) << k);
177
178 /* Now write back free bit map word with the bit for this sector cleared. */
179 178740 status = _lx_nor_flash_driver_write(nor_flash, (block_word_ptr + nor_flash -> lx_nor_flash_block_free_bit_map_offset + j), &block_word, 1);
180
181 /* Check for an error from flash driver. Drivers should never return an error.. */
182
2/4
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 13 taken 35748 times.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 21 taken 142992 times.
178740 if (status)
183 {
184
185 /* Call system error handler. */
186 ✗ _lx_nor_flash_system_error(nor_flash, status);
187
188 /* Return the error. */
189 ✗ return(status);
190 }
191
192 /* Determine if this is the last entry available in this block. */
193
6/8
✓ Branch 13 → 14 taken 2372 times.
✓ Branch 13 → 34 taken 33376 times.
✓ Branch 14 → 15 taken 2372 times.
✗ Branch 14 → 34 not taken.
✓ Branch 21 → 22 taken 9488 times.
✓ Branch 21 → 46 taken 133504 times.
✓ Branch 22 → 23 taken 9488 times.
✗ Branch 22 → 46 not taken.
178740 if (((block_word >> 1) == 0) && (j == (nor_flash -> lx_nor_flash_block_bit_map_words - 1)))
194 {
195
196 /* This is the last physical sector in the block. Now we need to calculate the minimum valid logical
197 sector and the maximum valid logical sector. */
198
199 /* Setup the minimum and maximum logical sectors to the current logical sector. */
200 11860 min_logical_sector = logical_sector;
201 11860 max_logical_sector = logical_sector;
202
203 /* Setup a pointer to the mapped list. */
204 11860 list_word_ptr = block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset;
205
206 /* Loop to search the mapped list. */
207
4/4
✓ Branch 23 → 16 taken 35580 times.
✓ Branch 23 → 24 taken 2372 times.
✓ Branch 35 → 24 taken 142320 times.
✓ Branch 35 → 36 taken 9488 times.
189760 for (l = 0; l < nor_flash -> lx_nor_flash_physical_sectors_per_block; l++)
208 {
209
210 /* Read the mapped sector entry. */
211 #ifdef LX_DIRECT_READ
212
213 /* Read the word directly. */
214 35580 list_word = *(list_word_ptr);
215 #else
216 142320 status = _lx_nor_flash_driver_read(nor_flash, list_word_ptr, &list_word, 1);
217
218 /* Check for an error from flash driver. Drivers should never return an error.. */
219
1/2
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 28 taken 142320 times.
142320 if (status)
220 {
221
222 /* Call system error handler. */
223 ✗ _lx_nor_flash_system_error(nor_flash, status);
224
225 /* Return the error. */
226 ✗ return(status);
227 }
228 #endif
229
230 /* Is this entry valid? */
231
4/4
✓ Branch 16 → 17 taken 34964 times.
✓ Branch 16 → 22 taken 616 times.
✓ Branch 28 → 29 taken 139856 times.
✓ Branch 28 → 34 taken 2464 times.
177900 if (list_word & LX_NOR_PHYSICAL_SECTOR_VALID)
232 {
233
234 /* Isolate the logical sector. */
235 174820 list_word = list_word & LX_NOR_LOGICAL_SECTOR_MASK;
236
237 /* Determine if a new minimum has been found. */
238
4/4
✓ Branch 17 → 18 taken 4968 times.
✓ Branch 17 → 19 taken 29996 times.
✓ Branch 29 → 30 taken 19872 times.
✓ Branch 29 → 31 taken 119984 times.
174820 if (list_word < min_logical_sector)
239 24840 min_logical_sector = list_word;
240
241 /* Determine if a new maximum has been found. */
242
4/4
✓ Branch 19 → 20 taken 32592 times.
✓ Branch 19 → 22 taken 2372 times.
✓ Branch 31 → 32 taken 130368 times.
✓ Branch 31 → 34 taken 9488 times.
174820 if (list_word != LX_NOR_LOGICAL_SECTOR_MASK)
243 {
244
4/4
✓ Branch 20 → 21 taken 5932 times.
✓ Branch 20 → 22 taken 26660 times.
✓ Branch 32 → 33 taken 23728 times.
✓ Branch 32 → 34 taken 106640 times.
162960 if (list_word > max_logical_sector)
245 29660 max_logical_sector = list_word;
246 }
247 }
248
249 /* Move the list pointer ahead. */
250 177900 list_word_ptr++;
251 }
252
253 /* Move the search pointer forward, since we know this block is exhausted. */
254 11860 search_block++;
255
256 /* Check for wrap condition on the search block. */
257
4/4
✓ Branch 24 → 25 taken 292 times.
✓ Branch 24 → 26 taken 2080 times.
✓ Branch 36 → 37 taken 1168 times.
✓ Branch 36 → 38 taken 8320 times.
11860 if (search_block >= nor_flash -> lx_nor_flash_total_blocks)
258 {
259
260 /* Reset search block to the beginning. */
261 1460 search_block = 0;
262 }
263
264 /* Now write the minimum and maximum logical sector in this block. */
265 11860 status = _lx_nor_flash_driver_write(nor_flash, block_word_ptr + LX_NOR_FLASH_MIN_LOGICAL_SECTOR_OFFSET, &min_logical_sector, 1);
266
267 /* Check for an error from flash driver. Drivers should never return an error.. */
268
2/4
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 30 taken 2372 times.
✗ Branch 39 → 40 not taken.
✓ Branch 39 → 42 taken 9488 times.
11860 if (status)
269 {
270
271 /* Call system error handler. */
272 ✗ _lx_nor_flash_system_error(nor_flash, status);
273
274 /* Return the error. */
275 ✗ return(status);
276 }
277
278 11860 status = _lx_nor_flash_driver_write(nor_flash, block_word_ptr + LX_NOR_FLASH_MAX_LOGICAL_SECTOR_OFFSET, &max_logical_sector, 1);
279
280 /* Check for an error from flash driver. Drivers should never return an error.. */
281
2/4
✗ Branch 31 → 32 not taken.
✓ Branch 31 → 34 taken 2372 times.
✗ Branch 43 → 44 not taken.
✓ Branch 43 → 46 taken 9488 times.
11860 if (status)
282 {
283
284 /* Call system error handler. */
285 ✗ _lx_nor_flash_system_error(nor_flash, status);
286
287 /* Return the error. */
288 ✗ return(status);
289 }
290 }
291
292 /* Remember the block to search. */
293 178740 nor_flash -> lx_nor_flash_free_block_search = search_block;
294
295 /* Prepare the return information. */
296 178740 *physical_sector_map_entry = block_word_ptr + (nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset + (j * 32)) + k;
297 178740 *physical_sector_address = block_word_ptr + (nor_flash -> lx_nor_flash_block_physical_sector_offset) + (((j * 32) + k) * LX_NOR_SECTOR_SIZE);
298
299 /* Return success! */
300 178740 return(LX_SUCCESS);
301 }
302
303 /* Shift down the bit map. */
304 1248850 block_word = block_word >> 1;
305
306 /* Determine if there are any more bits set? If not, we can break out of the search of this word. */
307
2/4
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 37 taken 249770 times.
✗ Branch 47 → 48 not taken.
✓ Branch 47 → 49 taken 999080 times.
1248850 if (block_word == 0)
308 ✗ break;
309 }
310 }
311 }
312
313 /* Move to the next flash block. */
314 29820 search_block++;
315
316 /* Determine if we have to wrap the search block. */
317
4/4
✓ Branch 41 → 42 taken 748 times.
✓ Branch 41 → 43 taken 5216 times.
✓ Branch 53 → 54 taken 2992 times.
✓ Branch 53 → 55 taken 20864 times.
29820 if (search_block >= nor_flash -> lx_nor_flash_total_blocks)
318 {
319
320 /* Set the search block to the beginning. */
321 3740 search_block = 0;
322 }
323 }
324
325 /* Increment the number of failed allocations. */
326 ✗ nor_flash -> lx_nor_flash_physical_block_allocate_errors++;
327
328 /* Return no sector completion. */
329 ✗ return(LX_NO_SECTORS);
330 }
331
332