GCC Code Coverage Report


Directory: common/src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 70.5% 31 / 0 / 44
Functions: 100.0% 1 / 0 / 1
Branches: 75.0% 36 / 0 / 48

lx_nand_flash_sector_read.c
Line Branch Exec Source
1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 * Copyright (c) 2026-present Eclipse ThreadX contributors
4 *
5 * This program and the accompanying materials are made available under the
6 * terms of the MIT License which is available at
7 * https://opensource.org/licenses/MIT.
8 *
9 * SPDX-License-Identifier: MIT
10 **************************************************************************/
11
12 // Portions of this file were generated with AI assistance.
13
14 /**************************************************************************/
15 /**************************************************************************/
16 /** */
17 /** LevelX Component */
18 /** */
19 /** NAND Flash */
20 /** */
21 /**************************************************************************/
22 /**************************************************************************/
23
24 #define LX_SOURCE_CODE
25
26
27 /* Disable ThreadX error checking. */
28
29 #ifndef LX_DISABLE_ERROR_CHECKING
30 #define LX_DISABLE_ERROR_CHECKING
31 #endif
32
33
34 /* Include necessary system files. */
35
36 #include "lx_api.h"
37
38
39 /**************************************************************************/
40 /* */
41 /* FUNCTION RELEASE */
42 /* */
43 /* _lx_nand_flash_sector_read PORTABLE C */
44 /* 6.2.1 */
45 /* AUTHOR */
46 /* */
47 /* Xiuwen Cai, Microsoft Corporation */
48 /* */
49 /* DESCRIPTION */
50 /* */
51 /* This function reads a logical sector from NAND flash. */
52 /* */
53 /* INPUT */
54 /* */
55 /* nand_flash NAND flash instance */
56 /* logical_sector Logical sector number */
57 /* buffer Pointer to buffer to read into*/
58 /* (the size is number of */
59 /* bytes in a page) */
60 /* */
61 /* OUTPUT */
62 /* */
63 /* return status */
64 /* */
65 /* CALLS */
66 /* */
67 /* _lx_nand_flash_block_find Find the mapped block */
68 /* lx_nand_flash_driver_pages_read Read pages */
69 /* _lx_nand_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 /**************************************************************************/
78 475860 UINT _lx_nand_flash_sector_read(LX_NAND_FLASH *nand_flash, ULONG logical_sector, VOID *buffer)
79 {
80
81 UINT status;
82 ULONG i;
83 ULONG *word_ptr;
84 ULONG block;
85 USHORT block_status;
86 UCHAR *spare_buffer_ptr;
87 ULONG available_pages;
88 LONG page;
89
90 #ifdef LX_THREAD_SAFE_ENABLE
91
92 /* Obtain the thread safe mutex. */
93 47586 tx_mutex_get(&nand_flash -> lx_nand_flash_mutex, TX_WAIT_FOREVER);
94 #endif
95
96 /* Increment the number of read requests. */
97 475860 nand_flash -> lx_nand_flash_diagnostic_sector_read_requests++;
98
99 /* See if we can find the sector in the current mapping. */
100 475860 status = _lx_nand_flash_block_find(nand_flash, logical_sector, &block, &block_status);
101
102 /* Check return status. */
103
2/4
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 7 taken 428274 times.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 9 taken 47586 times.
475860 if (status != LX_SUCCESS)
104 {
105
106 /* Call system error handler. */
107 ✗ _lx_nand_flash_system_error(nand_flash, status, block, 0);
108
109 /* Determine if the error is fatal. */
110 ✗ if (status != LX_NAND_ERROR_CORRECTED)
111 {
112 #ifdef LX_THREAD_SAFE_ENABLE
113
114 /* Release the thread safe mutex. */
115 ✗ tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
116 #endif
117 /* Return an error. */
118 ✗ return(LX_ERROR);
119 }
120 }
121
122 /* Determine if the block is mapped. */
123
4/4
✓ Branch 7 → 8 taken 48033 times.
✓ Branch 7 → 31 taken 380241 times.
✓ Branch 9 → 10 taken 5337 times.
✓ Branch 9 → 38 taken 42249 times.
475860 if (block != LX_NAND_BLOCK_UNMAPPED)
124 {
125
126 /* Setup spare buffer pointer. */
127 53370 spare_buffer_ptr = (UCHAR*)nand_flash -> lx_nand_flash_page_buffer;
128
129 /* Get available pages in this block. */
130
4/4
✓ Branch 8 → 9 taken 21951 times.
✓ Branch 8 → 10 taken 26082 times.
✓ Branch 10 → 11 taken 2439 times.
✓ Branch 10 → 12 taken 2898 times.
53370 available_pages = block_status & LX_NAND_BLOCK_STATUS_FULL ? nand_flash -> lx_nand_flash_pages_per_block : block_status & LX_NAND_BLOCK_STATUS_PAGE_NUMBER_MASK;
131
132 /* Determine if the pages are recorded sequentially. */
133
4/4
✓ Branch 11 → 12 taken 14895 times.
✓ Branch 11 → 25 taken 33138 times.
✓ Branch 13 → 14 taken 1655 times.
✓ Branch 13 → 30 taken 3682 times.
53370 if (block_status & LX_NAND_BLOCK_STATUS_NON_SEQUENTIAL)
134 {
135
136 /* Loop to search the logical page. */
137
4/4
✓ Branch 24 → 13 taken 1018836 times.
✓ Branch 24 → 31 taken 5751 times.
✓ Branch 29 → 15 taken 113204 times.
✓ Branch 29 → 38 taken 639 times.
1138430 for (page = (LONG)available_pages - 1; page >= 0; page--)
138 {
139
140 /* Read a page. */
141 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
142 113204 status = (nand_flash -> lx_nand_flash_driver_pages_read)(nand_flash, block, (ULONG)page, (UCHAR*)NULL, spare_buffer_ptr, 1);
143 #else
144 1018836 status = (nand_flash -> lx_nand_flash_driver_pages_read)(block, (ULONG)page, (UCHAR*)NULL, spare_buffer_ptr, 1);
145 #endif
146
147 /* Check for an error from flash driver. */
148
2/4
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 17 taken 1018836 times.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 20 taken 113204 times.
1132040 if (status)
149 {
150
151 /* Call system error handler. */
152 ✗ _lx_nand_flash_system_error(nand_flash, status, block, 0);
153 #ifdef LX_THREAD_SAFE_ENABLE
154
155 /* Release the thread safe mutex. */
156 ✗ tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
157 #endif
158 /* Return an error. */
159 ✗ return(LX_ERROR);
160 }
161
162 /* Get the logical sector number from spare bytes, and check if it matches the addressed sector number. */
163
4/4
✓ Branch 17 → 18 taken 9144 times.
✓ Branch 17 → 23 taken 1009692 times.
✓ Branch 20 → 21 taken 1016 times.
✓ Branch 20 → 28 taken 112188 times.
1132040 if ((LX_UTILITY_LONG_GET(&spare_buffer_ptr[nand_flash -> lx_nand_flash_spare_data1_offset]) & LX_NAND_PAGE_TYPE_USER_DATA_MASK) == logical_sector)
164 {
165 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
166 1016 status = (nand_flash -> lx_nand_flash_driver_pages_read)(nand_flash, block, (ULONG)page, (UCHAR*)buffer, NULL, 1);
167 #else
168 9144 status = (nand_flash -> lx_nand_flash_driver_pages_read)(block, (ULONG)page, (UCHAR*)buffer, NULL, 1);
169 #endif
170
171 /* Check for an error from flash driver. */
172
2/4
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 22 taken 9144 times.
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 26 taken 1016 times.
10160 if (status)
173 {
174
175 /* Call system error handler. */
176 ✗ _lx_nand_flash_system_error(nand_flash, status, block, 0);
177 #ifdef LX_THREAD_SAFE_ENABLE
178
179 /* Release the thread safe mutex. */
180 ✗ tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
181 #endif
182 /* Return an error. */
183 ✗ return(LX_ERROR);
184 }
185 #ifdef LX_THREAD_SAFE_ENABLE
186
187 /* Release the thread safe mutex. */
188 1016 tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
189 #endif
190 /* Return successful completion. */
191 10160 return(LX_SUCCESS);
192 }
193 }
194 }
195 else
196 {
197
198 /* Check if the logical sector is available. */
199
4/4
✓ Branch 25 → 26 taken 27756 times.
✓ Branch 25 → 31 taken 5382 times.
✓ Branch 30 → 31 taken 3084 times.
✓ Branch 30 → 38 taken 598 times.
36820 if (logical_sector % nand_flash -> lx_nand_flash_pages_per_block < available_pages)
200 {
201
202 /* Read a page. */
203 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
204 3084 status = (nand_flash -> lx_nand_flash_driver_pages_read)(nand_flash, block, logical_sector % nand_flash -> lx_nand_flash_pages_per_block, (UCHAR*)buffer, spare_buffer_ptr, 1);
205 #else
206 27756 status = (nand_flash -> lx_nand_flash_driver_pages_read)(block, logical_sector % nand_flash -> lx_nand_flash_pages_per_block, (UCHAR*)buffer, spare_buffer_ptr, 1);
207 #endif
208
209 /* Check for an error from flash driver. */
210
2/4
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 30 taken 27756 times.
✗ Branch 32 → 33 not taken.
✓ Branch 32 → 36 taken 3084 times.
30840 if (status)
211 {
212
213 /* Call system error handler. */
214 ✗ _lx_nand_flash_system_error(nand_flash, status, block, 0);
215
216 #ifdef LX_THREAD_SAFE_ENABLE
217
218 /* Release the thread safe mutex. */
219 ✗ tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
220 #endif
221 /* Return an error. */
222 ✗ return(LX_ERROR);
223 }
224 #ifdef LX_THREAD_SAFE_ENABLE
225
226 /* Release the thread safe mutex. */
227 3084 tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
228 #endif
229 /* Return successful completion. */
230 30840 return(LX_SUCCESS);
231 }
232 }
233 }
234
235 #ifdef LX_NAND_FLASH_ENABLE_LAZY_SECTOR_RELEASE
236 {
237
238 ULONG logical_group;
239 ULONG old_block;
240
241 /* Check the compaction table for a deferred source block that might hold
242 the requested sector. The primary block (tombstone block) was already
243 scanned above; fall back to the old full block here. */
244 logical_group = logical_sector / nand_flash -> lx_nand_flash_pages_per_block;
245
246 if (nand_flash -> lx_nand_flash_block_compaction_table[logical_group] != (USHORT)LX_NAND_BLOCK_UNMAPPED)
247 {
248
249 old_block = nand_flash -> lx_nand_flash_block_compaction_table[logical_group];
250
251 /* Set spare buffer pointer. */
252 spare_buffer_ptr = (UCHAR*)nand_flash -> lx_nand_flash_page_buffer;
253
254 /* The compaction-pending block is always FULL; scan all pages in reverse. */
255 for (page = (LONG)nand_flash -> lx_nand_flash_pages_per_block - 1; page >= 0; page--)
256 {
257
258 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
259 status = (nand_flash -> lx_nand_flash_driver_pages_read)(nand_flash, old_block, (ULONG)page, (UCHAR*)NULL, spare_buffer_ptr, 1);
260 #else
261 status = (nand_flash -> lx_nand_flash_driver_pages_read)(old_block, (ULONG)page, (UCHAR*)NULL, spare_buffer_ptr, 1);
262 #endif
263
264 /* Check for an error from flash driver. */
265 if (status)
266 {
267 _lx_nand_flash_system_error(nand_flash, status, old_block, 0);
268 #ifdef LX_THREAD_SAFE_ENABLE
269 tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
270 #endif
271 return(LX_ERROR);
272 }
273
274 /* Check if this page matches the requested sector. */
275 if ((LX_UTILITY_LONG_GET(&spare_buffer_ptr[nand_flash -> lx_nand_flash_spare_data1_offset]) & LX_NAND_PAGE_TYPE_USER_DATA_MASK) == logical_sector)
276 {
277
278 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
279 status = (nand_flash -> lx_nand_flash_driver_pages_read)(nand_flash, old_block, (ULONG)page, (UCHAR*)buffer, NULL, 1);
280 #else
281 status = (nand_flash -> lx_nand_flash_driver_pages_read)(old_block, (ULONG)page, (UCHAR*)buffer, NULL, 1);
282 #endif
283
284 /* Check for an error from flash driver. */
285 if (status)
286 {
287 _lx_nand_flash_system_error(nand_flash, status, old_block, 0);
288 #ifdef LX_THREAD_SAFE_ENABLE
289 tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
290 #endif
291 return(LX_ERROR);
292 }
293
294 #ifdef LX_THREAD_SAFE_ENABLE
295 tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
296 #endif
297 return(LX_SUCCESS);
298 }
299 }
300 }
301
302 }
303 #endif /* LX_NAND_FLASH_ENABLE_LAZY_SECTOR_RELEASE */
304
305 /* Sector hasn't been written. Simply fill the destination buffer with ones and return success. */
306
307 /* Setup pointer to users buffer. */
308 434860 word_ptr = (ULONG *) buffer;
309
310 /* Put all ones in he buffer. */
311
4/4
✓ Branch 33 → 32 taken 50095872 times.
✓ Branch 33 → 34 taken 391374 times.
✓ Branch 40 → 39 taken 5566208 times.
✓ Branch 40 → 41 taken 43486 times.
56096940 for (i = 0; i < nand_flash -> lx_nand_flash_words_per_page; i++)
312 {
313
314 /* Copy a word. */
315 55662080 *word_ptr++ = LX_ALL_ONES;
316 }
317
318 /* Set the status to success. */
319 434860 status = LX_SUCCESS;
320
321 #ifdef LX_THREAD_SAFE_ENABLE
322
323 /* Release the thread safe mutex. */
324 43486 tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
325 #endif
326
327 /* Return status. */
328 434860 return(status);
329 }
330
331