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_sector_read PORTABLE C */
42 /* 6.3.0 */
43 /* AUTHOR */
44 /* */
45 /* William E. Lamie, Microsoft Corporation */
46 /* */
47 /* DESCRIPTION */
48 /* */
49 /* This function reads a logical sector from NOR flash. */
50 /* */
51 /* INPUT */
52 /* */
53 /* nor_flash NOR flash instance */
54 /* logical_sector Logical sector number */
55 /* buffer Pointer to buffer to read into*/
56 /* (the size is 512 bytes) */
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_logical_sector_find Find logical sector */
67 /* _lx_nor_flash_physical_sector_allocate */
68 /* Allocate new logical sector */
69 /* _lx_nor_flash_system_error Internal system error handler */
70 /* tx_mutex_get Get thread protection */
71 /* tx_mutex_put Release thread protection */
72 /* */
73 /* CALLED BY */
74 /* */
75 /* Application Code */
76 /* */
77 /* RELEASE HISTORY */
78 /* */
79 /* DATE NAME DESCRIPTION */
80 /* */
81 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
82 /* 09-30-2020 William E. Lamie Modified comment(s), */
83 /* resulting in version 6.1 */
84 /* 06-02-2021 Bhupendra Naphade Modified comment(s), */
85 /* resulting in version 6.1.7 */
86 /* 10-31-2023 Xiuwen Cai Modified comment(s), */
87 /* added mapping bitmap cache, */
88 /* resulting in version 6.3.0 */
89 /* */
90 /**************************************************************************/
_lx_nor_flash_sector_read(LX_NOR_FLASH * nor_flash,ULONG logical_sector,VOID * buffer)91 UINT _lx_nor_flash_sector_read(LX_NOR_FLASH *nor_flash, ULONG logical_sector, VOID *buffer)
92 {
93
94 UINT status;
95 ULONG *mapping_address;
96 ULONG mapping_entry;
97 ULONG *sector_address;
98
99
100 #ifdef LX_THREAD_SAFE_ENABLE
101
102 /* Obtain the thread safe mutex. */
103 tx_mutex_get(&nor_flash -> lx_nor_flash_mutex, TX_WAIT_FOREVER);
104 #endif
105
106 /* Increment the number of read requests. */
107 nor_flash -> lx_nor_flash_read_requests++;
108
109 /* See if we can find the sector in the current mapping. */
110 _lx_nor_flash_logical_sector_find(nor_flash, logical_sector, LX_FALSE, &mapping_address, §or_address);
111
112 /* Determine if the logical sector was found. */
113 if (mapping_address)
114 {
115
116 /* Yes, we were able to find the logical sector. */
117
118 /* Read the sector data from the physical sector. */
119 status = _lx_nor_flash_driver_read(nor_flash, sector_address, buffer, LX_NOR_SECTOR_SIZE);
120
121 /* Check for an error from flash driver. Drivers should never return an error.. */
122 if (status)
123 {
124
125 /* Call system error handler. */
126 _lx_nor_flash_system_error(nor_flash, status);
127
128 /* Adjust return status. */
129 status = LX_ERROR;
130 }
131 else
132 {
133
134 /* Set the status to success. */
135 status = LX_SUCCESS;
136 }
137 }
138 else
139 {
140
141 /* Allocate a new physical sector for this write. */
142 _lx_nor_flash_physical_sector_allocate(nor_flash, logical_sector, &mapping_address, §or_address);
143
144 /* Determine if the new sector allocation was successful. */
145 if (mapping_address)
146 {
147
148 /* Update the number of free physical sectors. */
149 nor_flash -> lx_nor_flash_free_physical_sectors--;
150
151 /* Read the sector data from the physical sector. */
152 status = _lx_nor_flash_driver_read(nor_flash, sector_address, buffer, LX_NOR_SECTOR_SIZE);
153
154 /* Check for an error from flash driver. Drivers should never return an error.. */
155 if (status)
156 {
157
158 /* Call system error handler. */
159 _lx_nor_flash_system_error(nor_flash, status);
160 }
161
162 /* Now build the new mapping entry. */
163 mapping_entry = ((ULONG) LX_NOR_PHYSICAL_SECTOR_VALID) | ((ULONG) LX_NOR_PHYSICAL_SECTOR_SUPERCEDED) | logical_sector;
164
165 /* Write out the new mapping entry. */
166 status = _lx_nor_flash_driver_write(nor_flash, mapping_address, &mapping_entry, 1);
167
168 /* Check for an error from flash driver. Drivers should never return an error.. */
169 if (status)
170 {
171
172 /* Call system error handler. */
173 _lx_nor_flash_system_error(nor_flash, status);
174
175 #ifdef LX_THREAD_SAFE_ENABLE
176
177 /* Release the thread safe mutex. */
178 tx_mutex_put(&nor_flash -> lx_nor_flash_mutex);
179 #endif
180
181 /* Return status. */
182 return(LX_ERROR);
183 }
184 #ifndef LX_NOR_DISABLE_EXTENDED_CACHE
185 #ifdef LX_NOR_ENABLE_MAPPING_BITMAP
186
187 /* Determine if the logical sector is within the mapping bitmap. */
188 if (logical_sector < nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap_max_logical_sector)
189 {
190
191 /* Set the bit in the mapping bitmap. */
192 nor_flash -> lx_nor_flash_extended_cache_mapping_bitmap[logical_sector >> 5] |= (ULONG)(1 << (logical_sector & 31));
193 }
194 #endif
195 #endif
196
197 /* Increment the number of mapped physical sectors. */
198 nor_flash -> lx_nor_flash_mapped_physical_sectors++;
199
200 /* Set the status to success. */
201 status = LX_SUCCESS;
202 }
203 else
204 {
205
206 /* Could not find the logical sector. */
207 status = LX_SECTOR_NOT_FOUND;
208 }
209 }
210
211 #ifdef LX_THREAD_SAFE_ENABLE
212
213 /* Release the thread safe mutex. */
214 tx_mutex_put(&nor_flash -> lx_nor_flash_mutex);
215 #endif
216
217 /* Return status. */
218 return(status);
219 }
220
221