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