GCC Code Coverage Report


Directory: common/src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 86.4% 38 / 0 / 44
Functions: 100.0% 1 / 0 / 1
Branches: 78.1% 25 / 0 / 32

lx_nand_flash_data_page_copy.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
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** LevelX Component */
17 /** */
18 /** NAND 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_nand_flash_data_page_copy PORTABLE C */
43 /* 6.4.0 */
44 /* AUTHOR */
45 /* */
46 /* Xiuwen Cai, Microsoft Corporation */
47 /* */
48 /* DESCRIPTION */
49 /* */
50 /* This function copies logical sectors into new block. */
51 /* */
52 /* INPUT */
53 /* */
54 /* nand_flash NAND flash instance */
55 /* logical_sector Logical sector number */
56 /* source_block Source block number */
57 /* src_block_status Source block status */
58 /* destination_block Destination block number */
59 /* dest_block_status_ptr Pointer to destination block */
60 /* status */
61 /* sectors Number of sectors to copy */
62 /* */
63 /* OUTPUT */
64 /* */
65 /* return status */
66 /* */
67 /* CALLS */
68 /* */
69 /* lx_nand_flash_driver_pages_copy Driver pages copy */
70 /* lx_nand_flash_driver_pages_read Driver pages read */
71 /* _lx_nand_flash_system_error Internal system error handler */
72 /* */
73 /* CALLED BY */
74 /* */
75 /* Internal LevelX */
76 /* */
77 /**************************************************************************/
78 22780 UINT _lx_nand_flash_data_page_copy(LX_NAND_FLASH* nand_flash, ULONG logical_sector, ULONG source_block, USHORT src_block_status,
79 ULONG destination_block, USHORT* dest_block_status_ptr, ULONG sectors)
80 {
81
82 LONG source_page;
83 ULONG destination_page;
84 22780 UINT status = LX_SUCCESS;
85 UINT i;
86 ULONG available_pages;
87 ULONG spare_data1;
88 UCHAR *spare_buffer_ptr;
89 ULONG dest_block_status;
90 ULONG number_of_pages;
91
92
93 /* Get the destination block status. */
94 22780 dest_block_status = *dest_block_status_ptr;
95
96 /* Get the current page number of the destination block. */
97 22780 destination_page = dest_block_status & LX_NAND_BLOCK_STATUS_PAGE_NUMBER_MASK;
98
99 /* Get the available pages in the source block. */
100
1/2
✓ Branch 2 → 3 taken 22780 times.
✗ Branch 2 → 4 not taken.
22780 available_pages = (src_block_status & LX_NAND_BLOCK_STATUS_FULL) ? (nand_flash -> lx_nand_flash_pages_per_block) : (src_block_status & LX_NAND_BLOCK_STATUS_PAGE_NUMBER_MASK);
101
102 /* Check if pages in the source block are sequential. */
103
2/2
✓ Branch 5 → 6 taken 560 times.
✓ Branch 5 → 27 taken 22220 times.
22780 if (src_block_status & LX_NAND_BLOCK_STATUS_NON_SEQUENTIAL)
104 {
105
106 /* Get buffer for spare data. */
107 560 spare_buffer_ptr = nand_flash -> lx_nand_flash_page_buffer + nand_flash -> lx_nand_flash_bytes_per_page;
108
109 /* Loop to copy the data. */
110
2/2
✓ Branch 26 → 7 taken 71400 times.
✓ Branch 26 → 42 taken 560 times.
71960 for (i = 0; i < sectors; i++)
111 {
112
113 /* Loop to search the page. */
114
2/2
✓ Branch 24 → 8 taken 9878160 times.
✓ Branch 24 → 25 taken 6260 times.
9884420 for (source_page = (LONG)(available_pages - 1); source_page >= 0; source_page--)
115 {
116
117 /* Read one page. */
118 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
119 987816 status = (nand_flash -> lx_nand_flash_driver_pages_read)(nand_flash, source_block, (ULONG)source_page, LX_NULL, spare_buffer_ptr, 1);
120 #else
121 8890344 status = (nand_flash -> lx_nand_flash_driver_pages_read)(source_block, (ULONG)source_page, LX_NULL, spare_buffer_ptr, 1);
122 #endif
123
124 /* Check for an error from flash driver. */
125
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 12 taken 9878160 times.
9878160 if (status)
126 {
127
128 /* Call system error handler. */
129 ✗ _lx_nand_flash_system_error(nand_flash, status, source_block, 0);
130
131 /* Return an error. */
132 ✗ return(LX_ERROR);
133 }
134
135 /* Get the spare data. */
136 9878160 spare_data1 = LX_UTILITY_LONG_GET(&spare_buffer_ptr[nand_flash -> lx_nand_flash_spare_data1_offset]);
137
138 /* Check the address match. */
139
2/2
✓ Branch 12 → 13 taken 65140 times.
✓ Branch 12 → 23 taken 9813020 times.
9878160 if ((spare_data1 & LX_NAND_PAGE_TYPE_USER_DATA_MASK) == (logical_sector + i))
140 {
141
142 /* Check if the page contains valid data. */
143
2/2
✓ Branch 13 → 14 taken 65130 times.
✓ Branch 13 → 22 taken 10 times.
65140 if ((spare_data1 & (~LX_NAND_PAGE_TYPE_USER_DATA_MASK)) == (LX_NAND_PAGE_TYPE_USER_DATA))
144 {
145
146 /* Call the driver to copy the page. */
147 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
148 6513 status = (nand_flash -> lx_nand_flash_driver_pages_copy)(nand_flash, source_block, (ULONG)source_page, destination_block, destination_page, 1, nand_flash -> lx_nand_flash_page_buffer);
149 #else
150 58617 status = (nand_flash -> lx_nand_flash_driver_pages_copy)(source_block, (ULONG)source_page, destination_block, destination_page, 1, nand_flash -> lx_nand_flash_page_buffer);
151 #endif
152
153 /* Check for an error from flash driver. */
154
1/2
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 18 taken 65130 times.
65130 if (status)
155 {
156
157 /* Call system error handler. */
158 ✗ _lx_nand_flash_system_error(nand_flash, status, source_block, 0);
159
160 /* Return an error. */
161 ✗ return(LX_ERROR);
162 }
163
164 /* Check if the pages in destination block is still sequential. */
165
2/2
✓ Branch 18 → 19 taken 2530 times.
✓ Branch 18 → 20 taken 62600 times.
65130 if (destination_page != ((logical_sector + i) % nand_flash -> lx_nand_flash_pages_per_block))
166 {
167 /* Mark the block status as non sequential. */
168 2530 dest_block_status |= LX_NAND_BLOCK_STATUS_NON_SEQUENTIAL;
169 }
170
171 /* Update the available pages. */
172 65130 destination_page++;
173
174 /* Check if available page count reaches pages per block. */
175
2/2
✓ Branch 20 → 21 taken 50 times.
✓ Branch 20 → 22 taken 65080 times.
65130 if (destination_page == nand_flash -> lx_nand_flash_pages_per_block)
176 {
177
178 /* Set block full flag. */
179 50 dest_block_status |= LX_NAND_BLOCK_STATUS_FULL;
180 }
181 }
182 65140 break;
183 }
184 }
185 }
186 }
187 else
188 {
189
190 /* Get the source page number. */
191 22220 source_page = (LONG)(logical_sector % nand_flash -> lx_nand_flash_pages_per_block);
192
193 /* Check if the page to copy is greater than the available pages. */
194 44440 number_of_pages = ((ULONG)source_page + sectors) > available_pages ?
195
1/4
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 32 taken 22220 times.
✗ Branch 28 → 29 not taken.
✗ Branch 28 → 30 not taken.
22220 (available_pages > (ULONG)source_page ? available_pages - (ULONG)source_page : 0) : sectors;
196
197 /* Check if there is any pages to be copied. */
198
2/2
✓ Branch 33 → 34 taken 22180 times.
✓ Branch 33 → 42 taken 40 times.
22220 if (number_of_pages)
199 {
200
201 /* Call the driver to copy pages. */
202 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
203 2218 status = (nand_flash -> lx_nand_flash_driver_pages_copy)(nand_flash, source_block, (ULONG)source_page, destination_block, destination_page, number_of_pages, nand_flash -> lx_nand_flash_page_buffer);
204 #else
205 19962 status = (nand_flash -> lx_nand_flash_driver_pages_copy)(source_block, (ULONG)source_page, destination_block, destination_page, number_of_pages, nand_flash -> lx_nand_flash_page_buffer);
206 #endif
207
208 /* Check for an error from flash driver. */
209
1/2
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 38 taken 22180 times.
22180 if (status)
210 {
211
212 /* Call system error handler. */
213 ✗ _lx_nand_flash_system_error(nand_flash, status, source_block, 0);
214
215 /* Return an error. */
216 ✗ return(LX_ERROR);
217 }
218
219 /* Check if the pages in destination block is still sequential. */
220
2/2
✓ Branch 38 → 39 taken 10 times.
✓ Branch 38 → 40 taken 22170 times.
22180 if ((ULONG)source_page != destination_page)
221 {
222
223 /* Mark the block status as non sequential. */
224 10 dest_block_status |= LX_NAND_BLOCK_STATUS_NON_SEQUENTIAL;
225 }
226
227 /* Update the available pages. */
228 22180 destination_page += number_of_pages;
229
230 /* Check if available page count reaches pages per block. */
231
2/2
✓ Branch 40 → 41 taken 11070 times.
✓ Branch 40 → 42 taken 11110 times.
22180 if (destination_page == nand_flash -> lx_nand_flash_pages_per_block)
232 {
233
234 /* Set block full flag. */
235 11070 dest_block_status |= LX_NAND_BLOCK_STATUS_FULL;
236 }
237 }
238 }
239
240 /* Return the block status. */
241 22780 *dest_block_status_ptr = (USHORT)(destination_page | (dest_block_status & ~LX_NAND_BLOCK_STATUS_PAGE_NUMBER_MASK));
242
243 /* Return status. */
244 22780 return(status);
245 }
246
247