GCC Code Coverage Report


Directory: common/src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 79.7% 141 / 0 / 177
Functions: 75.0% 12 / 0 / 16
Branches: 70.0% 49 / 0 / 70

lx_nand_flash_simulator.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 Simulator */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23
24 /* Include necessary files. */
25
26 #include "lx_api.h"
27
28 /* Define constants for the NAND flash simulation. */
29
30 #define TOTAL_BLOCKS 1024
31 #define PHYSICAL_PAGES_PER_BLOCK 256 /* Min value of 2 */
32 #define BYTES_PER_PHYSICAL_PAGE 512 /* 512 bytes per page */
33 #define WORDS_PER_PHYSICAL_PAGE 512 / 4 /* Words per page */
34 #define SPARE_BYTES_PER_PAGE 16 /* 16 "spare" bytes per page */
35 /* For 2048 byte block spare area: */
36 #define BAD_BLOCK_POSITION 0 /* 0 is the bad block byte postion */
37 #define EXTRA_BYTE_POSITION 0 /* 0 is the extra bytes starting byte postion */
38 #define ECC_BYTE_POSITION 8 /* 8 is the ECC starting byte position */
39 #define SPARE_DATA1_OFFSET 4
40 #define SPARE_DATA1_LENGTH 4
41 #define SPARE_DATA2_OFFSET 2
42 #define SPARE_DATA2_LENGTH 2
43
44
45
46 /* Definition of the spare area is relative to the block size of the NAND part and perhaps manufactures of the NAND part.
47 Here are some common definitions:
48
49 256 Byte Block
50
51 Bytes Meaning
52
53 0,1,2 ECC bytes
54 3,4,6,7 Extra
55 5 Bad block flag
56
57 512 Byte Block
58
59 Bytes Meaning
60
61 0,1,2,3,6,7 ECC bytes
62 8-15 Extra
63 5 Bad block flag
64
65 2048 Byte Block
66
67 Bytes Meaning
68
69 0 Bad block flag
70 2-39 Extra
71 40-63 ECC bytes
72 */
73
74
75 typedef struct PHYSICAL_PAGE_STRUCT
76 {
77 unsigned long memory[WORDS_PER_PHYSICAL_PAGE];
78 unsigned char spare[SPARE_BYTES_PER_PAGE];
79 } PHYSICAL_PAGE;
80
81 typedef struct NAND_BLOCK_DIAG_STRUCT
82 {
83 unsigned long erases;
84 unsigned long page_writes[PHYSICAL_PAGES_PER_BLOCK];
85 unsigned long max_page_writes[PHYSICAL_PAGES_PER_BLOCK];
86 } NAND_BLOCK_DIAG;
87
88
89
90
91 typedef struct NAND_FLASH_BLOCK_STRUCT
92 {
93 PHYSICAL_PAGE physical_pages[PHYSICAL_PAGES_PER_BLOCK];
94 } NAND_FLASH_BLOCK;
95
96 NAND_FLASH_BLOCK nand_memory_area[TOTAL_BLOCKS];
97
98 NAND_BLOCK_DIAG nand_block_diag[TOTAL_BLOCKS];
99
100
101 /* Define NAND flash buffer for LevelX. */
102
103 ULONG nand_flash_simulator_buffer[WORDS_PER_PHYSICAL_PAGE];
104 ULONG *nand_flash_memory;
105
106
107 UINT _lx_nand_flash_simulator_initialize(LX_NAND_FLASH *nand_flash);
108 UINT _lx_nand_flash_simulator_erase_all(VOID);
109
110 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
111 UINT _lx_nand_flash_simulator_read(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, ULONG *destination, ULONG words);
112 UINT _lx_nand_flash_simulator_write(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, ULONG *source, ULONG words);
113 UINT _lx_nand_flash_simulator_block_erase(LX_NAND_FLASH *nand_flash, ULONG block, ULONG erase_count);
114 UINT _lx_nand_flash_simulator_block_erased_verify(LX_NAND_FLASH *nand_flash, ULONG block);
115 UINT _lx_nand_flash_simulator_page_erased_verify(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page);
116 UINT _lx_nand_flash_simulator_block_status_get(LX_NAND_FLASH *nand_flash, ULONG block, UCHAR *bad_block_byte);
117 UINT _lx_nand_flash_simulator_block_status_set(LX_NAND_FLASH *nand_flash, ULONG block, UCHAR bad_block_byte);
118 UINT _lx_nand_flash_simulator_extra_bytes_get(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR *destination, UINT size);
119 UINT _lx_nand_flash_simulator_extra_bytes_set(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR *source, UINT size);
120 UINT _lx_nand_flash_simulator_system_error(LX_NAND_FLASH *nand_flash, UINT error_code, ULONG block, ULONG page);
121
122 UINT _lx_nand_flash_simulator_pages_read(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages);
123 UINT _lx_nand_flash_simulator_pages_write(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages);
124 UINT _lx_nand_flash_simulator_pages_copy(LX_NAND_FLASH *nand_flash, ULONG source_block, ULONG source_page, ULONG destination_block, ULONG destination_page, ULONG pages, UCHAR* data_buffer);
125 #else
126 UINT _lx_nand_flash_simulator_read(ULONG block, ULONG page, ULONG *destination, ULONG words);
127 UINT _lx_nand_flash_simulator_write(ULONG block, ULONG page, ULONG *source, ULONG words);
128 UINT _lx_nand_flash_simulator_block_erase(ULONG block, ULONG erase_count);
129 UINT _lx_nand_flash_simulator_block_erased_verify(ULONG block);
130 UINT _lx_nand_flash_simulator_page_erased_verify(ULONG block, ULONG page);
131 UINT _lx_nand_flash_simulator_block_status_get(ULONG block, UCHAR *bad_block_byte);
132 UINT _lx_nand_flash_simulator_block_status_set(ULONG block, UCHAR bad_block_byte);
133 UINT _lx_nand_flash_simulator_extra_bytes_get(ULONG block, ULONG page, UCHAR *destination, UINT size);
134 UINT _lx_nand_flash_simulator_extra_bytes_set(ULONG block, ULONG page, UCHAR *source, UINT size);
135 UINT _lx_nand_flash_simulator_system_error(UINT error_code, ULONG block, ULONG page);
136
137 UINT _lx_nand_flash_simulator_pages_read(ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages);
138 UINT _lx_nand_flash_simulator_pages_write(ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages);
139 UINT _lx_nand_flash_simulator_pages_copy(ULONG source_block, ULONG source_page, ULONG destination_block, ULONG destination_page, ULONG pages, UCHAR* data_buffer);
140 #endif
141 UINT _lx_nand_flash_simulator_page_ecc_check(ULONG block, ULONG page);
142
143 90 UINT _lx_nand_flash_simulator_initialize(LX_NAND_FLASH *nand_flash)
144 {
145
146 /* Setup the buffer pointer. */
147 90 nand_flash_memory = (ULONG *) &nand_memory_area[0];
148
149 /* Setup geometry of the NAND flash. */
150 90 nand_flash -> lx_nand_flash_total_blocks = TOTAL_BLOCKS;
151 90 nand_flash -> lx_nand_flash_pages_per_block = PHYSICAL_PAGES_PER_BLOCK;
152 90 nand_flash -> lx_nand_flash_bytes_per_page = BYTES_PER_PHYSICAL_PAGE;
153
154 /* Setup function pointers for the NAND flash services. */
155 90 nand_flash -> lx_nand_flash_driver_read = _lx_nand_flash_simulator_read;
156 90 nand_flash -> lx_nand_flash_driver_write = _lx_nand_flash_simulator_write;
157 90 nand_flash -> lx_nand_flash_driver_block_erase = _lx_nand_flash_simulator_block_erase;
158 90 nand_flash -> lx_nand_flash_driver_block_erased_verify = _lx_nand_flash_simulator_block_erased_verify;
159 90 nand_flash -> lx_nand_flash_driver_page_erased_verify = _lx_nand_flash_simulator_page_erased_verify;
160 90 nand_flash -> lx_nand_flash_driver_block_status_get = _lx_nand_flash_simulator_block_status_get;
161 90 nand_flash -> lx_nand_flash_driver_block_status_set = _lx_nand_flash_simulator_block_status_set;
162 90 nand_flash -> lx_nand_flash_driver_extra_bytes_get = _lx_nand_flash_simulator_extra_bytes_get;
163 90 nand_flash -> lx_nand_flash_driver_extra_bytes_set = _lx_nand_flash_simulator_extra_bytes_set;
164 90 nand_flash -> lx_nand_flash_driver_system_error = _lx_nand_flash_simulator_system_error;
165
166 90 nand_flash -> lx_nand_flash_driver_pages_read = _lx_nand_flash_simulator_pages_read;
167 90 nand_flash -> lx_nand_flash_driver_pages_write = _lx_nand_flash_simulator_pages_write;
168 90 nand_flash -> lx_nand_flash_driver_pages_copy = _lx_nand_flash_simulator_pages_copy;
169
170 90 nand_flash -> lx_nand_flash_spare_data1_offset = SPARE_DATA1_OFFSET;
171 90 nand_flash -> lx_nand_flash_spare_data1_length = SPARE_DATA1_LENGTH;
172
173 90 nand_flash -> lx_nand_flash_spare_data2_offset = SPARE_DATA2_OFFSET;
174 90 nand_flash -> lx_nand_flash_spare_data2_length = SPARE_DATA2_LENGTH;
175
176 90 nand_flash -> lx_nand_flash_spare_total_length = SPARE_BYTES_PER_PAGE;
177
178 /* Return success. */
179 90 return(LX_SUCCESS);
180 }
181 2952820 UINT _lx_nand_flash_simulator_page_ecc_check(ULONG block, ULONG page)
182 {
183
184 UINT i;
185 2952820 INT ecc_pos = 0;
186 2952820 UINT ecc_status = LX_SUCCESS;
187 UINT status;
188
189
190
2/2
✓ Branch 9 → 3 taken 5905640 times.
✓ Branch 9 → 10 taken 2952820 times.
8858460 for (i = 0; i < BYTES_PER_PHYSICAL_PAGE; i += 256)
191 {
192 5905640 status = lx_nand_flash_256byte_ecc_check((UCHAR*)&nand_memory_area[block].physical_pages[page].memory[i / sizeof(ULONG)],
193 5905640 &nand_memory_area[block].physical_pages[page].spare[ECC_BYTE_POSITION + ecc_pos]);
194
195
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 5905640 times.
5905640 if (status == LX_NAND_ERROR_NOT_CORRECTED)
196 {
197 ✗ ecc_status = LX_NAND_ERROR_NOT_CORRECTED;
198 ✗ break;
199 }
200
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 5905640 times.
5905640 else if (status == LX_NAND_ERROR_CORRECTED)
201 {
202 ✗ ecc_status = LX_NAND_ERROR_CORRECTED;
203 }
204
205 5905640 ecc_pos += 3;
206 }
207
208
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 2952820 times.
2952820 if (ecc_status == LX_NAND_ERROR_CORRECTED)
209 {
210
211 ✗ return(LX_ERROR);
212 }
213
1/2
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 2952820 times.
2952820 else if (ecc_status == LX_NAND_ERROR_NOT_CORRECTED)
214 {
215
216 ✗ return(LX_ERROR);
217 }
218 2952820 return ecc_status;
219 }
220
221 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
222 295282 UINT _lx_nand_flash_simulator_read(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, ULONG *destination, ULONG words)
223 #else
224 2657538 UINT _lx_nand_flash_simulator_read(ULONG block, ULONG page, ULONG *destination, ULONG words)
225 #endif
226 {
227
228 ULONG *flash_address;
229 UINT status;
230
231 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
232 LX_PARAMETER_NOT_USED(nand_flash);
233 #endif
234
235 2952820 status = _lx_nand_flash_simulator_page_ecc_check(block, page);
236
237 /* Pickup the flash address. */
238 2952820 flash_address = &(nand_memory_area[block].physical_pages[page].memory[0]);
239
240 /* Loop to read flash. */
241
2/2
✓ Branch 5 → 4 taken 377960960 times.
✓ Branch 5 → 6 taken 2952820 times.
380913780 while (words--)
242 {
243 /* Copy word. */
244 377960960 *destination++ = *flash_address++;
245 }
246
247 2952820 return(status);
248 }
249
250 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
251 1407715 UINT _lx_nand_flash_simulator_pages_read(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages)
252 #else
253 12669435 UINT _lx_nand_flash_simulator_pages_read(ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages)
254 #endif
255 {
256
257 UINT i;
258 UINT status;
259 14077150 UINT ecc_status = LX_SUCCESS;
260
261
262
2/2
✓ Branch 12 → 3 taken 14077150 times.
✓ Branch 12 → 13 taken 14077150 times.
28154300 for (i = 0; i < pages; i++)
263 {
264
2/2
✓ Branch 3 → 4 taken 2952820 times.
✓ Branch 3 → 9 taken 11124330 times.
14077150 if (main_buffer)
265 {
266
267 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
268 295282 status = _lx_nand_flash_simulator_read(nand_flash, block, page + i, (ULONG*)(main_buffer + i * BYTES_PER_PHYSICAL_PAGE), WORDS_PER_PHYSICAL_PAGE);
269 #else
270 2657538 status = _lx_nand_flash_simulator_read(block, page + i, (ULONG*)(main_buffer + i * BYTES_PER_PHYSICAL_PAGE), WORDS_PER_PHYSICAL_PAGE);
271 #endif
272
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 2952820 times.
2952820 if (status == LX_NAND_ERROR_CORRECTED)
273 {
274 ✗ ecc_status = LX_NAND_ERROR_CORRECTED;
275 }
276
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 2952820 times.
2952820 else if (status == LX_NAND_ERROR_NOT_CORRECTED)
277 {
278 ✗ ecc_status = LX_ERROR;
279 ✗ break;
280 }
281 }
282
283
2/2
✓ Branch 9 → 10 taken 14066990 times.
✓ Branch 9 → 11 taken 10160 times.
14077150 if (spare_buffer)
284 {
285
286 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
287 1406699 status = _lx_nand_flash_simulator_extra_bytes_get(nand_flash, block, page + i, spare_buffer + i * SPARE_BYTES_PER_PAGE, SPARE_BYTES_PER_PAGE);
288 #else
289 12660291 status = _lx_nand_flash_simulator_extra_bytes_get(block, page + i, spare_buffer + i * SPARE_BYTES_PER_PAGE, SPARE_BYTES_PER_PAGE);
290 #endif
291 }
292 }
293 14077150 return (ecc_status);
294 }
295
296 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
297 396827 UINT _lx_nand_flash_simulator_write(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, ULONG *source, ULONG words)
298 #else
299 3571443 UINT _lx_nand_flash_simulator_write(ULONG block, ULONG page, ULONG *source, ULONG words)
300 #endif
301 {
302
303 ULONG *flash_address;
304 UCHAR *flash_spare_address;
305 UINT bytes_computed;
306 3968270 UINT ecc_bytes =0;
307 UCHAR new_ecc_buffer[24];
308 3968270 UCHAR *new_ecc_buffer_ptr = new_ecc_buffer;
309 3968270 UCHAR *ecc_buffer_ptr = new_ecc_buffer_ptr;
310 3968270 ULONG *page_ptr = &(nand_memory_area[block].physical_pages[page].memory[0]);
311
312 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
313 LX_PARAMETER_NOT_USED(nand_flash);
314 #endif
315
316 /* Increment the diag info. */
317 3968270 nand_block_diag[block].page_writes[page]++;
318
2/2
✓ Branch 2 → 3 taken 2528240 times.
✓ Branch 2 → 4 taken 1440030 times.
3968270 if (nand_block_diag[block].page_writes[page] > nand_block_diag[block].max_page_writes[page])
319 2528240 nand_block_diag[block].max_page_writes[page] = nand_block_diag[block].page_writes[page];
320
321 /* Pickup the flash address. */
322 3968270 flash_address = &(nand_memory_area[block].physical_pages[page].memory[0]);
323
324 /* Loop to write flash. */
325
2/2
✓ Branch 8 → 5 taken 507938560 times.
✓ Branch 8 → 9 taken 3968270 times.
511906830 while (words--)
326 {
327
328 /* Can the word be written? We can clear new bits, but just can't unclear
329 in a NAND device. */
330
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 507938560 times.
507938560 if ((*source & *flash_address) != *source)
331 ✗ return(LX_INVALID_WRITE);
332
333 /* Copy word. */
334 507938560 *flash_address++ = *source++;
335 }
336
337 /* Loop to compute the ECC over the entire NAND flash page. */
338 3968270 bytes_computed = 0;
339
340
2/2
✓ Branch 12 → 10 taken 7936540 times.
✓ Branch 12 → 13 taken 3968270 times.
11904810 while (bytes_computed < BYTES_PER_PHYSICAL_PAGE)
341 {
342
343 /* Compute the ECC for this 256 byte piece of the page. */
344 7936540 _lx_nand_flash_256byte_ecc_compute((UCHAR *)page_ptr, (UCHAR *)new_ecc_buffer_ptr);
345
346 /* Move to the next 256 byte portion of the page. */
347 7936540 bytes_computed = bytes_computed + 256;
348
349 /* Move the page buffer forward. */
350 7936540 page_ptr = page_ptr + 64;
351
352 7936540 ecc_bytes = ecc_bytes + 3;
353
354 /* Move the ECC buffer forward, note there are 3 bytes of ECC per page. */
355 7936540 new_ecc_buffer_ptr = new_ecc_buffer_ptr + 3;
356 }
357
358 /* Setup destination pointer in the spare area. */
359 3968270 flash_spare_address = (UCHAR *) &(nand_memory_area[block].physical_pages[page].spare[ECC_BYTE_POSITION]);
360
2/2
✓ Branch 17 → 14 taken 23809620 times.
✓ Branch 17 → 18 taken 3968270 times.
27777890 while(ecc_bytes--)
361 {
362
363 /* Can the word be written? We can clear new bits, but just can't unclear
364 in a NAND device. */
365
1/2
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 23809620 times.
23809620 if ((*ecc_buffer_ptr & *flash_spare_address) != *ecc_buffer_ptr)
366 ✗ return(LX_INVALID_WRITE);
367
368 /* Set an ecc byte in the spare area. */
369 23809620 *flash_spare_address++ = *ecc_buffer_ptr++;
370
371 }
372 3968270 return(LX_SUCCESS);
373 }
374
375 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
376 396827 UINT _lx_nand_flash_simulator_pages_write(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages)
377 #else
378 3571443 UINT _lx_nand_flash_simulator_pages_write(ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages)
379 #endif
380 {
381
382 UINT i;
383 3968270 UINT status = LX_SUCCESS;
384
385
386
2/2
✓ Branch 8 → 3 taken 3968270 times.
✓ Branch 8 → 9 taken 3968270 times.
7936540 for (i = 0; i < pages; i++)
387 {
388 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
389 396827 _lx_nand_flash_simulator_extra_bytes_set(nand_flash, block, page + i, spare_buffer + i * SPARE_BYTES_PER_PAGE, SPARE_BYTES_PER_PAGE);
390 396827 status = _lx_nand_flash_simulator_write(nand_flash, block, page + i, (ULONG*)(main_buffer + i * BYTES_PER_PHYSICAL_PAGE), WORDS_PER_PHYSICAL_PAGE);
391 #else
392 3571443 _lx_nand_flash_simulator_extra_bytes_set(block, page + i, spare_buffer + i * SPARE_BYTES_PER_PAGE, SPARE_BYTES_PER_PAGE);
393 3571443 status = _lx_nand_flash_simulator_write(block, page + i, (ULONG*)(main_buffer + i * BYTES_PER_PHYSICAL_PAGE), WORDS_PER_PHYSICAL_PAGE);
394 #endif
395
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 3968270 times.
3968270 if (status == LX_INVALID_WRITE)
396 {
397 ✗ break;
398 }
399
400 }
401 3968270 return (status);
402 }
403
404 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
405 8731 UINT _lx_nand_flash_simulator_pages_copy(LX_NAND_FLASH *nand_flash, ULONG source_block, ULONG source_page, ULONG destination_block, ULONG destination_page, ULONG pages, UCHAR *data_buffer)
406 #else
407 78579 UINT _lx_nand_flash_simulator_pages_copy(ULONG source_block, ULONG source_page, ULONG destination_block, ULONG destination_page, ULONG pages, UCHAR *data_buffer)
408 #endif
409 {
410 UINT i;
411 87310 UINT status = LX_SUCCESS;
412
413
414
2/2
✓ Branch 11 → 3 taken 2905830 times.
✓ Branch 11 → 12 taken 87310 times.
2993140 for (i = 0; i < pages; i++)
415 {
416 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
417 290583 status = _lx_nand_flash_simulator_pages_read(nand_flash, source_block, source_page + i, data_buffer, data_buffer + BYTES_PER_PHYSICAL_PAGE, 1);
418 #else
419 2615247 status = _lx_nand_flash_simulator_pages_read(source_block, source_page + i, data_buffer, data_buffer + BYTES_PER_PHYSICAL_PAGE, 1);
420 #endif
421
1/4
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 7 taken 2905830 times.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 7 not taken.
2905830 if (status != LX_SUCCESS && status != LX_NAND_ERROR_CORRECTED)
422 {
423 ✗ break;
424 }
425 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
426 290583 status = _lx_nand_flash_simulator_pages_write(nand_flash, destination_block, destination_page + i, data_buffer, data_buffer + BYTES_PER_PHYSICAL_PAGE, 1);
427 #else
428 2615247 status = _lx_nand_flash_simulator_pages_write(destination_block, destination_page + i, data_buffer, data_buffer + BYTES_PER_PHYSICAL_PAGE, 1);
429 #endif
430
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 2905830 times.
2905830 if (status != LX_SUCCESS)
431 {
432 ✗ break;
433 }
434
435 }
436 87310 return (status);
437
438 }
439
440 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
441 5514 UINT _lx_nand_flash_simulator_block_erase(LX_NAND_FLASH *nand_flash, ULONG block, ULONG erase_count)
442 #else
443 49626 UINT _lx_nand_flash_simulator_block_erase(ULONG block, ULONG erase_count)
444 #endif
445 {
446
447 ULONG *pointer;
448 ULONG words;
449 UINT i;
450
451 LX_PARAMETER_NOT_USED(erase_count);
452 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
453 LX_PARAMETER_NOT_USED(nand_flash);
454 #endif
455
456 /* Increment the diag info. */
457 55140 nand_block_diag[block].erases++;
458
2/2
✓ Branch 4 → 3 taken 14115840 times.
✓ Branch 4 → 5 taken 55140 times.
14170980 for (i = 0; i < PHYSICAL_PAGES_PER_BLOCK;i++)
459 14115840 nand_block_diag[block].page_writes[i] = 0;
460
461 /* Setup pointer. */
462 55140 pointer = (ULONG *) &nand_memory_area[block];
463
464 /* Loop to erase block. */
465 55140 words = sizeof(NAND_FLASH_BLOCK)/sizeof(ULONG);
466
2/2
✓ Branch 7 → 6 taken 1863290880 times.
✓ Branch 7 → 8 taken 55140 times.
1863346020 while (words--)
467 {
468
469 /* Erase word of block. */
470 1863290880 *pointer++ = (ULONG) 0xFFFFFFFF;
471 }
472
473 55140 return(LX_SUCCESS);
474 }
475
476
477 40 UINT _lx_nand_flash_simulator_erase_all(VOID)
478 {
479
480 ULONG *pointer;
481 ULONG words;
482 UINT i, j;
483
484
485 /* Increment the diag info. */
486
2/2
✓ Branch 7 → 3 taken 40960 times.
✓ Branch 7 → 8 taken 40 times.
41000 for (i = 0; i < TOTAL_BLOCKS; i++)
487 {
488 40960 nand_block_diag[i].erases = 0;
489
2/2
✓ Branch 5 → 4 taken 10485760 times.
✓ Branch 5 → 6 taken 40960 times.
10526720 for (j = 0; j < PHYSICAL_PAGES_PER_BLOCK;j++)
490 10485760 nand_block_diag[i].page_writes[j] = 0;
491 }
492
493 /* Setup pointer. */
494 40 pointer = (ULONG *) &nand_memory_area[0];
495
496 /* Loop to erase block. */
497 40 words = sizeof(nand_memory_area)/(sizeof(ULONG));
498
2/2
✓ Branch 10 → 9 taken 1384120320 times.
✓ Branch 10 → 11 taken 40 times.
1384120360 while (words--)
499 {
500
501 /* Erase word of block. */
502 1384120320 *pointer++ = (ULONG) 0xFFFFFFFF;
503 }
504
505 40 return(LX_SUCCESS);
506 }
507
508
509 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
510 ✗ UINT _lx_nand_flash_simulator_block_erased_verify(LX_NAND_FLASH *nand_flash, ULONG block)
511 #else
512 ✗ UINT _lx_nand_flash_simulator_block_erased_verify(ULONG block)
513 #endif
514 {
515
516 ULONG *word_ptr;
517 ULONG words;
518
519 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
520 LX_PARAMETER_NOT_USED(nand_flash);
521 #endif
522
523 /* Determine if the block is completely erased. */
524
525 /* Pickup the pointer to the first word of the block. */
526 ✗ word_ptr = (ULONG *) &nand_memory_area[block];
527
528 /* Calculate the number of words in a block. */
529 ✗ words = sizeof(NAND_FLASH_BLOCK)/sizeof(ULONG);
530
531 /* Loop to check if the block is erased. */
532 ✗ while (words--)
533 {
534
535 /* Is this word erased? */
536 ✗ if (*word_ptr++ != 0xFFFFFFFF)
537 ✗ return(LX_ERROR);
538 }
539
540 /* Return success. */
541 ✗ return(LX_SUCCESS);
542 }
543
544 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
545 ✗ UINT _lx_nand_flash_simulator_page_erased_verify(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page)
546 #else
547 ✗ UINT _lx_nand_flash_simulator_page_erased_verify(ULONG block, ULONG page)
548 #endif
549 {
550
551 ULONG *word_ptr;
552 ULONG words;
553
554 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
555 LX_PARAMETER_NOT_USED(nand_flash);
556 #endif
557
558 /* Determine if the block is completely erased. */
559
560 /* Pickup the pointer to the first word of the block's page. */
561 ✗ word_ptr = (ULONG *) &nand_memory_area[block].physical_pages[page];
562
563 /* Calculate the number of words in a block. */
564 ✗ words = WORDS_PER_PHYSICAL_PAGE;
565
566 /* Loop to check if the page is erased. */
567 ✗ while (words--)
568 {
569
570 /* Is this word erased? */
571 ✗ if (*word_ptr++ != 0xFFFFFFFF)
572 ✗ return(LX_ERROR);
573 }
574
575 /* Return success. */
576 ✗ return(LX_SUCCESS);
577 }
578
579 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
580 4101 UINT _lx_nand_flash_simulator_block_status_get(LX_NAND_FLASH *nand_flash, ULONG block, UCHAR *bad_block_byte)
581 #else
582 36909 UINT _lx_nand_flash_simulator_block_status_get(ULONG block, UCHAR *bad_block_byte)
583 #endif
584 {
585
586 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
587 LX_PARAMETER_NOT_USED(nand_flash);
588 #endif
589
590 /* Pickup the bad block byte and return it. */
591 41010 *bad_block_byte = nand_memory_area[block].physical_pages[0].spare[BAD_BLOCK_POSITION];
592
593 /* Return success. */
594 41010 return(LX_SUCCESS);
595 }
596
597 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
598 ✗ UINT _lx_nand_flash_simulator_block_status_set(LX_NAND_FLASH *nand_flash, ULONG block, UCHAR bad_block_byte)
599 #else
600 ✗ UINT _lx_nand_flash_simulator_block_status_set(ULONG block, UCHAR bad_block_byte)
601 #endif
602 {
603
604 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
605 LX_PARAMETER_NOT_USED(nand_flash);
606 #endif
607
608 /* Set the bad block byte. */
609 ✗ nand_memory_area[block].physical_pages[0].spare[BAD_BLOCK_POSITION] = bad_block_byte;
610
611 /* Return success. */
612 ✗ return(LX_SUCCESS);
613 }
614
615
616 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
617 1406699 UINT _lx_nand_flash_simulator_extra_bytes_get(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR *destination, UINT size)
618 #else
619 12660291 UINT _lx_nand_flash_simulator_extra_bytes_get(ULONG block, ULONG page, UCHAR *destination, UINT size)
620 #endif
621 {
622
623 UCHAR *source;
624
625 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
626 LX_PARAMETER_NOT_USED(nand_flash);
627 #endif
628
629 /* Setup source pointer in the spare area. */
630 14066990 source = (UCHAR *) &(nand_memory_area[block].physical_pages[page].spare[EXTRA_BYTE_POSITION]);
631
632 /* Loop to return the extra bytes requested. */
633
2/2
✓ Branch 4 → 3 taken 225071840 times.
✓ Branch 4 → 5 taken 14066990 times.
239138830 while (size--)
634 {
635
636 /* Retrieve an extra byte from the spare area. */
637 225071840 *destination++ = *source++;
638 }
639
640 /* Return success. */
641 14066990 return(LX_SUCCESS);
642 }
643
644 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
645 396827 UINT _lx_nand_flash_simulator_extra_bytes_set(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR *source, UINT size)
646 #else
647 3571443 UINT _lx_nand_flash_simulator_extra_bytes_set(ULONG block, ULONG page, UCHAR *source, UINT size)
648 #endif
649 {
650
651 UCHAR *destination;
652
653 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
654 LX_PARAMETER_NOT_USED(nand_flash);
655 #endif
656
657 /* Increment the diag info. */
658 3968270 nand_block_diag[block].page_writes[page]++;
659
2/2
✓ Branch 2 → 3 taken 2528240 times.
✓ Branch 2 → 4 taken 1440030 times.
3968270 if (nand_block_diag[block].page_writes[page] > nand_block_diag[block].max_page_writes[page])
660 2528240 nand_block_diag[block].max_page_writes[page] = nand_block_diag[block].page_writes[page];
661
662 /* Setup destination pointer in the spare area. */
663 3968270 destination = (UCHAR *) &(nand_memory_area[block].physical_pages[page].spare[EXTRA_BYTE_POSITION]);
664
665 /* Loop to set the extra bytes. */
666
2/2
✓ Branch 6 → 5 taken 63492320 times.
✓ Branch 6 → 7 taken 3968270 times.
67460590 while (size--)
667 {
668
669 /* Set an extra byte in the spare area. */
670 63492320 *destination++ = *source++;
671 }
672
673 /* Return success. */
674 3968270 return(LX_SUCCESS);
675 }
676
677 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
678 ✗ UINT _lx_nand_flash_simulator_system_error(LX_NAND_FLASH *nand_flash, UINT error_code, ULONG block, ULONG page)
679 #else
680 ✗ UINT _lx_nand_flash_simulator_system_error(UINT error_code, ULONG block, ULONG page)
681 #endif
682 {
683 LX_PARAMETER_NOT_USED(error_code);
684 LX_PARAMETER_NOT_USED(block);
685 LX_PARAMETER_NOT_USED(page);
686 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
687 LX_PARAMETER_NOT_USED(nand_flash);
688 #endif
689
690 /* Custom processing goes here... all errors except for LX_NAND_ERROR_CORRECTED are fatal. */
691 ✗ return(LX_ERROR);
692 }
693
694
695
696