1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
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 /*  RELEASE HISTORY                                                       */
71 /*                                                                        */
72 /*    DATE              NAME                      DESCRIPTION             */
73 /*                                                                        */
74 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
75 /*  09-30-2020     William E. Lamie         Modified comment(s),          */
76 /*                                            resulting in version 6.1    */
77 /*  12-31-2020     William E. Lamie         Modified comment(s),          */
78 /*                                            fixed compiler warnings,    */
79 /*                                            resulting in version 6.1.3  */
80 /*  06-02-2021     Bhupendra Naphade        Modified comment(s), and      */
81 /*                                            updated product constants   */
82 /*                                            resulting in version 6.1.7  */
83 /*  10-15-2021     Bhupendra Naphade        Modified comment(s), and      */
84 /*                                            added check for out of      */
85 /*                                            bound memory access,        */
86 /*                                            resulting in version 6.1.9  */
87 /*  10-31-2023     Xiuwen Cai               Modified comment(s),          */
88 /*                                            added mapping bitmap cache, */
89 /*                                            added obsolete count cache, */
90 /*                                            resulting in version 6.3.0  */
91 /*                                                                        */
92 /**************************************************************************/
_lx_nor_flash_extended_cache_enable(LX_NOR_FLASH * nor_flash,VOID * memory,ULONG size)93 UINT  _lx_nor_flash_extended_cache_enable(LX_NOR_FLASH *nor_flash, VOID *memory, ULONG size)
94 {
95 #ifndef LX_NOR_DISABLE_EXTENDED_CACHE
96 
97 UINT    i;
98 ULONG   cache_size;
99 ULONG   *cache_memory;
100 #ifdef LX_NOR_ENABLE_MAPPING_BITMAP
101 ULONG   mapping_bitmap_words;
102 ULONG   mapping_bitmap_word;
103 ULONG   logical_sector;
104 ULONG   *mapping_bitmap_ptr;
105 #endif
106 #ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE
107 ULONG   obsolete_count_words;
108 ULONG   obsolete_sectors;
109 #endif
110 #if defined(LX_NOR_ENABLE_MAPPING_BITMAP) || defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
111 ULONG   *block_word_ptr;
112 UINT    j;
113 UINT    status;
114 ULONG   block_word;
115 #endif
116 
117 
118     /* Determine if memory was specified but with an invalid size (less than one NOR sector).  */
119     if ((memory) && (size < LX_NOR_SECTOR_SIZE))
120     {
121 
122         /* Error in memory size supplied.  */
123         return(LX_ERROR);
124     }
125 
126 #ifdef LX_THREAD_SAFE_ENABLE
127 
128     /* Obtain the thread safe mutex.  */
129     tx_mutex_get(&nor_flash -> lx_nor_flash_mutex, TX_WAIT_FOREVER);
130 #endif
131 
132     /* Initialize the internal NOR cache.  */
133     nor_flash -> lx_nor_flash_extended_cache_entries =  0;
134 
135     /* Calculate cache size in words.  */
136     cache_size = size/sizeof(ULONG);
137 
138     /* Setup cache memory pointer.  */
139     cache_memory =  (ULONG *) memory;
140 
141 #if defined(LX_NOR_ENABLE_MAPPING_BITMAP) || defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
142 
143     /* Check if the NOR flash is opened.  */
144     if (nor_flash -> lx_nor_flash_state == LX_NOR_FLASH_OPENED)
145     {
146 #if defined(LX_NOR_ENABLE_MAPPING_BITMAP)
147 
148         /* Get the mapping bitmap cache size.  */
149         mapping_bitmap_words = (nor_flash -> lx_nor_flash_total_physical_sectors + 31) / 32;
150 
151         /* Check if the mapping bitmap cache fits in the suppiled cache memory.  */
152         if (cache_size < mapping_bitmap_words)
153         {
154 
155             /* Update the cache size.  */
156             mapping_bitmap_words = cache_size;
157         }
158 
159         /* Setup the mapping bitmap cache.  */
160         nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap =  cache_memory;
161 
162         /* Setup the mapping bitmap cache size.  */
163         nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap_max_logical_sector =  mapping_bitmap_words * 32;
164 
165         /* Clear the mapping bitmap cache.  */
166         for (i = 0; i < mapping_bitmap_words; i++)
167         {
168             cache_memory[i] =  0;
169         }
170 
171         /* Update the cache memory pointer.  */
172         mapping_bitmap_ptr =  cache_memory;
173 
174         /* Update the cache size.  */
175         cache_size =  cache_size - mapping_bitmap_words;
176 
177         /* Update the cache memory pointer.  */
178         cache_memory =  cache_memory + mapping_bitmap_words;
179 #endif
180 
181 #if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
182 
183         /* Get the obsolete count cache size.  */
184         obsolete_count_words = nor_flash -> lx_nor_flash_total_blocks * sizeof(LX_NOR_OBSOLETE_COUNT_CACHE_TYPE) / 4;
185 
186         /* Check if the obsolete count cache fits in the suppiled cache memory.  */
187         if (cache_size < obsolete_count_words)
188         {
189 
190             /* Update the cache size.  */
191             obsolete_count_words = cache_size;
192         }
193 
194         /* Setup the obsolete count cache.  */
195         nor_flash -> lx_nor_flash_extended_cache_obsolete_count =  (LX_NOR_OBSOLETE_COUNT_CACHE_TYPE*)cache_memory;
196 
197         /* Setup the obsolete count cache size.  */
198         nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block =  obsolete_count_words * 4 / sizeof(LX_NOR_OBSOLETE_COUNT_CACHE_TYPE);
199 
200         /* Update the cache size.  */
201         cache_size =  cache_size - obsolete_count_words;
202 
203         /* Update the cache memory pointer.  */
204         cache_memory =  cache_memory + obsolete_count_words;
205 #endif
206 
207         /* Loop through the blocks.  */
208         for (i = 0; i < nor_flash -> lx_nor_flash_total_blocks; i++)
209         {
210             /* Setup the block word pointer to the first word of the block.  */
211             block_word_ptr =  (nor_flash -> lx_nor_flash_base_address + (i * nor_flash -> lx_nor_flash_words_per_block));
212 
213 #if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
214 
215             /* Initialize the obsolete count cache.  */
216             obsolete_sectors = 0;
217 #endif
218 
219             /* Now walk the list of logical-physical sector mapping.  */
220             for (j = 0; j < nor_flash ->lx_nor_flash_physical_sectors_per_block; j++)
221             {
222 
223                 /* Read this word of the sector mapping list.  */
224 #ifdef LX_DIRECT_READ
225 
226                 /* Read the word directly.  */
227                 block_word =  *(block_word_ptr + nor_flash -> lx_nor_flash_block_physical_sector_mapping_offset + j);
228 #else
229                 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);
230 
231                 /* Check for an error from flash driver. Drivers should never return an error..  */
232                 if (status)
233                 {
234 
235                     /* Call system error handler.  */
236                     _lx_nor_flash_system_error(nor_flash, status);
237 
238                     /* Return an error.  */
239                     return(LX_ERROR);
240                 }
241 #endif
242                 /* Determine if the entry hasn't been used.  */
243                 if (block_word == LX_NOR_PHYSICAL_SECTOR_FREE)
244                 {
245                     break;
246                 }
247 
248                 /* Is this entry valid?  */
249                 if ((block_word & (LX_NOR_PHYSICAL_SECTOR_VALID | LX_NOR_PHYSICAL_SECTOR_MAPPING_NOT_VALID)) == LX_NOR_PHYSICAL_SECTOR_VALID)
250                 {
251 #if defined(LX_NOR_ENABLE_MAPPING_BITMAP)
252 
253                     /* Yes, get the logical sector.  */
254                     logical_sector = block_word & LX_NOR_LOGICAL_SECTOR_MASK;
255 
256                     /* Get the mapping bitmap word.  */
257                     mapping_bitmap_word = logical_sector >> 5;
258 
259                     /* Check if the mapping bitmap word is within the cache.  */
260                     if (mapping_bitmap_word < mapping_bitmap_words)
261                     {
262 
263                         /* Set the bit in the mapping bitmap.  */
264                         mapping_bitmap_ptr[mapping_bitmap_word] |=  (ULONG)(1 << (logical_sector & 31));
265                     }
266 #endif
267 
268                 }
269                 else
270                 {
271 #if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
272 
273                     /* Increment the obsolete sector count.  */
274                     obsolete_sectors++;
275 #endif
276                 }
277             }
278 #if defined(LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE)
279 
280             /* Check if the block is cached by obsolete count cache.  */
281             if (i < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block)
282             {
283 
284                 /* Yes, cache the obsolete sector count.  */
285                 nor_flash -> lx_nor_flash_extended_cache_obsolete_count[i] = (LX_NOR_OBSOLETE_COUNT_CACHE_TYPE)obsolete_sectors;
286             }
287 #endif
288         }
289     }
290 #endif
291 
292     /* Loop through the memory supplied and assign to cache entries.  */
293     i =  0;
294     while (cache_size >= LX_NOR_SECTOR_SIZE)
295     {
296 
297         /* Setup this cache entry.  */
298         nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_sector_address =  LX_NULL;
299         nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_sector_memory =   cache_memory;
300         nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_access_count =    0;
301 
302         /* Move the cache memory forward.   */
303         cache_memory =  cache_memory + LX_NOR_SECTOR_SIZE;
304 
305         /* Decrement the size.  */
306         cache_size =  cache_size - LX_NOR_SECTOR_SIZE;
307 
308         /* Move to next cache entry.  */
309         i++;
310     }
311 
312     /* Save the number of cache entries.  */
313     if(i > LX_NOR_EXTENDED_CACHE_SIZE)
314     {
315 
316         nor_flash -> lx_nor_flash_extended_cache_entries =  LX_NOR_EXTENDED_CACHE_SIZE;
317     }
318     else
319     {
320 
321         nor_flash -> lx_nor_flash_extended_cache_entries =  i;
322     }
323 
324 #ifdef LX_THREAD_SAFE_ENABLE
325 
326     /* Release the thread safe mutex.  */
327     tx_mutex_put(&nor_flash -> lx_nor_flash_mutex);
328 #endif
329 
330     /* Return successful completion.  */
331     return(LX_SUCCESS);
332 #else
333 
334     LX_PARAMETER_NOT_USED(nor_flash);
335     LX_PARAMETER_NOT_USED(memory);
336     LX_PARAMETER_NOT_USED(size);
337 
338     /* Return disabled error message.  */
339     return(LX_DISABLED);
340 #endif
341 }
342 
343 
344