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_sector_release                        PORTABLE C      */
43 /*                                                           6.3.0        */
44 /*  AUTHOR                                                                */
45 /*                                                                        */
46 /*    William E. Lamie, Microsoft Corporation                             */
47 /*                                                                        */
48 /*  DESCRIPTION                                                           */
49 /*                                                                        */
50 /*    This function releases a logical sector from being managed in the   */
51 /*    NOR flash.                                                          */
52 /*                                                                        */
53 /*  INPUT                                                                 */
54 /*                                                                        */
55 /*    nor_flash                             NOR flash instance            */
56 /*    logical_sector                        Logical sector number         */
57 /*                                                                        */
58 /*  OUTPUT                                                                */
59 /*                                                                        */
60 /*    return status                                                       */
61 /*                                                                        */
62 /*  CALLS                                                                 */
63 /*                                                                        */
64 /*    _lx_nor_flash_driver_write            Driver flash sector write     */
65 /*    _lx_nor_flash_driver_read             Driver flash sector read      */
66 /*    _lx_nor_flash_block_reclaim           Reclaim one flash block       */
67 /*    _lx_nor_flash_sector_mapping_cache_invalidate                       */
68 /*                                          Invalidate cache entry        */
69 /*    _lx_nor_flash_logical_sector_find     Find logical sector           */
70 /*    _lx_nor_flash_system_error            Internal system error handler */
71 /*    tx_mutex_get                          Get thread protection         */
72 /*    tx_mutex_put                          Release thread protection     */
73 /*                                                                        */
74 /*  CALLED BY                                                             */
75 /*                                                                        */
76 /*    Application Code                                                    */
77 /*                                                                        */
78 /*  RELEASE HISTORY                                                       */
79 /*                                                                        */
80 /*    DATE              NAME                      DESCRIPTION             */
81 /*                                                                        */
82 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
83 /*  09-30-2020     William E. Lamie         Modified comment(s),          */
84 /*                                            resulting in version 6.1    */
85 /*  06-02-2021     Bhupendra Naphade        Modified comment(s),          */
86 /*                                            resulting in version 6.1.7  */
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_sector_release(LX_NOR_FLASH * nor_flash,ULONG logical_sector)93 UINT  _lx_nor_flash_sector_release(LX_NOR_FLASH *nor_flash, ULONG logical_sector)
94 {
95 
96 UINT    status;
97 ULONG   *mapping_address;
98 ULONG   mapping_entry;
99 ULONG   *sector_address;
100 ULONG   i;
101 #ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE
102 ULONG   block;
103 #endif
104 
105 
106 #ifdef LX_THREAD_SAFE_ENABLE
107 
108     /* Obtain the thread safe mutex.  */
109     tx_mutex_get(&nor_flash -> lx_nor_flash_mutex, TX_WAIT_FOREVER);
110 #endif
111 
112     /* Increment the number of read requests.  */
113     nor_flash -> lx_nor_flash_read_requests++;
114 
115     /* See if we can find the sector in the current mapping.  */
116     _lx_nor_flash_logical_sector_find(nor_flash, logical_sector, LX_FALSE, &mapping_address, &sector_address);
117 
118     /* Determine if the logical sector was found.  */
119     if (mapping_address)
120     {
121 
122         /* Yes, we were able to find the logical sector.  */
123 
124         /* Read in the old sector mapping.  */
125 #ifdef LX_DIRECT_READ
126 
127         /* Read the word directly.  */
128         mapping_entry =  *(mapping_address);
129 #else
130         status =  _lx_nor_flash_driver_read(nor_flash, mapping_address, &mapping_entry, 1);
131 
132         /* Check for an error from flash driver. Drivers should never return an error..  */
133         if (status)
134         {
135 
136             /* Call system error handler.  */
137             _lx_nor_flash_system_error(nor_flash, status);
138 
139 #ifdef LX_THREAD_SAFE_ENABLE
140 
141             /* Release the thread safe mutex.  */
142             tx_mutex_put(&nor_flash -> lx_nor_flash_mutex);
143 #endif
144 
145             /* Return status.  */
146             return(LX_ERROR);
147         }
148 #endif
149 
150         /* Mark this sector as invalid.  */
151         /* Now clear bits 31 and 30, which indicates this sector is now obsoleted.  */
152         mapping_entry =  mapping_entry & ~(((ULONG) LX_NOR_PHYSICAL_SECTOR_VALID) | ((ULONG) LX_NOR_PHYSICAL_SECTOR_SUPERCEDED));
153 
154         /* Write the value back to the flash to clear bits 31 & 30.  */
155         status =  _lx_nor_flash_driver_write(nor_flash, mapping_address, &mapping_entry, 1);
156 
157         /* Check for an error from flash driver. Drivers should never return an error..  */
158         if (status)
159         {
160 
161             /* Call system error handler.  */
162             _lx_nor_flash_system_error(nor_flash, status);
163 
164 #ifdef LX_THREAD_SAFE_ENABLE
165 
166             /* Release the thread safe mutex.  */
167             tx_mutex_put(&nor_flash -> lx_nor_flash_mutex);
168 #endif
169 
170             /* Return status.  */
171             return(LX_ERROR);
172         }
173 
174 #ifndef LX_NOR_DISABLE_EXTENDED_CACHE
175 #ifdef LX_NOR_ENABLE_MAPPING_BITMAP
176 
177         /* Determine if the logical sector is within the mapping bitmap.  */
178         if (logical_sector < nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap_max_logical_sector)
179         {
180 
181             /* Set the bit in the mapping bitmap.  */
182             nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap[logical_sector >> 5] &= (ULONG)~(1 << (logical_sector & 31));
183         }
184 #endif
185 #endif
186 
187         /* Increment the number of obsolete physical sectors.  */
188         nor_flash -> lx_nor_flash_obsolete_physical_sectors++;
189 
190 #ifdef LX_NOR_ENABLE_OBSOLETE_COUNT_CACHE
191 
192         /* Get the block number from mapping address.  */
193         block = (ULONG)(mapping_address - nor_flash -> lx_nor_flash_base_address) / nor_flash -> lx_nor_flash_words_per_block;
194 
195         /* Determine if this block is within the range of the obsolete count cache.  */
196         if (block < nor_flash -> lx_nor_flash_extended_cache_obsolete_count_max_block)
197         {
198 
199             /* Increment the obsolete count for this block.  */
200             nor_flash -> lx_nor_flash_extended_cache_obsolete_count[block] ++;
201         }
202 #endif
203 
204         /* Decrement the number of mapped physical sectors.  */
205         nor_flash -> lx_nor_flash_mapped_physical_sectors--;
206 
207         /* Ensure the sector mapping cache no longer has this sector.  */
208         _lx_nor_flash_sector_mapping_cache_invalidate(nor_flash, logical_sector);
209 
210         /* Determine if there are less than two block's worth of free sectors.  */
211         i =  0;
212         while (nor_flash -> lx_nor_flash_free_physical_sectors <= nor_flash -> lx_nor_flash_physical_sectors_per_block)
213         {
214 
215             /* Attempt to reclaim one physical block.  */
216             _lx_nor_flash_block_reclaim(nor_flash);
217 
218             /* Increment the block count.  */
219             i++;
220 
221             /* Have we exceeded the number of blocks in the system?  */
222             if (i >= nor_flash -> lx_nor_flash_total_blocks)
223             {
224 
225                 /* Yes, break out of the loop.  */
226                 break;
227             }
228         }
229 
230         /* Set the status to success.  */
231         status =  LX_SUCCESS;
232     }
233     else
234     {
235 
236         /* Could not find the logical sector.  */
237         status =  LX_SECTOR_NOT_FOUND;
238     }
239 
240 #ifdef LX_THREAD_SAFE_ENABLE
241 
242     /* Release the thread safe mutex.  */
243     tx_mutex_put(&nor_flash -> lx_nor_flash_mutex);
244 #endif
245 
246     /* Return status.  */
247     return(status);
248 }
249 
250