GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lx_nand_flash_data_page_copy.c Lines: 35 41 85.4 %
Date: 2026-03-06 18:45:40 Branches: 25 32 78.1 %

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
2278
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
2278
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
2278
    dest_block_status = *dest_block_status_ptr;
95
96
    /* Get the current page number of the destination block.  */
97
2278
    destination_page = dest_block_status & LX_NAND_BLOCK_STATUS_PAGE_NUMBER_MASK;
98
99
    /* Get the available pages in the source block.  */
100
2278
    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
2278
    if (src_block_status & LX_NAND_BLOCK_STATUS_NON_SEQUENTIAL)
104
    {
105
106
        /* Get buffer for spare data.  */
107
56
        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
7196
        for (i = 0; i < sectors; i++)
111
        {
112
113
            /* Loop to search the page.  */
114
988442
            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
                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
987816
                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
987816
                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
987816
                spare_data1 = LX_UTILITY_LONG_GET(&spare_buffer_ptr[nand_flash -> lx_nand_flash_spare_data1_offset]);
137
138
                /* Check the address match.  */
139
987816
                if ((spare_data1 & LX_NAND_PAGE_TYPE_USER_DATA_MASK) == (logical_sector + i))
140
                {
141
142
                    /* Check if the page contains valid data.  */
143
6514
                    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
                        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
6513
                        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
6513
                        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
6513
                        if (destination_page != ((logical_sector + i) % nand_flash -> lx_nand_flash_pages_per_block))
166
                        {
167
                            /* Mark the block status as non sequential.  */
168
253
                            dest_block_status |= LX_NAND_BLOCK_STATUS_NON_SEQUENTIAL;
169
                        }
170
171
                        /* Update the available pages.  */
172
6513
                        destination_page++;
173
174
                        /* Check if available page count reaches pages per block.  */
175
6513
                        if (destination_page == nand_flash -> lx_nand_flash_pages_per_block)
176
                        {
177
178
                            /* Set block full flag.  */
179
5
                            dest_block_status |= LX_NAND_BLOCK_STATUS_FULL;
180
                        }
181
                    }
182
6514
                    break;
183
                }
184
            }
185
        }
186
    }
187
    else
188
    {
189
190
        /* Get the source page number.  */
191
2222
        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
4444
        number_of_pages = ((ULONG)source_page + sectors) > available_pages ?
195

2222
            (available_pages > (ULONG)source_page ? available_pages - (ULONG)source_page : 0) : sectors;
196
197
        /* Check if there is any pages to be copied.  */
198
2222
        if (number_of_pages)
199
        {
200
201
            /* Call the driver to copy pages.  */
202
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
203
            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
2218
            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
2218
            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
2218
            if ((ULONG)source_page != destination_page)
221
            {
222
223
                /* Mark the block status as non sequential.  */
224
1
                dest_block_status |= LX_NAND_BLOCK_STATUS_NON_SEQUENTIAL;
225
            }
226
227
            /* Update the available pages.  */
228
2218
            destination_page += number_of_pages;
229
230
            /* Check if available page count reaches pages per block.  */
231
2218
            if (destination_page == nand_flash -> lx_nand_flash_pages_per_block)
232
            {
233
234
                /* Set block full flag.  */
235
1107
                dest_block_status |= LX_NAND_BLOCK_STATUS_FULL;
236
            }
237
        }
238
    }
239
240
    /* Return the block status.  */
241
2278
    *dest_block_status_ptr = (USHORT)(destination_page | (dest_block_status & ~LX_NAND_BLOCK_STATUS_PAGE_NUMBER_MASK));
242
243
    /* Return status.  */
244
2278
    return(status);
245
}
246