GCC Code Coverage Report


Directory: common/src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 91.1% 51 / 0 / 56
Functions: 100.0% 1 / 0 / 1
Branches: 82.1% 64 / 0 / 78

lx_nor_flash_extended_cache_enable.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_extended_cache_enable PORTABLE C */
45 /* 6.3.0 */
46 /* AUTHOR */
47 /* */
48 /* William E. Lamie, Microsoft Corporation */
49 /* */
50 /* DESCRIPTION */
51 /* */
52 /* This function enables or disables the extended cache. */
53 /* */
54 /* INPUT */
55 /* */
56 /* nor_flash NOR flash instance */
57 /* memory Address of RAM for cache */
58 /* size Size of the RAM for cache */
59 /* */
60 /* OUTPUT */
61 /* */
62 /* return status */
63 /* */
64 /* CALLS */
65 /* */
66 /* None */
67 /* */
68 /* CALLED BY */
69 /* */
70 /* Application Code */
71 /* */
72 /**************************************************************************/
73 96 UINT _lx_nor_flash_extended_cache_enable(LX_NOR_FLASH *nor_flash, VOID *memory, ULONG size)
74 {
75 #ifndef LX_NOR_DISABLE_EXTENDED_CACHE
76
77 UINT i;
78 ULONG cache_size;
79 ULONG *cache_memory;
80 #ifdef LX_NOR_ENABLE_MAPPING_BITMAP
81 ULONG mapping_bitmap_words;
82 ULONG mapping_bitmap_word;
83 ULONG logical_sector;
84 ULONG *mapping_bitmap_ptr;
85 #endif
86 #ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE
87 ULONG obsolete_count_words;
88 ULONG obsolete_sectors;
89 #endif
90 #if defined(LX_NOR_ENABLE_MAPPING_BITMAP) || defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
91 ULONG *block_word_ptr;
92 UINT j;
93 UINT status;
94 ULONG block_word;
95 #endif
96
97
98 /* Calculate cache size in words. */
99 96 cache_size = size / sizeof(ULONG);
100
101 /* Determine if memory was specified but with an invalid size (less than one NOR sector). */
102
3/4
✓ Branch 2 → 3 taken 96 times.
✗ Branch 2 → 5 not taken.
✓ Branch 3 → 4 taken 8 times.
✓ Branch 3 → 5 taken 88 times.
96 if ((memory) && (cache_size < LX_NOR_SECTOR_SIZE))
103 {
104
105 /* Error in memory size supplied. */
106 8 return(LX_ERROR);
107 }
108
109 #ifdef LX_THREAD_SAFE_ENABLE
110
111 /* Obtain the thread safe mutex. */
112 tx_mutex_get(&nor_flash -> lx_nor_flash_mutex, TX_WAIT_FOREVER);
113 #endif
114
115 /* Initialize the internal NOR cache. */
116 88 nor_flash -> lx_nor_flash_extended_cache_entries = 0;
117
118 /* Setup cache memory pointer. */
119 88 cache_memory = (ULONG *) memory;
120
121 #if defined(LX_NOR_ENABLE_MAPPING_BITMAP) || defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
122
123 /* Check if the NOR flash is opened. */
124
4/4
✓ Branch 5 → 6 taken 30 times.
✓ Branch 5 → 24 taken 1 time.
✓ Branch 5 → 26 taken 1 time.
✓ Branch 5 → 31 taken 1 time.
33 if (nor_flash -> lx_nor_flash_state == LX_NOR_FLASH_OPENED)
125 {
126 #if defined(LX_NOR_ENABLE_MAPPING_BITMAP)
127
128 /* Get the mapping bitmap cache size. */
129 20 mapping_bitmap_words = (nor_flash -> lx_nor_flash_total_physical_sectors + 31) / 32;
130
131 /* Check if the mapping bitmap cache fits in the suppiled cache memory. */
132
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 20 times.
20 if (cache_size < mapping_bitmap_words)
133 {
134
135 /* Update the cache size. */
136 ✗ mapping_bitmap_words = cache_size;
137 }
138
139 /* Setup the mapping bitmap cache. */
140 20 nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap = cache_memory;
141
142 /* Setup the mapping bitmap cache size. */
143 20 nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap_max_logical_sector = mapping_bitmap_words * 32;
144
145 /* Clear the mapping bitmap cache. */
146
2/2
✓ Branch 10 → 9 taken 80 times.
✓ Branch 10 → 11 taken 20 times.
100 for (i = 0; i < mapping_bitmap_words; i++)
147 {
148 80 cache_memory[i] = 0;
149 }
150
151 /* Update the cache memory pointer. */
152 20 mapping_bitmap_ptr = cache_memory;
153
154 /* Update the cache size. */
155 20 cache_size = cache_size - mapping_bitmap_words;
156
157 /* Update the cache memory pointer. */
158 20 cache_memory = cache_memory + mapping_bitmap_words;
159 #endif
160
161 #if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
162
163 /* Get the obsolete count cache size. */
164 20 obsolete_count_words = nor_flash -> lx_nor_flash_total_blocks * sizeof(LX_NOR_OBSOLETE_COUNT_CACHE_TYPE) / 4;
165
166 /* Check if the obsolete count cache fits in the suppiled cache memory. */
167
2/4
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 10 times.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 10 times.
20 if (cache_size < obsolete_count_words)
168 {
169
170 /* Update the cache size. */
171 ✗ obsolete_count_words = cache_size;
172 }
173
174 /* Setup the obsolete count cache. */
175 20 nor_flash -> lx_nor_flash_extended_cache_obsolete_count = (LX_NOR_OBSOLETE_COUNT_CACHE_TYPE*)cache_memory;
176
177 /* Setup the obsolete count cache size. */
178 20 nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block = obsolete_count_words * 4 / sizeof(LX_NOR_OBSOLETE_COUNT_CACHE_TYPE);
179
180 /* Update the cache size. */
181 20 cache_size = cache_size - obsolete_count_words;
182
183 /* Update the cache memory pointer. */
184 20 cache_memory = cache_memory + obsolete_count_words;
185 #endif
186
187 /* Loop through the blocks. */
188
6/6
✓ Branch 23 → 9 taken 80 times.
✓ Branch 23 → 24 taken 10 times.
✓ Branch 25 → 12 taken 80 times.
✓ Branch 25 → 26 taken 10 times.
✓ Branch 30 → 14 taken 80 times.
✓ Branch 30 → 31 taken 10 times.
270 for (i = 0; i < nor_flash -> lx_nor_flash_total_blocks; i++)
189 {
190 /* Setup the block word pointer to the first word of the block. */
191 240 block_word_ptr = (nor_flash -> lx_nor_flash_base_address + (i * nor_flash -> lx_nor_flash_words_per_block));
192
193 #if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
194
195 /* Initialize the obsolete count cache. */
196 160 obsolete_sectors = 0;
197 #endif
198
199 /* Now walk the list of logical-physical sector mapping. */
200
3/6
✓ Branch 19 → 10 taken 144 times.
✗ Branch 19 → 20 not taken.
✓ Branch 23 → 13 taken 144 times.
✗ Branch 23 → 24 not taken.
✓ Branch 26 → 15 taken 144 times.
✗ Branch 26 → 27 not taken.
432 for (j = 0; j < nor_flash ->lx_nor_flash_physical_sectors_per_block; j++)
201 {
202
203 /* Read this word of the sector mapping list. */
204 #ifdef LX_DIRECT_READ
205
206 /* Read the word directly. */
207 block_word = *(block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset + j);
208 #else
209 432 status = _lx_nor_flash_driver_read(nor_flash, (block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset + j), &block_word, 1);
210
211 /* Check for an error from flash driver. Drivers should never return an error.. */
212
3/6
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 14 taken 144 times.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 17 taken 144 times.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 19 taken 144 times.
432 if (status)
213 {
214
215 /* Call system error handler. */
216 ✗ _lx_nor_flash_system_error(nor_flash, status);
217
218 /* Return an error. */
219 ✗ return(LX_ERROR);
220 }
221 #endif
222 /* Determine if the entry hasn't been used. */
223
6/6
✓ Branch 14 → 15 taken 80 times.
✓ Branch 14 → 16 taken 64 times.
✓ Branch 17 → 18 taken 80 times.
✓ Branch 17 → 19 taken 64 times.
✓ Branch 19 → 20 taken 80 times.
✓ Branch 19 → 21 taken 64 times.
432 if (block_word == LX_NOR_PHYSICAL_SECTOR_FREE)
224 {
225 240 break;
226 }
227
228 /* Is this entry valid? */
229
6/6
✓ Branch 16 → 17 taken 10 times.
✓ Branch 16 → 18 taken 54 times.
✓ Branch 19 → 20 taken 54 times.
✓ Branch 19 → 22 taken 10 times.
✓ Branch 21 → 22 taken 54 times.
✓ Branch 21 → 24 taken 10 times.
192 if ((block_word & (LX_NOR_PHYSICAL_SECTOR_VALID | LX_NOR_PHYSICAL_SECTOR_MAPPING_NOT_VALID)) == LX_NOR_PHYSICAL_SECTOR_VALID)
230 {
231 #if defined(LX_NOR_ENABLE_MAPPING_BITMAP)
232
233 /* Yes, get the logical sector. */
234 108 logical_sector = block_word & LX_NOR_LOGICAL_SECTOR_MASK;
235
236 /* Get the mapping bitmap word. */
237 108 mapping_bitmap_word = logical_sector >> 5;
238
239 /* Check if the mapping bitmap word is within the cache. */
240
2/4
✓ Branch 20 → 21 taken 54 times.
✗ Branch 20 → 22 not taken.
✓ Branch 22 → 23 taken 54 times.
✗ Branch 22 → 25 not taken.
108 if (mapping_bitmap_word < mapping_bitmap_words)
241 {
242
243 /* Set the bit in the mapping bitmap. */
244 108 mapping_bitmap_ptr[mapping_bitmap_word] |= (ULONG)(1 << (logical_sector & 31));
245 }
246 #endif
247
248 }
249 else
250 {
251 #if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
252
253 /* Increment the obsolete sector count. */
254 20 obsolete_sectors++;
255 #endif
256 }
257 }
258 #if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
259
260 /* Check if the block is cached by obsolete count cache. */
261
2/4
✓ Branch 20 → 21 taken 80 times.
✗ Branch 20 → 22 not taken.
✓ Branch 27 → 28 taken 80 times.
✗ Branch 27 → 29 not taken.
160 if (i < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block)
262 {
263
264 /* Yes, cache the obsolete sector count. */
265 160 nor_flash -> lx_nor_flash_extended_cache_obsolete_count[i] = (LX_NOR_OBSOLETE_COUNT_CACHE_TYPE)obsolete_sectors;
266 }
267 #endif
268 }
269 }
270 #endif
271
272 /* Loop through the memory supplied and assign to cache entries. */
273 88 i = 0;
274
16/16
✓ Branch 7 → 8 taken 230 times.
✓ Branch 7 → 9 taken 50 times.
✓ Branch 8 → 6 taken 225 times.
✓ Branch 8 → 9 taken 5 times.
✓ Branch 26 → 27 taken 46 times.
✓ Branch 26 → 28 taken 10 times.
✓ Branch 27 → 25 taken 45 times.
✓ Branch 27 → 28 taken 1 time.
✓ Branch 28 → 29 taken 46 times.
✓ Branch 28 → 30 taken 10 times.
✓ Branch 29 → 27 taken 45 times.
✓ Branch 29 → 30 taken 1 time.
✓ Branch 33 → 34 taken 46 times.
✓ Branch 33 → 35 taken 10 times.
✓ Branch 34 → 32 taken 45 times.
✓ Branch 34 → 35 taken 1 time.
448 while ((cache_size >= LX_NOR_SECTOR_SIZE) && (i < LX_NOR_EXTENDED_CACHE_SIZE))
275 {
276
277 /* Setup this cache entry. */
278 360 nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_sector_address = LX_NULL;
279 360 nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_sector_memory = cache_memory;
280 360 nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_access_count = 0;
281 360 nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_valid = LX_FALSE;
282
283 /* Move the cache memory forward. */
284 360 cache_memory = cache_memory + LX_NOR_SECTOR_SIZE;
285
286 /* Decrement the size. */
287 360 cache_size = cache_size - LX_NOR_SECTOR_SIZE;
288
289 /* Move to next cache entry. */
290 360 i++;
291 }
292
293 /* Save the number of cache entries. */
294
8/8
✓ Branch 9 → 10 taken 5 times.
✓ Branch 9 → 11 taken 50 times.
✓ Branch 28 → 29 taken 1 time.
✓ Branch 28 → 30 taken 10 times.
✓ Branch 30 → 31 taken 1 time.
✓ Branch 30 → 32 taken 10 times.
✓ Branch 35 → 36 taken 1 time.
✓ Branch 35 → 37 taken 10 times.
88 if(i == LX_NOR_EXTENDED_CACHE_SIZE)
295 {
296
297 8 nor_flash -> lx_nor_flash_extended_cache_entries = LX_NOR_EXTENDED_CACHE_SIZE;
298 }
299 else
300 {
301
302 80 nor_flash -> lx_nor_flash_extended_cache_entries = i;
303 }
304
305 #ifdef LX_THREAD_SAFE_ENABLE
306
307 /* Release the thread safe mutex. */
308 tx_mutex_put(&nor_flash -> lx_nor_flash_mutex);
309 #endif
310
311 /* Return successful completion. */
312 88 return(LX_SUCCESS);
313 #else
314
315 LX_PARAMETER_NOT_USED(nor_flash);
316 LX_PARAMETER_NOT_USED(memory);
317 LX_PARAMETER_NOT_USED(size);
318
319 /* Return disabled error message. */
320 ✗ return(LX_DISABLED);
321 #endif
322 }
323