GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lx_nor_flash_extended_cache_enable.c Lines: 17 18 94.4 %
Date: 2024-03-11 05:20:25 Branches: 6 8 75.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 *
4
 * This program and the accompanying materials are made available under the
5
 * terms of the MIT License which is available at
6
 * https://opensource.org/licenses/MIT.
7
 *
8
 * SPDX-License-Identifier: MIT
9
 **************************************************************************/
10
11
12
/**************************************************************************/
13
/**************************************************************************/
14
/**                                                                       */
15
/** LevelX Component                                                      */
16
/**                                                                       */
17
/**   NOR Flash                                                           */
18
/**                                                                       */
19
/**************************************************************************/
20
/**************************************************************************/
21
22
#define LX_SOURCE_CODE
23
24
25
/* Disable ThreadX error checking.  */
26
27
#ifndef LX_DISABLE_ERROR_CHECKING
28
#define LX_DISABLE_ERROR_CHECKING
29
#endif
30
31
32
/* Include necessary system files.  */
33
34
#include "lx_api.h"
35
36
37
/**************************************************************************/
38
/*                                                                        */
39
/*  FUNCTION                                               RELEASE        */
40
/*                                                                        */
41
/*    _lx_nor_flash_extended_cache_enable                 PORTABLE C      */
42
/*                                                           6.3.0        */
43
/*  AUTHOR                                                                */
44
/*                                                                        */
45
/*    William E. Lamie, Microsoft Corporation                             */
46
/*                                                                        */
47
/*  DESCRIPTION                                                           */
48
/*                                                                        */
49
/*    This function enables or disables the extended cache.               */
50
/*                                                                        */
51
/*  INPUT                                                                 */
52
/*                                                                        */
53
/*    nor_flash                             NOR flash instance            */
54
/*    memory                                Address of RAM for cache      */
55
/*    size                                  Size of the RAM for cache     */
56
/*                                                                        */
57
/*  OUTPUT                                                                */
58
/*                                                                        */
59
/*    return status                                                       */
60
/*                                                                        */
61
/*  CALLS                                                                 */
62
/*                                                                        */
63
/*    None                                                                */
64
/*                                                                        */
65
/*  CALLED BY                                                             */
66
/*                                                                        */
67
/*    Application Code                                                    */
68
/*                                                                        */
69
/*  RELEASE HISTORY                                                       */
70
/*                                                                        */
71
/*    DATE              NAME                      DESCRIPTION             */
72
/*                                                                        */
73
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
74
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
75
/*                                            resulting in version 6.1    */
76
/*  12-31-2020     William E. Lamie         Modified comment(s),          */
77
/*                                            fixed compiler warnings,    */
78
/*                                            resulting in version 6.1.3  */
79
/*  06-02-2021     Bhupendra Naphade        Modified comment(s), and      */
80
/*                                            updated product constants   */
81
/*                                            resulting in version 6.1.7  */
82
/*  10-15-2021     Bhupendra Naphade        Modified comment(s), and      */
83
/*                                            added check for out of      */
84
/*                                            bound memory access,        */
85
/*                                            resulting in version 6.1.9  */
86
/*  10-31-2023     Xiuwen Cai               Modified comment(s),          */
87
/*                                            added mapping bitmap cache, */
88
/*                                            added obsolete count cache, */
89
/*                                            resulting in version 6.3.0  */
90
/*                                                                        */
91
/**************************************************************************/
92
10
UINT  _lx_nor_flash_extended_cache_enable(LX_NOR_FLASH *nor_flash, VOID *memory, ULONG size)
93
{
94
#ifndef LX_NOR_DISABLE_EXTENDED_CACHE
95
96
UINT    i;
97
ULONG   cache_size;
98
ULONG   *cache_memory;
99
#ifdef LX_NOR_ENABLE_MAPPING_BITMAP
100
ULONG   mapping_bitmap_words;
101
ULONG   mapping_bitmap_word;
102
ULONG   logical_sector;
103
ULONG   *mapping_bitmap_ptr;
104
#endif
105
#ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE
106
ULONG   obsolete_count_words;
107
ULONG   obsolete_sectors;
108
#endif
109
#if defined(LX_NOR_ENABLE_MAPPING_BITMAP) || defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
110
ULONG   *block_word_ptr;
111
UINT    j;
112
UINT    status;
113
ULONG   block_word;
114
#endif
115
116
117
    /* Determine if memory was specified but with an invalid size (less than one NOR sector).  */
118

10
    if ((memory) && (size < LX_NOR_SECTOR_SIZE))
119
    {
120
121
        /* Error in memory size supplied.  */
122
        return(LX_ERROR);
123
    }
124
125
#ifdef LX_THREAD_SAFE_ENABLE
126
127
    /* Obtain the thread safe mutex.  */
128
    tx_mutex_get(&nor_flash -> lx_nor_flash_mutex, TX_WAIT_FOREVER);
129
#endif
130
131
    /* Initialize the internal NOR cache.  */
132
10
    nor_flash -> lx_nor_flash_extended_cache_entries =  0;
133
134
    /* Calculate cache size in words.  */
135
10
    cache_size = size/sizeof(ULONG);
136
137
    /* Setup cache memory pointer.  */
138
10
    cache_memory =  (ULONG *) memory;
139
140
#if defined(LX_NOR_ENABLE_MAPPING_BITMAP) || defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
141
142
    /* Check if the NOR flash is opened.  */
143
    if (nor_flash -> lx_nor_flash_state == LX_NOR_FLASH_OPENED)
144
    {
145
#if defined(LX_NOR_ENABLE_MAPPING_BITMAP)
146
147
        /* Get the mapping bitmap cache size.  */
148
        mapping_bitmap_words = (nor_flash -> lx_nor_flash_total_physical_sectors + 31) / 32;
149
150
        /* Check if the mapping bitmap cache fits in the suppiled cache memory.  */
151
        if (cache_size < mapping_bitmap_words)
152
        {
153
154
            /* Update the cache size.  */
155
            mapping_bitmap_words = cache_size;
156
        }
157
158
        /* Setup the mapping bitmap cache.  */
159
        nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap =  cache_memory;
160
161
        /* Setup the mapping bitmap cache size.  */
162
        nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap_max_logical_sector =  mapping_bitmap_words * 32;
163
164
        /* Clear the mapping bitmap cache.  */
165
        for (i = 0; i < mapping_bitmap_words; i++)
166
        {
167
            cache_memory[i] =  0;
168
        }
169
170
        /* Update the cache memory pointer.  */
171
        mapping_bitmap_ptr =  cache_memory;
172
173
        /* Update the cache size.  */
174
        cache_size =  cache_size - mapping_bitmap_words;
175
176
        /* Update the cache memory pointer.  */
177
        cache_memory =  cache_memory + mapping_bitmap_words;
178
#endif
179
180
#if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
181
182
        /* Get the obsolete count cache size.  */
183
        obsolete_count_words = nor_flash -> lx_nor_flash_total_blocks * sizeof(LX_NOR_OBSOLETE_COUNT_CACHE_TYPE) / 4;
184
185
        /* Check if the obsolete count cache fits in the suppiled cache memory.  */
186
        if (cache_size < obsolete_count_words)
187
        {
188
189
            /* Update the cache size.  */
190
            obsolete_count_words = cache_size;
191
        }
192
193
        /* Setup the obsolete count cache.  */
194
        nor_flash -> lx_nor_flash_extended_cache_obsolete_count =  (LX_NOR_OBSOLETE_COUNT_CACHE_TYPE*)cache_memory;
195
196
        /* Setup the obsolete count cache size.  */
197
        nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block =  obsolete_count_words * 4 / sizeof(LX_NOR_OBSOLETE_COUNT_CACHE_TYPE);
198
199
        /* Update the cache size.  */
200
        cache_size =  cache_size - obsolete_count_words;
201
202
        /* Update the cache memory pointer.  */
203
        cache_memory =  cache_memory + obsolete_count_words;
204
#endif
205
206
        /* Loop through the blocks.  */
207
        for (i = 0; i < nor_flash -> lx_nor_flash_total_blocks; i++)
208
        {
209
            /* Setup the block word pointer to the first word of the block.  */
210
            block_word_ptr =  (nor_flash -> lx_nor_flash_base_address + (i * nor_flash -> lx_nor_flash_words_per_block));
211
212
#if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
213
214
            /* Initialize the obsolete count cache.  */
215
            obsolete_sectors = 0;
216
#endif
217
218
            /* Now walk the list of logical-physical sector mapping.  */
219
            for (j = 0; j < nor_flash ->lx_nor_flash_physical_sectors_per_block; j++)
220
            {
221
222
                /* Read this word of the sector mapping list.  */
223
#ifdef LX_DIRECT_READ
224
225
                /* Read the word directly.  */
226
                block_word =  *(block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset + j);
227
#else
228
                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);
229
230
                /* Check for an error from flash driver. Drivers should never return an error..  */
231
                if (status)
232
                {
233
234
                    /* Call system error handler.  */
235
                    _lx_nor_flash_system_error(nor_flash, status);
236
237
                    /* Return an error.  */
238
                    return(LX_ERROR);
239
                }
240
#endif
241
                /* Determine if the entry hasn't been used.  */
242
                if (block_word == LX_NOR_PHYSICAL_SECTOR_FREE)
243
                {
244
                    break;
245
                }
246
247
                /* Is this entry valid?  */
248
                if ((block_word & (LX_NOR_PHYSICAL_SECTOR_VALID | LX_NOR_PHYSICAL_SECTOR_MAPPING_NOT_VALID)) == LX_NOR_PHYSICAL_SECTOR_VALID)
249
                {
250
#if defined(LX_NOR_ENABLE_MAPPING_BITMAP)
251
252
                    /* Yes, get the logical sector.  */
253
                    logical_sector = block_word & LX_NOR_LOGICAL_SECTOR_MASK;
254
255
                    /* Get the mapping bitmap word.  */
256
                    mapping_bitmap_word = logical_sector >> 5;
257
258
                    /* Check if the mapping bitmap word is within the cache.  */
259
                    if (mapping_bitmap_word < mapping_bitmap_words)
260
                    {
261
262
                        /* Set the bit in the mapping bitmap.  */
263
                        mapping_bitmap_ptr[mapping_bitmap_word] |=  (ULONG)(1 << (logical_sector & 31));
264
                    }
265
#endif
266
267
                }
268
                else
269
                {
270
#if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
271
272
                    /* Increment the obsolete sector count.  */
273
                    obsolete_sectors++;
274
#endif
275
                }
276
            }
277
#if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
278
279
            /* Check if the block is cached by obsolete count cache.  */
280
            if (i < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block)
281
            {
282
283
                /* Yes, cache the obsolete sector count.  */
284
                nor_flash -> lx_nor_flash_extended_cache_obsolete_count[i] = (LX_NOR_OBSOLETE_COUNT_CACHE_TYPE)obsolete_sectors;
285
            }
286
#endif
287
        }
288
    }
289
#endif
290
291
    /* Loop through the memory supplied and assign to cache entries.  */
292
10
    i =  0;
293
62
    while (cache_size >= LX_NOR_SECTOR_SIZE)
294
    {
295
296
        /* Setup this cache entry.  */
297
52
        nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_sector_address =  LX_NULL;
298
52
        nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_sector_memory =   cache_memory;
299
52
        nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_access_count =    0;
300
301
        /* Move the cache memory forward.   */
302
52
        cache_memory =  cache_memory + LX_NOR_SECTOR_SIZE;
303
304
        /* Decrement the size.  */
305
52
        cache_size =  cache_size - LX_NOR_SECTOR_SIZE;
306
307
        /* Move to next cache entry.  */
308
52
        i++;
309
    }
310
311
    /* Save the number of cache entries.  */
312
10
    if(i > LX_NOR_EXTENDED_CACHE_SIZE)
313
    {
314
315
1
        nor_flash -> lx_nor_flash_extended_cache_entries =  LX_NOR_EXTENDED_CACHE_SIZE;
316
    }
317
    else
318
    {
319
320
9
        nor_flash -> lx_nor_flash_extended_cache_entries =  i;
321
    }
322
323
#ifdef LX_THREAD_SAFE_ENABLE
324
325
    /* Release the thread safe mutex.  */
326
    tx_mutex_put(&nor_flash -> lx_nor_flash_mutex);
327
#endif
328
329
    /* Return successful completion.  */
330
10
    return(LX_SUCCESS);
331
#else
332
333
    LX_PARAMETER_NOT_USED(nor_flash);
334
    LX_PARAMETER_NOT_USED(memory);
335
    LX_PARAMETER_NOT_USED(size);
336
337
    /* Return disabled error message.  */
338
    return(LX_DISABLED);
339
#endif
340
}
341
342