GCC Code Coverage Report


Directory: common/src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 72.7% 48 / 0 / 66
Functions: 100.0% 1 / 0 / 1
Branches: 64.3% 54 / 0 / 84

lx_nand_flash_format_extended.c
Line Branch Exec Source
1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 * Copyright (c) 2026-present Eclipse ThreadX contributors
4 * Copyright (c) 2025 STMicroelectronics
5 *
6 * This program and the accompanying materials are made available under the
7 * terms of the MIT License which is available at
8 * https://opensource.org/licenses/MIT.
9 *
10 * SPDX-License-Identifier: MIT
11 **************************************************************************/
12
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_format_extended PORTABLE C */
44 /* */
45 /* AUTHOR */
46 /* */
47 /* Xiuwen Cai, Microsoft Corporation */
48 /* */
49 /* DESCRIPTION */
50 /* */
51 /* This function erases and formats a NAND flash. */
52 /* */
53 /* INPUT */
54 /* */
55 /* nand_flash NAND flash instance */
56 /* name Name of NAND flash instance */
57 /* nand_driver_initialize Driver initialize */
58 /* nand_driver_info_ptr Driver user data pointer */
59 /* memory_ptr Pointer to memory used by the */
60 /* LevelX for this NAND. */
61 /* memory_size Size of memory - must at least*/
62 /* 7 * total block count + */
63 /* 2 * page size */
64 /* */
65 /* OUTPUT */
66 /* */
67 /* return status */
68 /* */
69 /* CALLS */
70 /* */
71 /* (nand_driver_initialize) Driver initialize */
72 /* LX_MEMSET Initialize memory */
73 /* _lx_nand_flash_memory_initialize Initialize buffer */
74 /* _lx_nand_flash_driver_block_status_get */
75 /* Driver block status get */
76 /* _lx_nand_flash_driver_block_status_set */
77 /* Driver block status set */
78 /* _lx_nand_flash_metadata_build Build metadata */
79 /* _lx_nand_flash_metadata_write Write metadata */
80 /* _lx_nand_flash_driver_block_erase Driver block erase */
81 /* _lx_nand_flash_system_error System error handler */
82 /* tx_mutex_create Create thread-safe mutex */
83 /* */
84 /* CALLED BY */
85 /* */
86 /* Application Code */
87 /* */
88 /**************************************************************************/
89 40 UINT _lx_nand_flash_format_extended(LX_NAND_FLASH* nand_flash, CHAR* name,
90 UINT(*nand_driver_initialize)(LX_NAND_FLASH*),VOID* nand_driver_info_ptr,
91 ULONG* memory_ptr, UINT memory_size)
92 {
93
94 ULONG block;
95 UCHAR block_status;
96 UINT status;
97 UCHAR *page_buffer_ptr;
98
99 LX_PARAMETER_NOT_USED(name);
100
101 /* Clear the NAND flash control block. User extension is not cleared. */
102
2/2
✓ Branch 4 → 3 taken 8720 times.
✓ Branch 4 → 5 taken 28 times.
8760 LX_MEMSET(nand_flash, 0, (ULONG)((UCHAR*)&(nand_flash -> lx_nand_flash_open_previous) - (UCHAR*)nand_flash) + sizeof(nand_flash -> lx_nand_flash_open_previous));
103
104 40 nand_flash -> lx_nand_flash_driver_info_ptr = nand_driver_info_ptr;
105 /* Call the flash driver's initialization function. */
106 40 (nand_driver_initialize)(nand_flash);
107
108 /* Determine if we can support this NAND flash size. */
109
4/8
✓ Branch 3 → 4 taken 12 times.
✗ Branch 3 → 5 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 12 times.
✓ Branch 6 → 7 taken 28 times.
✗ Branch 6 → 8 not taken.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 28 times.
40 if (nand_flash -> lx_nand_flash_pages_per_block > LX_NAND_MAX_PAGE_PER_BLOCK || nand_flash -> lx_nand_flash_total_blocks > LX_NAND_MAX_BLOCK_COUNT)
110 {
111 ✗ return(LX_ERROR);
112 }
113
114 /* Check if it is new LevelX NAND driver. */
115
6/12
✓ Branch 6 → 7 taken 12 times.
✗ Branch 6 → 9 not taken.
✓ Branch 7 → 8 taken 12 times.
✗ Branch 7 → 9 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 12 times.
✓ Branch 9 → 10 taken 28 times.
✗ Branch 9 → 12 not taken.
✓ Branch 10 → 11 taken 28 times.
✗ Branch 10 → 12 not taken.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 28 times.
40 if (nand_flash -> lx_nand_flash_driver_pages_read == LX_NULL || nand_flash -> lx_nand_flash_driver_pages_write == LX_NULL || nand_flash -> lx_nand_flash_driver_pages_copy == LX_NULL)
116 {
117 ✗ return(LX_ERROR);
118 }
119
120 /* Check the spare data length. */
121
2/4
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 12 times.
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 28 times.
40 if (nand_flash -> lx_nand_flash_spare_data1_length < sizeof(ULONG))
122 {
123 ✗ return(LX_ERROR);
124 }
125
126 /* Calculate the number of words per block and per page. */
127 40 nand_flash -> lx_nand_flash_words_per_page = (nand_flash -> lx_nand_flash_bytes_per_page / sizeof(ULONG));
128 40 nand_flash -> lx_nand_flash_words_per_block = (nand_flash -> lx_nand_flash_words_per_page * nand_flash -> lx_nand_flash_pages_per_block);
129
130 /* Calculate the total pages. */
131 40 nand_flash -> lx_nand_flash_total_pages = nand_flash -> lx_nand_flash_total_blocks * nand_flash -> lx_nand_flash_pages_per_block;
132
133 /* Initialize memory buffer. */
134 40 status = _lx_nand_flash_memory_initialize(nand_flash, memory_ptr, memory_size);
135
2/4
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 12 times.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 28 times.
40 if (status != LX_SUCCESS)
136 {
137 ✗ return(status);
138 }
139
140 /* Initialize block numbers. */
141 40 nand_flash -> lx_nand_flash_metadata_block_number = LX_NAND_BLOCK_UNMAPPED;
142 40 nand_flash -> lx_nand_flash_metadata_block_number_next = LX_NAND_BLOCK_UNMAPPED;
143 40 nand_flash -> lx_nand_flash_backup_metadata_block_number = LX_NAND_BLOCK_UNMAPPED;
144 40 nand_flash -> lx_nand_flash_backup_metadata_block_number_next = LX_NAND_BLOCK_UNMAPPED;
145
146 /* Initialize the block status buffer. */
147
2/2
✓ Branch 20 → 19 taken 57344 times.
✓ Branch 20 → 21 taken 28 times.
57384 LX_MEMSET(nand_flash -> lx_nand_flash_block_status_table, 0xFF, nand_flash -> lx_nand_flash_block_status_table_size);
148
149 /* Loop through the blocks to check for bad blocks and determine the minimum and maximum erase count for each good block. */
150
4/4
✓ Branch 38 → 16 taken 12288 times.
✓ Branch 38 → 39 taken 12 times.
✓ Branch 44 → 22 taken 28672 times.
✓ Branch 44 → 45 taken 28 times.
41000 for (block = 0; block < nand_flash -> lx_nand_flash_total_blocks; block++)
151 {
152
153 /* First, check to make sure this block is good. */
154 40960 status = _lx_nand_flash_driver_block_status_get(nand_flash, block, &block_status);
155
156 /* Check for an error from flash driver. */
157
2/4
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 20 taken 12288 times.
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 26 taken 28672 times.
40960 if (status)
158 {
159
160 /* Call system error handler. */
161 ✗ _lx_nand_flash_system_error(nand_flash, status, block, 0);
162
163 /* Return an error. */
164 ✗ return(LX_ERROR);
165 }
166
167 /* Is this block bad? */
168
2/4
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 12288 times.
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 28 taken 28672 times.
40960 if (block_status != LX_NAND_GOOD_BLOCK)
169 {
170
171 /* Yes, this block is bad. */
172
173 /* Increment the number of bad blocks. */
174 ✗ nand_flash -> lx_nand_flash_bad_blocks++;
175
176 /* Save the block status. */
177 ✗ nand_flash -> lx_nand_flash_block_status_table[block] = LX_NAND_BLOCK_STATUS_BAD;
178
179 /* Continue to the next block. */
180 ✗ continue;
181 }
182
183 /* Erase the block. */
184 40960 status = _lx_nand_flash_driver_block_erase(nand_flash, block, 0);
185
186 /* Check for an error from flash driver. */
187
2/4
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 29 taken 12288 times.
✗ Branch 29 → 30 not taken.
✓ Branch 29 → 35 taken 28672 times.
40960 if (status)
188 {
189
190 /* Call system error handler. */
191 ✗ _lx_nand_flash_system_error(nand_flash, status, block, 0);
192
193 /* Attempt to mark this block as bad. */
194 ✗ status = _lx_nand_flash_driver_block_status_set(nand_flash, block, LX_NAND_BAD_BLOCK);
195
196 /* Check for error in setting the block status. */
197 ✗ if (status)
198 {
199
200 /* Call system error handler. */
201 ✗ _lx_nand_flash_system_error(nand_flash, status, block, 0);
202 }
203
204 /* Increment the bad block count. */
205 ✗ nand_flash -> lx_nand_flash_bad_blocks++;
206
207 /* Save the block status. */
208 ✗ nand_flash -> lx_nand_flash_block_status_table[block] = LX_NAND_BLOCK_STATUS_BAD;
209 }
210 else
211 {
212
213 /* Allocate blocks for metadata. */
214
4/4
✓ Branch 29 → 30 taken 12 times.
✓ Branch 29 → 31 taken 12276 times.
✓ Branch 35 → 36 taken 28 times.
✓ Branch 35 → 37 taken 28644 times.
40960 if (nand_flash -> lx_nand_flash_metadata_block_number == LX_NAND_BLOCK_UNMAPPED)
215 {
216 40 nand_flash -> lx_nand_flash_metadata_block_number = block;
217 40 nand_flash -> lx_nand_flash_metadata_block_number_current = block;
218 }
219
4/4
✓ Branch 31 → 32 taken 12 times.
✓ Branch 31 → 33 taken 12264 times.
✓ Branch 37 → 38 taken 28 times.
✓ Branch 37 → 39 taken 28616 times.
40920 else if (nand_flash -> lx_nand_flash_backup_metadata_block_number == LX_NAND_BLOCK_UNMAPPED)
220 {
221 40 nand_flash -> lx_nand_flash_backup_metadata_block_number = block;
222 40 nand_flash -> lx_nand_flash_backup_metadata_block_number_current = block;
223 }
224
4/4
✓ Branch 33 → 34 taken 12 times.
✓ Branch 33 → 35 taken 12252 times.
✓ Branch 39 → 40 taken 28 times.
✓ Branch 39 → 41 taken 28588 times.
40880 else if (nand_flash -> lx_nand_flash_metadata_block_number_next == LX_NAND_BLOCK_UNMAPPED)
225 {
226 40 nand_flash -> lx_nand_flash_metadata_block_number_next = block;
227 }
228
4/4
✓ Branch 35 → 36 taken 12 times.
✓ Branch 35 → 37 taken 12240 times.
✓ Branch 41 → 42 taken 28 times.
✓ Branch 41 → 43 taken 28560 times.
40840 else if (nand_flash -> lx_nand_flash_backup_metadata_block_number_next == LX_NAND_BLOCK_UNMAPPED)
229 {
230 40 nand_flash -> lx_nand_flash_backup_metadata_block_number_next = block;
231 }
232 }
233 }
234
235 /* There should be enough blocks for metadata. */
236
2/4
✗ Branch 39 → 40 not taken.
✓ Branch 39 → 41 taken 12 times.
✗ Branch 45 → 46 not taken.
✓ Branch 45 → 47 taken 28 times.
40 if (nand_flash -> lx_nand_flash_backup_metadata_block_number_next == LX_NAND_BLOCK_UNMAPPED)
237 {
238 ✗ return (LX_NO_BLOCKS);
239 }
240
241 /* Save the block status for metadata. */
242 40 nand_flash -> lx_nand_flash_block_status_table[nand_flash -> lx_nand_flash_backup_metadata_block_number_next] = LX_NAND_BLOCK_STATUS_ALLOCATED;
243 40 nand_flash -> lx_nand_flash_block_status_table[nand_flash -> lx_nand_flash_metadata_block_number_next] = LX_NAND_BLOCK_STATUS_ALLOCATED;
244 40 nand_flash -> lx_nand_flash_block_status_table[nand_flash -> lx_nand_flash_backup_metadata_block_number] = (USHORT)nand_flash -> lx_nand_flash_backup_metadata_block_number_next;
245 40 nand_flash -> lx_nand_flash_block_status_table[nand_flash -> lx_nand_flash_metadata_block_number] = (USHORT)nand_flash -> lx_nand_flash_metadata_block_number_next;
246
247 /* Initialize the mapping table. */
248
2/2
✓ Branch 49 → 48 taken 57344 times.
✓ Branch 49 → 50 taken 28 times.
57384 LX_MEMSET(nand_flash -> lx_nand_flash_block_mapping_table, 0xFF, nand_flash -> lx_nand_flash_block_mapping_table_size);
249
250 /* Build initial metadata. */
251 40 status = _lx_nand_flash_metadata_build(nand_flash);
252
2/4
✗ Branch 42 → 43 not taken.
✓ Branch 42 → 44 taken 12 times.
✗ Branch 51 → 52 not taken.
✓ Branch 51 → 53 taken 28 times.
40 if (status != LX_SUCCESS)
253 {
254 /* Return error status. */
255 ✗ return(status);
256 }
257
258 /* Get buffer for page data. */
259 40 page_buffer_ptr = nand_flash -> lx_nand_flash_page_buffer;
260
261 /* Initialize the page buffer. */
262
2/2
✓ Branch 55 → 54 taken 14336 times.
✓ Branch 55 → 56 taken 28 times.
14376 LX_MEMSET(page_buffer_ptr, 0xFF, nand_flash -> lx_nand_flash_bytes_per_page);
263
264 /* Set the next block numbers. */
265 40 LX_UTILITY_LONG_SET(&page_buffer_ptr[LX_NAND_BLOCK_LINK_MAIN_METADATA_OFFSET], nand_flash -> lx_nand_flash_metadata_block_number_next);
266 40 LX_UTILITY_LONG_SET(&page_buffer_ptr[LX_NAND_BLOCK_LINK_BACKUP_METADATA_OFFSET], nand_flash -> lx_nand_flash_backup_metadata_block_number_next);
267
268 /* Save the next block numbers to metadata block. */
269 40 status = _lx_nand_flash_metadata_write(nand_flash, page_buffer_ptr, LX_NAND_PAGE_TYPE_BLOCK_LINK);
270
271
2/4
✗ Branch 45 → 46 not taken.
✓ Branch 45 → 47 taken 12 times.
✗ Branch 57 → 58 not taken.
✓ Branch 57 → 59 taken 28 times.
40 if (status != LX_SUCCESS)
272 {
273 /* Return error status. */
274 ✗ return(status);
275 }
276
277 /* Return a successful completion. */
278 40 return(LX_SUCCESS);
279 }
280
281