GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lx_nand_flash_sector_read.c Lines: 24 33 72.7 %
Date: 2026-03-06 18:45:40 Branches: 18 24 75.0 %

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_sector_read                          PORTABLE C      */
43
/*                                                           6.2.1       */
44
/*  AUTHOR                                                                */
45
/*                                                                        */
46
/*    Xiuwen Cai, Microsoft Corporation                                   */
47
/*                                                                        */
48
/*  DESCRIPTION                                                           */
49
/*                                                                        */
50
/*    This function reads a logical sector from NAND flash.               */
51
/*                                                                        */
52
/*  INPUT                                                                 */
53
/*                                                                        */
54
/*    nand_flash                            NAND flash instance           */
55
/*    logical_sector                        Logical sector number         */
56
/*    buffer                                Pointer to buffer to read into*/
57
/*                                            (the size is number of      */
58
/*                                             bytes in a page)           */
59
/*                                                                        */
60
/*  OUTPUT                                                                */
61
/*                                                                        */
62
/*    return status                                                       */
63
/*                                                                        */
64
/*  CALLS                                                                 */
65
/*                                                                        */
66
/*    _lx_nand_flash_block_find             Find the mapped block         */
67
/*    lx_nand_flash_driver_pages_read       Read pages                    */
68
/*    _lx_nand_flash_system_error           Internal system error handler */
69
/*    tx_mutex_get                          Get thread protection         */
70
/*    tx_mutex_put                          Release thread protection     */
71
/*                                                                        */
72
/*  CALLED BY                                                             */
73
/*                                                                        */
74
/*    Application Code                                                    */
75
/*                                                                        */
76
/**************************************************************************/
77
47586
UINT  _lx_nand_flash_sector_read(LX_NAND_FLASH *nand_flash, ULONG logical_sector, VOID *buffer)
78
{
79
80
UINT        status;
81
ULONG       i;
82
ULONG       *word_ptr;
83
ULONG       block;
84
USHORT      block_status;
85
UCHAR       *spare_buffer_ptr;
86
ULONG       available_pages;
87
LONG        page;
88
89
#ifdef LX_THREAD_SAFE_ENABLE
90
91
    /* Obtain the thread safe mutex.  */
92
    tx_mutex_get(&nand_flash -> lx_nand_flash_mutex, TX_WAIT_FOREVER);
93
#endif
94
95
    /* Increment the number of read requests.  */
96
47586
    nand_flash -> lx_nand_flash_diagnostic_sector_read_requests++;
97
98
    /* See if we can find the sector in the current mapping.  */
99
47586
    status = _lx_nand_flash_block_find(nand_flash, logical_sector, &block, &block_status);
100
101
    /* Check return status.   */
102
47586
    if (status != LX_SUCCESS)
103
    {
104
105
        /* Call system error handler.  */
106
        _lx_nand_flash_system_error(nand_flash, status, block, 0);
107
108
        /* Determine if the error is fatal.  */
109
        if (status != LX_NAND_ERROR_CORRECTED)
110
        {
111
#ifdef LX_THREAD_SAFE_ENABLE
112
113
            /* Release the thread safe mutex.  */
114
            tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
115
#endif
116
            /* Return an error.  */
117
            return(LX_ERROR);
118
        }
119
    }
120
121
    /* Determine if the block is mapped.  */
122
47586
    if (block != LX_NAND_BLOCK_UNMAPPED)
123
    {
124
125
        /* Setup spare buffer pointer.  */
126
5337
        spare_buffer_ptr = (UCHAR*)nand_flash -> lx_nand_flash_page_buffer;
127
128
        /* Get available pages in this block.  */
129
5337
        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;
130
131
        /* Determine if the pages are recorded sequentially.  */
132
5337
        if (block_status & LX_NAND_BLOCK_STATUS_NON_SEQUENTIAL)
133
        {
134
135
            /* Loop to search the logical page.  */
136
113843
            for (page = (LONG)available_pages - 1; page >= 0; page--)
137
            {
138
139
                /* Read a page.  */
140
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
141
                status = (nand_flash -> lx_nand_flash_driver_pages_read)(nand_flash, block, (ULONG)page, (UCHAR*)NULL, spare_buffer_ptr, 1);
142
#else
143
113204
                status = (nand_flash -> lx_nand_flash_driver_pages_read)(block, (ULONG)page, (UCHAR*)NULL, spare_buffer_ptr, 1);
144
#endif
145
146
                /* Check for an error from flash driver.   */
147
113204
                if (status)
148
                {
149
150
                    /* Call system error handler.  */
151
                    _lx_nand_flash_system_error(nand_flash, status, block, 0);
152
#ifdef LX_THREAD_SAFE_ENABLE
153
154
                    /* Release the thread safe mutex.  */
155
                    tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
156
#endif
157
                    /* Return an error.  */
158
                    return(LX_ERROR);
159
                }
160
161
                /* Get the logical sector number from spare bytes, and check if it matches the addressed sector number.  */
162
113204
                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)
163
                {
164
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
165
                    status = (nand_flash -> lx_nand_flash_driver_pages_read)(nand_flash, block, (ULONG)page, (UCHAR*)buffer, NULL, 1);
166
#else
167
1016
                    status = (nand_flash -> lx_nand_flash_driver_pages_read)(block, (ULONG)page, (UCHAR*)buffer, NULL, 1);
168
#endif
169
170
                    /* Check for an error from flash driver.   */
171
1016
                    if (status)
172
                    {
173
174
                        /* Call system error handler.  */
175
                        _lx_nand_flash_system_error(nand_flash, status, block, 0);
176
#ifdef LX_THREAD_SAFE_ENABLE
177
178
                        /* Release the thread safe mutex.  */
179
                        tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
180
#endif
181
                        /* Return an error.  */
182
                        return(LX_ERROR);
183
                    }
184
#ifdef LX_THREAD_SAFE_ENABLE
185
186
                    /* Release the thread safe mutex.  */
187
                    tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
188
#endif
189
                    /* Return successful completion.  */
190
1016
                    return(LX_SUCCESS);
191
                }
192
            }
193
        }
194
        else
195
        {
196
197
            /* Check if the logical sector is available.  */
198
3682
            if (logical_sector % nand_flash -> lx_nand_flash_pages_per_block < available_pages)
199
            {
200
201
                /* Read a page.  */
202
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
203
                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);
204
#else
205
3084
                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);
206
#endif
207
208
                /* Check for an error from flash driver.   */
209
3084
                if (status)
210
                {
211
212
                    /* Call system error handler.  */
213
                    _lx_nand_flash_system_error(nand_flash, status, block, 0);
214
215
#ifdef LX_THREAD_SAFE_ENABLE
216
217
                    /* Release the thread safe mutex.  */
218
                    tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
219
#endif
220
                    /* Return an error.  */
221
                    return(LX_ERROR);
222
                }
223
#ifdef LX_THREAD_SAFE_ENABLE
224
225
                /* Release the thread safe mutex.  */
226
                tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
227
#endif
228
                /* Return successful completion.  */
229
3084
                return(LX_SUCCESS);
230
            }
231
        }
232
    }
233
234
    /* Sector hasn't been written. Simply fill the destination buffer with ones and return success.  */
235
236
    /* Setup pointer to users buffer.  */
237
43486
    word_ptr =  (ULONG *) buffer;
238
239
    /* Put all ones in he buffer.  */
240
5609694
    for (i = 0; i < nand_flash -> lx_nand_flash_words_per_page; i++)
241
    {
242
243
        /* Copy a word.  */
244
5566208
        *word_ptr++ =  LX_ALL_ONES;
245
    }
246
247
    /* Set the status to success.  */
248
43486
    status =  LX_SUCCESS;
249
250
#ifdef LX_THREAD_SAFE_ENABLE
251
252
    /* Release the thread safe mutex.  */
253
    tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
254
#endif
255
256
    /* Return status.  */
257
43486
    return(status);
258
}
259