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_read                  PORTABLE C       */
43 /*                                                           6.2.1       */
44 /*  AUTHOR                                                                */
45 /*                                                                        */
46 /*    William E. Lamie, Microsoft Corporation                             */
47 /*                                                                        */
48 /*  DESCRIPTION                                                           */
49 /*                                                                        */
50 /*    This function performs a read of the NOR flash memory.              */
51 /*                                                                        */
52 /*  INPUT                                                                 */
53 /*                                                                        */
54 /*    nor_flash                             NOR flash instance            */
55 /*    flash_address                         Address of NOR flash to read  */
56 /*    destination                           Destination for the read      */
57 /*    words                                 Number of words to read       */
58 /*                                                                        */
59 /*  OUTPUT                                                                */
60 /*                                                                        */
61 /*    return status                                                       */
62 /*                                                                        */
63 /*  CALLS                                                                 */
64 /*                                                                        */
65 /*    (lx_nor_flash_driver_read)            Actual driver read            */
66 /*                                                                        */
67 /*  CALLED BY                                                             */
68 /*                                                                        */
69 /*    Application Code                                                    */
70 /*                                                                        */
71 /*  RELEASE HISTORY                                                       */
72 /*                                                                        */
73 /*    DATE              NAME                      DESCRIPTION             */
74 /*                                                                        */
75 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
76 /*  09-30-2020     William E. Lamie         Modified comment(s),          */
77 /*                                            resulting in version 6.1    */
78 /*  06-02-2021     Bhupendra Naphade        Modified comment(s),          */
79 /*                                            resulting in version 6.1.7  */
80 /*  03-08-2023     Xiuwen Cai               Modified comment(s),          */
81 /*                                            added new driver interface, */
82 /*                                            resulting in version 6.2.1 */
83 /*                                                                        */
84 /**************************************************************************/
_lx_nor_flash_driver_read(LX_NOR_FLASH * nor_flash,ULONG * flash_address,ULONG * destination,ULONG words)85 UINT  _lx_nor_flash_driver_read(LX_NOR_FLASH *nor_flash, ULONG *flash_address, ULONG *destination, ULONG words)
86 {
87 #ifndef LX_NOR_DISABLE_EXTENDED_CACHE
88 
89 UINT    status;
90 UINT    i;
91 ULONG   *cache_entry_start;
92 ULONG   *cache_entry_end;
93 ULONG   cache_offset;
94 UINT    least_used_cache_entry;
95 
96 
97     /* Is the request a whole sector or a partial sector.  */
98     if ((words == 1) && (nor_flash -> lx_nor_flash_extended_cache_entries))
99     {
100 
101         /* One word request, which implies that it is a NOR flash metadata read.  */
102 
103 
104         /* Initialize the least used cache entry.  */
105         least_used_cache_entry =  0;
106 
107         do
108         {
109 
110             /* Loop through the cache entries to see if there is a sector in cache.  */
111             for (i = 0; i < nor_flash -> lx_nor_flash_extended_cache_entries; i++)
112             {
113 
114                 /* Search through the cache to find the entry.  */
115 
116                 /* Determine the cache entry addresses.  */
117                 cache_entry_start =  nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_sector_address;
118                 cache_entry_end =    cache_entry_start + LX_NOR_SECTOR_SIZE;
119 
120                 /* Determine if the flash address in in the cache entry.  */
121                 if ((cache_entry_start) && (flash_address >= cache_entry_start) && (flash_address < cache_entry_end))
122                 {
123 
124                     /* Yes, we found the entry.  */
125 
126                     /* Increment the accessed count.  */
127                     nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_access_count++;
128 
129                     /* Calculate the offset into the cache entry.  */
130                     cache_offset =  (ULONG)(flash_address - cache_entry_start);
131 
132                     /* Copy the word from the cache.  */
133                     *destination =  *(nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_sector_memory + cache_offset);
134 
135                     /* Increment the number of cache hits.  */
136                     nor_flash -> lx_nor_flash_extended_cache_hits++;
137 
138                     /* Return success.  */
139                     return(LX_SUCCESS);
140                 }
141                 else
142                 {
143 
144                     /* Determine if we have a new least used sector.  */
145                     if (i != least_used_cache_entry)
146                     {
147 
148                         /* Determine if this entry has a smaller accessed count.  */
149                         if (nor_flash -> lx_nor_flash_extended_cache[i].lx_nor_flash_extended_cache_entry_access_count <
150                             nor_flash -> lx_nor_flash_extended_cache[least_used_cache_entry].lx_nor_flash_extended_cache_entry_access_count)
151                         {
152 
153                             /* New least used entry.  */
154                             least_used_cache_entry =  i;
155                         }
156                     }
157                 }
158             }
159 
160             /* Now read in the sector into the cache.  */
161             cache_offset =  (ULONG)(flash_address - nor_flash -> lx_nor_flash_base_address);
162             cache_offset =  cache_offset & ~((ULONG) (LX_NOR_SECTOR_SIZE-1));
163             cache_entry_start =  nor_flash -> lx_nor_flash_base_address + cache_offset;
164 
165             /* Call the actual driver read function.  */
166 #ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
167             status =  (nor_flash -> lx_nor_flash_driver_read)(nor_flash, cache_entry_start,
168                             nor_flash -> lx_nor_flash_extended_cache[least_used_cache_entry].lx_nor_flash_extended_cache_entry_sector_memory,
169                             LX_NOR_SECTOR_SIZE);
170 #else
171             status =  (nor_flash -> lx_nor_flash_driver_read)(cache_entry_start,
172                             nor_flash -> lx_nor_flash_extended_cache[least_used_cache_entry].lx_nor_flash_extended_cache_entry_sector_memory,
173                             LX_NOR_SECTOR_SIZE);
174 #endif
175 
176             /* Determine if there was an error.  */
177             if (status != LX_SUCCESS)
178             {
179 
180                 /* Return the error to the caller.  */
181                 return(status);
182             }
183 
184             /* Setup the cache entry.  */
185             nor_flash -> lx_nor_flash_extended_cache[least_used_cache_entry].lx_nor_flash_extended_cache_entry_sector_address =  cache_entry_start;
186             nor_flash -> lx_nor_flash_extended_cache[least_used_cache_entry].lx_nor_flash_extended_cache_entry_access_count =    0;
187 
188             /* Increment the number of cache misses.  */
189             nor_flash -> lx_nor_flash_extended_cache_misses++;
190 
191             /* Decrement the number of cache hits, so that the increment that will happen next will be cancelled out.  */
192             nor_flash -> lx_nor_flash_extended_cache_hits--;
193 
194         } while (status == LX_SUCCESS);
195 
196         /* Return success.  */
197         return(LX_SUCCESS);
198     }
199     else
200     {
201 
202         /* Call the actual driver read function.  */
203 #ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
204         status =  (nor_flash -> lx_nor_flash_driver_read)(nor_flash, flash_address, destination, words);
205 #else
206         status =  (nor_flash -> lx_nor_flash_driver_read)(flash_address, destination, words);
207 #endif
208 
209         /* Return completion status.  */
210         return(status);
211     }
212 #else
213 UINT    status;
214 
215 
216     /* Call the actual driver read function.  */
217 #ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
218     status =  (nor_flash -> lx_nor_flash_driver_read)(nor_flash, flash_address, destination, words);
219 #else
220     status =  (nor_flash -> lx_nor_flash_driver_read)(flash_address, destination, words);
221 #endif
222 
223     /* Return completion status.  */
224     return(status);
225 #endif
226 }
227 
228 
229