GCC Code Coverage Report


Directory: common/src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 0.0% 0 / 0 / 80
Functions: 0.0% 0 / 0 / 1
Branches: 0.0% 0 / 0 / 30

fx_nand_flash_simulated_driver.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 /** FileX Component */
17 /** */
18 /** FileX NAND FLASH Simulator Driver */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23
24 /* Include necessary system files. */
25
26 #include "fx_api.h"
27 #include "lx_api.h"
28
29
30 /* Create a NAND flash control block. */
31
32 LX_NAND_FLASH nand_flash;
33
34 /* Memory buffer size should be at least 7 * total block count + 2 * page size,
35 that is 7 * 1024 + 2 * 528 = 8224 bytes */
36 ULONG lx_memory_buffer[8224 / sizeof (ULONG)];
37
38 /* Define the NAND flash simulation initialization function. */
39
40 UINT _lx_nand_flash_simulator_initialize(LX_NAND_FLASH *nand_flash);
41 VOID _fx_nand_flash_read_sectors(ULONG logical_sector, ULONG sectors, UCHAR *destination_buffer);
42 VOID _fx_nand_flash_write_sectors(ULONG logical_sector, ULONG sectors, UCHAR *source_buffer);
43
44
45 /* The simulated NAND driver relies on the fx_media_format call to be made prior to
46 the fx_media_open call.
47
48 fx_media_format(&ram_disk,
49 _fx_nand_sim_driver, // Driver entry
50 FX_NULL, // Unused
51 media_memory, // Media buffer pointer
52 sizeof(media_memory), // Media buffer size
53 "MY_NAND_DISK", // Volume Name
54 1, // Number of FATs
55 32, // Directory Entries
56 0, // Hidden sectors
57 120, // Total sectors
58 2048, // Sector size
59 1, // Sectors per cluster
60 1, // Heads
61 1); // Sectors per track
62
63 */
64
65
66 VOID _fx_nand_flash_simulator_driver(FX_MEDIA *media_ptr);
67
68
69 /**************************************************************************/
70 /* */
71 /* FUNCTION RELEASE */
72 /* */
73 /* _fx_nand_simulator_driver PORTABLE C */
74 /* 6.2.1 */
75 /* AUTHOR */
76 /* */
77 /* William E. Lamie, Microsoft Corporation */
78 /* */
79 /* DESCRIPTION */
80 /* */
81 /* This function is the entry point to the generic NAND simulated */
82 /* disk driver that is delivered with the flash wear leveling product */
83 /* LevelX. */
84 /* */
85 /* This driver also serves as a template for developing other LevelX */
86 /* NAND flash drivers for actual flash devices. Simply replace the */
87 /* read/write sector logic with calls to read/write from the */
88 /* appropriate physical device access functions. */
89 /* */
90 /* FileX NAND FLASH structures look like the following: */
91 /* */
92 /* Logical Sector Contents */
93 /* */
94 /* 0 Boot record */
95 /* 1 FAT Area Start */
96 /* +FAT Sectors Root Directory Start */
97 /* +Directory Sectors Data Sector Start */
98 /* */
99 /* */
100 /* INPUT */
101 /* */
102 /* media_ptr Media control block pointer */
103 /* */
104 /* OUTPUT */
105 /* */
106 /* None */
107 /* */
108 /* CALLS */
109 /* */
110 /* _lx_nand_flash_close Close NAND flash manager */
111 /* _lx_nand_flash_open Open NAND flash manager */
112 /* _lx_nand_flash_sector_read Read a NAND sector */
113 /* _lx_nand_flash_sector_release Release a NAND sector */
114 /* _lx_nand_flash_sector_write Write a NAND sector */
115 /* */
116 /* CALLED BY */
117 /* */
118 /* FileX System Functions */
119 /* */
120 /**************************************************************************/
121 ✗ VOID _fx_nand_flash_simulator_driver(FX_MEDIA *media_ptr)
122 {
123
124 ULONG logical_sector;
125 ULONG count;
126 UCHAR *buffer;
127 UINT status;
128
129
130 /* There are several useful/important pieces of information contained in the media
131 structure, some of which are supplied by FileX and others are for the driver to
132 setup. The following is a summary of the necessary FX_MEDIA structure members:
133
134 FX_MEDIA Member Meaning
135
136 fx_media_driver_request FileX request type. Valid requests from FileX are
137 as follows:
138
139 FX_DRIVER_READ
140 FX_DRIVER_WRITE
141 FX_DRIVER_FLUSH
142 FX_DRIVER_ABORT
143 FX_DRIVER_INIT
144 FX_DRIVER_BOOT_READ
145 FX_DRIVER_RELEASE_SECTORS
146 FX_DRIVER_BOOT_WRITE
147 FX_DRIVER_UNINIT
148
149 fx_media_driver_status This value is RETURNED by the driver. If the
150 operation is successful, this field should be
151 set to FX_SUCCESS for before returning. Otherwise,
152 if an error occurred, this field should be set
153 to FX_IO_ERROR.
154
155 fx_media_driver_buffer Pointer to buffer to read or write sector data.
156 This is supplied by FileX.
157
158 fx_media_driver_logical_sector Logical sector FileX is requesting.
159
160 fx_media_driver_sectors Number of sectors FileX is requesting.
161
162
163 The following is a summary of the optional FX_MEDIA structure members:
164
165 FX_MEDIA Member Meaning
166
167 fx_media_driver_info Pointer to any additional information or memory.
168 This is optional for the driver use and is setup
169 from the fx_media_open call. The RAM disk uses
170 this pointer for the RAM disk memory itself.
171
172 fx_media_driver_write_protect The DRIVER sets this to FX_TRUE when media is write
173 protected. This is typically done in initialization,
174 but can be done anytime.
175
176 fx_media_driver_free_sector_update The DRIVER sets this to FX_TRUE when it needs to
177 know when clusters are released. This is important
178 for FLASH wear-leveling drivers.
179
180 fx_media_driver_system_write FileX sets this flag to FX_TRUE if the sector being
181 written is a system sector, e.g., a boot, FAT, or
182 directory sector. The driver may choose to use this
183 to initiate error recovery logic for greater fault
184 tolerance.
185
186 fx_media_driver_data_sector_read FileX sets this flag to FX_TRUE if the sector(s) being
187 read are file data sectors, i.e., NOT system sectors.
188
189 fx_media_driver_sector_type FileX sets this variable to the specific type of
190 sector being read or written. The following sector
191 types are identified:
192
193 FX_UNKNOWN_SECTOR
194 FX_BOOT_SECTOR
195 FX_FAT_SECTOR
196 FX_DIRECTORY_SECTOR
197 FX_DATA_SECTOR
198 */
199
200 /* Process the driver request specified in the media control block. */
201 ✗ switch(media_ptr -> fx_media_driver_request)
202 {
203
204 ✗ case FX_DRIVER_READ:
205 {
206
207 /* Read sector(s) from NAND flash. */
208 ✗ logical_sector = media_ptr -> fx_media_driver_logical_sector;
209 ✗ count = media_ptr -> fx_media_driver_sectors;
210 ✗ buffer = (UCHAR *) media_ptr -> fx_media_driver_buffer;
211 ✗ while (count)
212 {
213
214 /* Call LevelX to read one flash sector. */
215 ✗ status = _lx_nand_flash_sector_read(&nand_flash, logical_sector, buffer);
216
217 /* Determine if the read was successful. */
218 ✗ if (status != LX_SUCCESS)
219 {
220
221 /* Return an I/O error to FileX. */
222 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
223
224 ✗ return;
225 }
226
227 /* Successful sector read. */
228 ✗ count--;
229 ✗ logical_sector++;
230 ✗ buffer += media_ptr -> fx_media_bytes_per_sector;
231 }
232 /* Successful driver request. */
233 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
234 ✗ break;
235 }
236
237 ✗ case FX_DRIVER_WRITE:
238 {
239
240 /* Write sector(s) to NAND flash. */
241 ✗ logical_sector = media_ptr -> fx_media_driver_logical_sector;
242 ✗ count = media_ptr -> fx_media_driver_sectors;
243 ✗ buffer = (UCHAR *) media_ptr -> fx_media_driver_buffer;
244 ✗ while (count)
245 {
246
247 /* Call LevelX to write a sector. */
248 ✗ status = _lx_nand_flash_sector_write(&nand_flash, logical_sector, buffer);
249
250 /* Determine if the write was successful. */
251 ✗ if (status != LX_SUCCESS)
252 {
253
254 /* Return an I/O error to FileX. */
255 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
256
257 ✗ return;
258 }
259
260 /* Successful sector write. */
261 ✗ count--;
262 ✗ logical_sector++;
263 ✗ buffer += media_ptr -> fx_media_bytes_per_sector;
264 }
265
266 /* Successful driver request. */
267 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
268 ✗ break;
269 }
270
271 ✗ case FX_DRIVER_RELEASE_SECTORS:
272 {
273
274 /* Release the mapping of this sector. */
275 ✗ logical_sector = media_ptr -> fx_media_driver_logical_sector;
276 ✗ count = media_ptr -> fx_media_driver_sectors;
277 ✗ while (count)
278 {
279
280 /* Call LevelX to release a sector mapping. */
281 ✗ status = _lx_nand_flash_sector_release(&nand_flash, logical_sector);
282
283 /* Determine if the sector release was successful. */
284 ✗ if (status != LX_SUCCESS)
285 {
286
287 /* Return an I/O error to FileX. */
288 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
289
290 ✗ return;
291 }
292
293 /* Successful sector release. */
294 ✗ count--;
295 ✗ logical_sector++;
296 }
297
298 /* Successful driver request. */
299 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
300 ✗ break;
301 }
302
303 ✗ case FX_DRIVER_FLUSH:
304 {
305
306 /* Return driver success. */
307 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
308 ✗ break;
309 }
310
311 ✗ case FX_DRIVER_ABORT:
312 {
313
314 /* Return driver success. */
315 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
316 ✗ break;
317 }
318
319 ✗ case FX_DRIVER_INIT:
320 {
321
322 /* FLASH drivers are responsible for setting several fields in the
323 media structure, as follows:
324
325 media_ptr -> fx_media_driver_free_sector_update
326 media_ptr -> fx_media_driver_write_protect
327
328 The fx_media_driver_free_sector_update flag is used to instruct
329 FileX to inform the driver whenever sectors are not being used.
330 This is especially useful for FLASH managers so they don't have
331 maintain mapping for sectors no longer in use.
332
333 The fx_media_driver_write_protect flag can be set anytime by the
334 driver to indicate the media is not writable. Write attempts made
335 when this flag is set are returned as errors. */
336
337 /* Perform basic initialization here... since the boot record is going
338 to be read subsequently and again for volume name requests. */
339
340 /* With flash wear leveling, FileX should tell wear leveling when sectors
341 are no longer in use. */
342 ✗ media_ptr -> fx_media_driver_free_sector_update = FX_TRUE;
343
344 /* Open the NAND flash simulation. */
345 ✗ status = _lx_nand_flash_open(&nand_flash, "sim nand flash", _lx_nand_flash_simulator_initialize, lx_memory_buffer, sizeof(lx_memory_buffer));
346
347 /* Determine if the flash open was successful. */
348 ✗ if (status != LX_SUCCESS)
349 {
350
351 /* Return an I/O error to FileX. */
352 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
353
354 ✗ return;
355 }
356
357 /* Successful driver request. */
358 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
359 ✗ break;
360 }
361
362 ✗ case FX_DRIVER_UNINIT:
363 {
364
365 /* There is nothing to do in this case for the RAM driver. For actual
366 devices some shutdown processing may be necessary. */
367
368 /* Close the NAND flash simulation. */
369 ✗ status = _lx_nand_flash_close(&nand_flash);
370
371 /* Determine if the flash close was successful. */
372 ✗ if (status != LX_SUCCESS)
373 {
374
375 /* Return an I/O error to FileX. */
376 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
377
378 ✗ return;
379 }
380
381 /* Successful driver request. */
382 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
383 ✗ break;
384 }
385
386 ✗ case FX_DRIVER_BOOT_READ:
387 {
388
389 /* Read the boot record and return to the caller. */
390 ✗ status = _lx_nand_flash_sector_read(&nand_flash, 0, (UCHAR *) media_ptr -> fx_media_driver_buffer);
391
392 /* Determine if the read was successful. */
393 ✗ if (status != LX_SUCCESS)
394 {
395
396 /* Return an I/O error to FileX. */
397 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
398
399 ✗ return;
400 }
401
402 /* Successful driver request. */
403 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
404 ✗ break;
405 }
406
407 ✗ case FX_DRIVER_BOOT_WRITE:
408 {
409
410 /* Write the boot record and return to the caller. */
411 ✗ status = _lx_nand_flash_sector_write(&nand_flash, 0, (UCHAR *) media_ptr -> fx_media_driver_buffer);
412
413 /* Determine if the write was successful. */
414 ✗ if (status != LX_SUCCESS)
415 {
416
417 /* Return an I/O error to FileX. */
418 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
419
420 ✗ return;
421 }
422
423 /* Successful driver request. */
424 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
425 ✗ break ;
426 }
427
428 ✗ default:
429 {
430
431 /* Invalid driver request. */
432 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
433 ✗ break;
434 }
435 }
436 }
437
438