GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lx_nor_flash_extended_cache_enable.c Lines: 17 18 94.4 %
Date: 2026-03-06 18:45:40 Branches: 8 10 80.0 %

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_extended_cache_enable                 PORTABLE C      */
43
/*                                                           6.3.0        */
44
/*  AUTHOR                                                                */
45
/*                                                                        */
46
/*    William E. Lamie, Microsoft Corporation                             */
47
/*                                                                        */
48
/*  DESCRIPTION                                                           */
49
/*                                                                        */
50
/*    This function enables or disables the extended cache.               */
51
/*                                                                        */
52
/*  INPUT                                                                 */
53
/*                                                                        */
54
/*    nor_flash                             NOR flash instance            */
55
/*    memory                                Address of RAM for cache      */
56
/*    size                                  Size of the RAM for cache     */
57
/*                                                                        */
58
/*  OUTPUT                                                                */
59
/*                                                                        */
60
/*    return status                                                       */
61
/*                                                                        */
62
/*  CALLS                                                                 */
63
/*                                                                        */
64
/*    None                                                                */
65
/*                                                                        */
66
/*  CALLED BY                                                             */
67
/*                                                                        */
68
/*    Application Code                                                    */
69
/*                                                                        */
70
/**************************************************************************/
71
10
UINT  _lx_nor_flash_extended_cache_enable(LX_NOR_FLASH *nor_flash, VOID *memory, ULONG size)
72
{
73
#ifndef LX_NOR_DISABLE_EXTENDED_CACHE
74
75
UINT    i;
76
ULONG   cache_size;
77
ULONG   *cache_memory;
78
#ifdef LX_NOR_ENABLE_MAPPING_BITMAP
79
ULONG   mapping_bitmap_words;
80
ULONG   mapping_bitmap_word;
81
ULONG   logical_sector;
82
ULONG   *mapping_bitmap_ptr;
83
#endif
84
#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE
85
ULONG   obsolete_count_words;
86
ULONG   obsolete_sectors;
87
#endif
88
#if defined(LX_NOR_ENABLE_MAPPING_BITMAP) || defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
89
ULONG   *block_word_ptr;
90
UINT    j;
91
UINT    status;
92
ULONG   block_word;
93
#endif
94
95
96
    /* Determine if memory was specified but with an invalid size (less than one NOR sector).  */
97

10
    if ((memory) && (size < LX_NOR_SECTOR_SIZE))
98
    {
99
100
        /* Error in memory size supplied.  */
101
        return(LX_ERROR);
102
    }
103
104
#ifdef LX_THREAD_SAFE_ENABLE
105
106
    /* Obtain the thread safe mutex.  */
107
    tx_mutex_get(&nor_flash -> lx_nor_flash_mutex, TX_WAIT_FOREVER);
108
#endif
109
110
    /* Initialize the internal NOR cache.  */
111
10
    nor_flash -> lx_nor_flash_extended_cache_entries =  0;
112
113
    /* Calculate cache size in words.  */
114
10
    cache_size = size/sizeof(ULONG);
115
116
    /* Setup cache memory pointer.  */
117
10
    cache_memory =  (ULONG *) memory;
118
119
#if defined(LX_NOR_ENABLE_MAPPING_BITMAP) || defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
120
121
    /* Check if the NOR flash is opened.  */
122
    if (nor_flash -> lx_nor_flash_state == LX_NOR_FLASH_OPENED)
123
    {
124
#if defined(LX_NOR_ENABLE_MAPPING_BITMAP)
125
126
        /* Get the mapping bitmap cache size.  */
127
        mapping_bitmap_words = (nor_flash -> lx_nor_flash_total_physical_sectors + 31) / 32;
128
129
        /* Check if the mapping bitmap cache fits in the suppiled cache memory.  */
130
        if (cache_size < mapping_bitmap_words)
131
        {
132
133
            /* Update the cache size.  */
134
            mapping_bitmap_words = cache_size;
135
        }
136
137
        /* Setup the mapping bitmap cache.  */
138
        nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap =  cache_memory;
139
140
        /* Setup the mapping bitmap cache size.  */
141
        nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap_max_logical_sector =  mapping_bitmap_words * 32;
142
143
        /* Clear the mapping bitmap cache.  */
144
        for (i = 0; i < mapping_bitmap_words; i++)
145
        {
146
            cache_memory[i] =  0;
147
        }
148
149
        /* Update the cache memory pointer.  */
150
        mapping_bitmap_ptr =  cache_memory;
151
152
        /* Update the cache size.  */
153
        cache_size =  cache_size - mapping_bitmap_words;
154
155
        /* Update the cache memory pointer.  */
156
        cache_memory =  cache_memory + mapping_bitmap_words;
157
#endif
158
159
#if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
160
161
        /* Get the obsolete count cache size.  */
162
        obsolete_count_words = nor_flash -> lx_nor_flash_total_blocks * sizeof(LX_NOR_OBSOLETE_COUNT_CACHE_TYPE) / 4;
163
164
        /* Check if the obsolete count cache fits in the suppiled cache memory.  */
165
        if (cache_size < obsolete_count_words)
166
        {
167
168
            /* Update the cache size.  */
169
            obsolete_count_words = cache_size;
170
        }
171
172
        /* Setup the obsolete count cache.  */
173
        nor_flash -> lx_nor_flash_extended_cache_obsolete_count =  (LX_NOR_OBSOLETE_COUNT_CACHE_TYPE*)cache_memory;
174
175
        /* Setup the obsolete count cache size.  */
176
        nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block =  obsolete_count_words * 4 / sizeof(LX_NOR_OBSOLETE_COUNT_CACHE_TYPE);
177
178
        /* Update the cache size.  */
179
        cache_size =  cache_size - obsolete_count_words;
180
181
        /* Update the cache memory pointer.  */
182
        cache_memory =  cache_memory + obsolete_count_words;
183
#endif
184
185
        /* Loop through the blocks.  */
186
        for (i = 0; i < nor_flash -> lx_nor_flash_total_blocks; i++)
187
        {
188
            /* Setup the block word pointer to the first word of the block.  */
189
            block_word_ptr =  (nor_flash -> lx_nor_flash_base_address + (i * nor_flash -> lx_nor_flash_words_per_block));
190
191
#if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
192
193
            /* Initialize the obsolete count cache.  */
194
            obsolete_sectors = 0;
195
#endif
196
197
            /* Now walk the list of logical-physical sector mapping.  */
198
            for (j = 0; j < nor_flash ->lx_nor_flash_physical_sectors_per_block; j++)
199
            {
200
201
                /* Read this word of the sector mapping list.  */
202
#ifdef LX_DIRECT_READ
203
204
                /* Read the word directly.  */
205
                block_word =  *(block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset + j);
206
#else
207
                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);
208
209
                /* Check for an error from flash driver. Drivers should never return an error..  */
210
                if (status)
211
                {
212
213
                    /* Call system error handler.  */
214
                    _lx_nor_flash_system_error(nor_flash, status);
215
216
                    /* Return an error.  */
217
                    return(LX_ERROR);
218
                }
219
#endif
220
                /* Determine if the entry hasn't been used.  */
221
                if (block_word == LX_NOR_PHYSICAL_SECTOR_FREE)
222
                {
223
                    break;
224
                }
225
226
                /* Is this entry valid?  */
227
                if ((block_word & (LX_NOR_PHYSICAL_SECTOR_VALID | LX_NOR_PHYSICAL_SECTOR_MAPPING_NOT_VALID)) == LX_NOR_PHYSICAL_SECTOR_VALID)
228
                {
229
#if defined(LX_NOR_ENABLE_MAPPING_BITMAP)
230
231
                    /* Yes, get the logical sector.  */
232
                    logical_sector = block_word & LX_NOR_LOGICAL_SECTOR_MASK;
233
234
                    /* Get the mapping bitmap word.  */
235
                    mapping_bitmap_word = logical_sector >> 5;
236
237
                    /* Check if the mapping bitmap word is within the cache.  */
238
                    if (mapping_bitmap_word < mapping_bitmap_words)
239
                    {
240
241
                        /* Set the bit in the mapping bitmap.  */
242
                        mapping_bitmap_ptr[mapping_bitmap_word] |=  (ULONG)(1 << (logical_sector & 31));
243
                    }
244
#endif
245
246
                }
247
                else
248
                {
249
#if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
250
251
                    /* Increment the obsolete sector count.  */
252
                    obsolete_sectors++;
253
#endif
254
                }
255
            }
256
#if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
257
258
            /* Check if the block is cached by obsolete count cache.  */
259
            if (i < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block)
260
            {
261
262
                /* Yes, cache the obsolete sector count.  */
263
                nor_flash -> lx_nor_flash_extended_cache_obsolete_count[i] = (LX_NOR_OBSOLETE_COUNT_CACHE_TYPE)obsolete_sectors;
264
            }
265
#endif
266
        }
267
    }
268
#endif
269
270
    /* Loop through the memory supplied and assign to cache entries.  */
271
10
    i =  0;
272

54
    while ((cache_size >= LX_NOR_SECTOR_SIZE) && (i < LX_NOR_EXTENDED_CACHE_SIZE))
273
    {
274
275
        /* Setup this cache entry.  */
276
44
        nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_sector_address =  LX_NULL;
277
44
        nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_sector_memory =   cache_memory;
278
44
        nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_access_count =    0;
279
280
        /* Move the cache memory forward.   */
281
44
        cache_memory =  cache_memory + LX_NOR_SECTOR_SIZE;
282
283
        /* Decrement the size.  */
284
44
        cache_size =  cache_size - LX_NOR_SECTOR_SIZE;
285
286
        /* Move to next cache entry.  */
287
44
        i++;
288
    }
289
290
    /* Save the number of cache entries.  */
291
10
    if(i == LX_NOR_EXTENDED_CACHE_SIZE)
292
    {
293
294
1
        nor_flash -> lx_nor_flash_extended_cache_entries =  LX_NOR_EXTENDED_CACHE_SIZE;
295
    }
296
    else
297
    {
298
299
9
        nor_flash -> lx_nor_flash_extended_cache_entries =  i;
300
    }
301
302
#ifdef LX_THREAD_SAFE_ENABLE
303
304
    /* Release the thread safe mutex.  */
305
    tx_mutex_put(&nor_flash -> lx_nor_flash_mutex);
306
#endif
307
308
    /* Return successful completion.  */
309
10
    return(LX_SUCCESS);
310
#else
311
312
    LX_PARAMETER_NOT_USED(nor_flash);
313
    LX_PARAMETER_NOT_USED(memory);
314
    LX_PARAMETER_NOT_USED(size);
315
316
    /* Return disabled error message.  */
317
    return(LX_DISABLED);
318
#endif
319
}
320
321