GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lx_nand_flash_data_page_copy.c Lines: 35 41 85.4 %
Date: 2024-03-11 05:20:25 Branches: 25 32 78.1 %

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_data_page_copy                       PORTABLE C      */
42
/*                                                           6.4.0        */
43
/*  AUTHOR                                                                */
44
/*                                                                        */
45
/*    Xiuwen Cai, Microsoft Corporation                                   */
46
/*                                                                        */
47
/*  DESCRIPTION                                                           */
48
/*                                                                        */
49
/*    This function copies logical sectors into new block.                */
50
/*                                                                        */
51
/*  INPUT                                                                 */
52
/*                                                                        */
53
/*    nand_flash                            NAND flash instance           */
54
/*    logical_sector                        Logical sector number         */
55
/*    source_block                          Source block number           */
56
/*    src_block_status                      Source block status           */
57
/*    destination_block                     Destination block number      */
58
/*    dest_block_status_ptr                 Pointer to destination block  */
59
/*                                            status                      */
60
/*    sectors                               Number of sectors to copy     */
61
/*                                                                        */
62
/*  OUTPUT                                                                */
63
/*                                                                        */
64
/*    return status                                                       */
65
/*                                                                        */
66
/*  CALLS                                                                 */
67
/*                                                                        */
68
/*    lx_nand_flash_driver_pages_copy       Driver pages copy             */
69
/*    lx_nand_flash_driver_pages_read       Driver pages read             */
70
/*    _lx_nand_flash_system_error           Internal system error handler */
71
/*                                                                        */
72
/*  CALLED BY                                                             */
73
/*                                                                        */
74
/*    Internal LevelX                                                     */
75
/*                                                                        */
76
/*  RELEASE HISTORY                                                       */
77
/*                                                                        */
78
/*    DATE              NAME                      DESCRIPTION             */
79
/*                                                                        */
80
/*  03-08-2023     Xiuwen Cai               Initial Version 6.2.1         */
81
/*  12-31-2023     Xiuwen Cai               Modified comment(s),          */
82
/*                                            fixed sequential checking   */
83
/*                                            logic,                      */
84
/*                                            resulting in version 6.4.0  */
85
/*                                                                        */
86
/**************************************************************************/
87
2278
UINT  _lx_nand_flash_data_page_copy(LX_NAND_FLASH* nand_flash, ULONG logical_sector, ULONG source_block, USHORT src_block_status,
88
                                    ULONG destination_block, USHORT* dest_block_status_ptr, ULONG sectors)
89
{
90
91
LONG    source_page;
92
ULONG   destination_page;
93
2278
UINT    status = LX_SUCCESS;
94
UINT    i;
95
ULONG   available_pages;
96
ULONG   spare_data1;
97
UCHAR  *spare_buffer_ptr;
98
ULONG   dest_block_status;
99
ULONG   number_of_pages;
100
101
102
    /* Get the destination block status.  */
103
2278
    dest_block_status = *dest_block_status_ptr;
104
105
    /* Get the current page number of the destination block.  */
106
2278
    destination_page = dest_block_status & LX_NAND_BLOCK_STATUS_PAGE_NUMBER_MASK;
107
108
    /* Get the available pages in the source block.  */
109
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);
110
111
    /* Check if pages in the source block are sequential.  */
112
2278
    if (src_block_status & LX_NAND_BLOCK_STATUS_NON_SEQUENTIAL)
113
    {
114
115
        /* Get buffer for spare data.  */
116
56
        spare_buffer_ptr = nand_flash -> lx_nand_flash_page_buffer + nand_flash -> lx_nand_flash_bytes_per_page;
117
118
        /* Loop to copy the data.  */
119
7196
        for (i = 0; i < sectors; i++)
120
        {
121
122
            /* Loop to search the page.  */
123
988442
            for (source_page = (LONG)(available_pages - 1); source_page >= 0; source_page--)
124
            {
125
126
                /* Read one page.  */
127
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
128
                status = (nand_flash -> lx_nand_flash_driver_pages_read)(nand_flash, source_block, (ULONG)source_page, LX_NULL, spare_buffer_ptr, 1);
129
#else
130
987816
                status = (nand_flash -> lx_nand_flash_driver_pages_read)(source_block, (ULONG)source_page, LX_NULL, spare_buffer_ptr, 1);
131
#endif
132
133
                /* Check for an error from flash driver.   */
134
987816
                if (status)
135
                {
136
137
                    /* Call system error handler.  */
138
                    _lx_nand_flash_system_error(nand_flash, status, source_block, 0);
139
140
                    /* Return an error.  */
141
                    return(LX_ERROR);
142
                }
143
144
                /* Get the spare data.  */
145
987816
                spare_data1 = LX_UTILITY_LONG_GET(&spare_buffer_ptr[nand_flash -> lx_nand_flash_spare_data1_offset]);
146
147
                /* Check the address match.  */
148
987816
                if ((spare_data1 & LX_NAND_PAGE_TYPE_USER_DATA_MASK) == (logical_sector + i))
149
                {
150
151
                    /* Check if the page contains valid data.  */
152
6514
                    if ((spare_data1 & (~LX_NAND_PAGE_TYPE_USER_DATA_MASK)) == (LX_NAND_PAGE_TYPE_USER_DATA))
153
                    {
154
155
                        /* Call the driver to copy the page.  */
156
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
157
                        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);
158
#else
159
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);
160
#endif
161
162
                        /* Check for an error from flash driver.   */
163
6513
                        if (status)
164
                        {
165
166
                            /* Call system error handler.  */
167
                            _lx_nand_flash_system_error(nand_flash, status, source_block, 0);
168
169
                            /* Return an error.  */
170
                            return(LX_ERROR);
171
                        }
172
173
                        /* Check if the pages in destination block is still sequential.  */
174
6513
                        if (destination_page != ((logical_sector + i) % nand_flash -> lx_nand_flash_pages_per_block))
175
                        {
176
                            /* Mark the block status as non sequential.  */
177
253
                            dest_block_status |= LX_NAND_BLOCK_STATUS_NON_SEQUENTIAL;
178
                        }
179
180
                        /* Update the available pages.  */
181
6513
                        destination_page++;
182
183
                        /* Check if available page count reaches pages per block.  */
184
6513
                        if (destination_page == nand_flash -> lx_nand_flash_pages_per_block)
185
                        {
186
187
                            /* Set block full flag.  */
188
5
                            dest_block_status |= LX_NAND_BLOCK_STATUS_FULL;
189
                        }
190
                    }
191
6514
                    break;
192
                }
193
            }
194
        }
195
    }
196
    else
197
    {
198
199
        /* Get the source page number.  */
200
2222
        source_page = (LONG)(logical_sector % nand_flash -> lx_nand_flash_pages_per_block);
201
202
        /* Check if the page to copy is greater than the available pages.  */
203
4444
        number_of_pages = ((ULONG)source_page + sectors) > available_pages ?
204

2222
            (available_pages > (ULONG)source_page ? available_pages - (ULONG)source_page : 0) : sectors;
205
206
        /* Check if there is any pages to be copied.  */
207
2222
        if (number_of_pages)
208
        {
209
210
            /* Call the driver to copy pages.  */
211
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
212
            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);
213
#else
214
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);
215
#endif
216
217
            /* Check for an error from flash driver.   */
218
2218
            if (status)
219
            {
220
221
                /* Call system error handler.  */
222
                _lx_nand_flash_system_error(nand_flash, status, source_block, 0);
223
224
                /* Return an error.  */
225
                return(LX_ERROR);
226
            }
227
228
            /* Check if the pages in destination block is still sequential.  */
229
2218
            if ((ULONG)source_page != destination_page)
230
            {
231
232
                /* Mark the block status as non sequential.  */
233
1
                dest_block_status |= LX_NAND_BLOCK_STATUS_NON_SEQUENTIAL;
234
            }
235
236
            /* Update the available pages.  */
237
2218
            destination_page += number_of_pages;
238
239
            /* Check if available page count reaches pages per block.  */
240
2218
            if (destination_page == nand_flash -> lx_nand_flash_pages_per_block)
241
            {
242
243
                /* Set block full flag.  */
244
1107
                dest_block_status |= LX_NAND_BLOCK_STATUS_FULL;
245
            }
246
        }
247
    }
248
249
    /* Return the block status.  */
250
2278
    *dest_block_status_ptr = (USHORT)(destination_page | (dest_block_status & ~LX_NAND_BLOCK_STATUS_PAGE_NUMBER_MASK));
251
252
    /* Return status.  */
253
2278
    return(status);
254
}
255