GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lx_nand_flash_sector_read.c Lines: 22 29 75.9 %
Date: 2024-03-11 05:20:25 Branches: 17 22 77.3 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 *
4
 * This program and the accompanying materials are made available under the
5
 * terms of the MIT License which is available at
6
 * https://opensource.org/licenses/MIT.
7
 *
8
 * SPDX-License-Identifier: MIT
9
 **************************************************************************/
10
11
12
/**************************************************************************/
13
/**************************************************************************/
14
/**                                                                       */
15
/** LevelX Component                                                      */
16
/**                                                                       */
17
/**   NAND Flash                                                          */
18
/**                                                                       */
19
/**************************************************************************/
20
/**************************************************************************/
21
22
#define LX_SOURCE_CODE
23
24
25
/* Disable ThreadX error checking.  */
26
27
#ifndef LX_DISABLE_ERROR_CHECKING
28
#define LX_DISABLE_ERROR_CHECKING
29
#endif
30
31
32
/* Include necessary system files.  */
33
34
#include "lx_api.h"
35
36
37
/**************************************************************************/
38
/*                                                                        */
39
/*  FUNCTION                                               RELEASE        */
40
/*                                                                        */
41
/*    _lx_nand_flash_sector_read                          PORTABLE C      */
42
/*                                                           6.2.1       */
43
/*  AUTHOR                                                                */
44
/*                                                                        */
45
/*    Xiuwen Cai, Microsoft Corporation                                   */
46
/*                                                                        */
47
/*  DESCRIPTION                                                           */
48
/*                                                                        */
49
/*    This function reads a logical sector from NAND flash.               */
50
/*                                                                        */
51
/*  INPUT                                                                 */
52
/*                                                                        */
53
/*    nand_flash                            NAND flash instance           */
54
/*    logical_sector                        Logical sector number         */
55
/*    buffer                                Pointer to buffer to read into*/
56
/*                                            (the size is number of      */
57
/*                                             bytes in a page)           */
58
/*                                                                        */
59
/*  OUTPUT                                                                */
60
/*                                                                        */
61
/*    return status                                                       */
62
/*                                                                        */
63
/*  CALLS                                                                 */
64
/*                                                                        */
65
/*    _lx_nand_flash_block_find             Find the mapped block         */
66
/*    lx_nand_flash_driver_pages_read       Read pages                    */
67
/*    _lx_nand_flash_system_error           Internal system error handler */
68
/*    tx_mutex_get                          Get thread protection         */
69
/*    tx_mutex_put                          Release thread protection     */
70
/*                                                                        */
71
/*  CALLED BY                                                             */
72
/*                                                                        */
73
/*    Application Code                                                    */
74
/*                                                                        */
75
/*  RELEASE HISTORY                                                       */
76
/*                                                                        */
77
/*    DATE              NAME                      DESCRIPTION             */
78
/*                                                                        */
79
/*  03-08-2023     Xiuwen Cai               Initial Version 6.2.1        */
80
/*                                                                        */
81
/**************************************************************************/
82
47586
UINT  _lx_nand_flash_sector_read(LX_NAND_FLASH *nand_flash, ULONG logical_sector, VOID *buffer)
83
{
84
85
UINT        status;
86
ULONG       i;
87
ULONG       *word_ptr;
88
ULONG       block;
89
USHORT      block_status;
90
UCHAR       *spare_buffer_ptr;
91
ULONG       available_pages;
92
LONG        page;
93
94
#ifdef LX_THREAD_SAFE_ENABLE
95
96
    /* Obtain the thread safe mutex.  */
97
    tx_mutex_get(&nand_flash -> lx_nand_flash_mutex, TX_WAIT_FOREVER);
98
#endif
99
100
    /* Increment the number of read requests.  */
101
47586
    nand_flash -> lx_nand_flash_diagnostic_sector_read_requests++;
102
103
    /* See if we can find the sector in the current mapping.  */
104
47586
    status = _lx_nand_flash_block_find(nand_flash, logical_sector, &block, &block_status);
105
106
    /* Check return status.   */
107
47586
    if (status != LX_SUCCESS)
108
    {
109
110
        /* Call system error handler.  */
111
        _lx_nand_flash_system_error(nand_flash, status, block, 0);
112
113
        /* Determine if the error is fatal.  */
114
        if (status != LX_NAND_ERROR_CORRECTED)
115
        {
116
#ifdef LX_THREAD_SAFE_ENABLE
117
118
            /* Release the thread safe mutex.  */
119
            tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
120
#endif
121
            /* Return an error.  */
122
            return(LX_ERROR);
123
        }
124
    }
125
126
    /* Determine if the block is mapped.  */
127
47586
    if (block != LX_NAND_BLOCK_UNMAPPED)
128
    {
129
130
        /* Setup spare buffer pointer.  */
131
5337
        spare_buffer_ptr = (UCHAR*)nand_flash -> lx_nand_flash_page_buffer;
132
133
        /* Get available pages in this block.  */
134
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;
135
136
        /* Determine if the pages are recorded sequentially.  */
137
5337
        if (block_status & LX_NAND_BLOCK_STATUS_NON_SEQUENTIAL)
138
        {
139
140
            /* Loop to search the logical page.  */
141
113843
            for (page = (LONG)available_pages - 1; page >= 0; page--)
142
            {
143
144
                /* Read a page.  */
145
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
146
                status = (nand_flash -> lx_nand_flash_driver_pages_read)(nand_flash, block, (ULONG)page, (UCHAR*)buffer, spare_buffer_ptr, 1);
147
#else
148
113204
                status = (nand_flash -> lx_nand_flash_driver_pages_read)(block, (ULONG)page, (UCHAR*)buffer, spare_buffer_ptr, 1);
149
#endif
150
151
                /* Check for an error from flash driver.   */
152
113204
                if (status)
153
                {
154
155
                    /* Call system error handler.  */
156
                    _lx_nand_flash_system_error(nand_flash, status, block, 0);
157
#ifdef LX_THREAD_SAFE_ENABLE
158
159
                    /* Release the thread safe mutex.  */
160
                    tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
161
#endif
162
                    /* Return an error.  */
163
                    return(LX_ERROR);
164
                }
165
166
                /* Get the logical sector number from spare bytes, and check if it matches the addressed sector number.  */
167
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)
168
                {
169
#ifdef LX_THREAD_SAFE_ENABLE
170
171
                    /* Release the thread safe mutex.  */
172
                    tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
173
#endif
174
                    /* Return successful completion.  */
175
1016
                    return(LX_SUCCESS);
176
                }
177
            }
178
        }
179
        else
180
        {
181
182
            /* Check if the logical sector is available.  */
183
3682
            if (logical_sector % nand_flash -> lx_nand_flash_pages_per_block < available_pages)
184
            {
185
186
                /* Read a page.  */
187
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
188
                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);
189
#else
190
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);
191
#endif
192
193
                /* Check for an error from flash driver.   */
194
3084
                if (status)
195
                {
196
197
                    /* Call system error handler.  */
198
                    _lx_nand_flash_system_error(nand_flash, status, block, 0);
199
200
#ifdef LX_THREAD_SAFE_ENABLE
201
202
                    /* Release the thread safe mutex.  */
203
                    tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
204
#endif
205
                    /* Return an error.  */
206
                    return(LX_ERROR);
207
                }
208
#ifdef LX_THREAD_SAFE_ENABLE
209
210
                /* Release the thread safe mutex.  */
211
                tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
212
#endif
213
                /* Return successful completion.  */
214
3084
                return(LX_SUCCESS);
215
            }
216
        }
217
    }
218
219
    /* Sector hasn't been written. Simply fill the destination buffer with ones and return success.  */
220
221
    /* Setup pointer to users buffer.  */
222
43486
    word_ptr =  (ULONG *) buffer;
223
224
    /* Put all ones in he buffer.  */
225
5609694
    for (i = 0; i < nand_flash -> lx_nand_flash_words_per_page; i++)
226
    {
227
228
        /* Copy a word.  */
229
5566208
        *word_ptr++ =  LX_ALL_ONES;
230
    }
231
232
    /* Set the status to success.  */
233
43486
    status =  LX_SUCCESS;
234
235
#ifdef LX_THREAD_SAFE_ENABLE
236
237
    /* Release the thread safe mutex.  */
238
    tx_mutex_put(&nand_flash -> lx_nand_flash_mutex);
239
#endif
240
241
    /* Return status.  */
242
43486
    return(status);
243
}
244