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_block_data_move PORTABLE C */
42 /* 6.2.1 */
43 /* AUTHOR */
44 /* */
45 /* Xiuwen Cai, Microsoft Corporation */
46 /* */
47 /* DESCRIPTION */
48 /* */
49 /* This function finds a block with less erase count and copies pages */
50 /* into new block. */
51 /* */
52 /* INPUT */
53 /* */
54 /* nand_flash NAND flash instance */
55 /* new_block New block number */
56 /* */
57 /* OUTPUT */
58 /* */
59 /* return status */
60 /* */
61 /* CALLS */
62 /* */
63 /* _lx_nand_flash_mapped_block_list_get Get mapped block index */
64 /* _lx_nand_flash_block_find Find the mapped block */
65 /* _lx_nand_flash_data_page_copy Copy data pages */
66 /* _lx_nand_flash_free_block_list_add Add free block to list */
67 /* _lx_nand_flash_block_status_set Set block status */
68 /* _lx_nand_flash_block_mapping_set Set block mapping */
69 /* _lx_nand_flash_mapped_block_list_add Add mapped block to list */
70 /* _lx_nand_flash_driver_block_erase Erase block */
71 /* _lx_nand_flash_erase_count_set Set erase count */
72 /* _lx_nand_flash_free_block_list_add Add free block to list */
73 /* _lx_nand_flash_system_error Internal system error handler */
74 /* tx_mutex_get Get thread protection */
75 /* tx_mutex_put Release thread protection */
76 /* */
77 /* CALLED BY */
78 /* */
79 /* Application Code */
80 /* */
81 /* RELEASE HISTORY */
82 /* */
83 /* DATE NAME DESCRIPTION */
84 /* */
85 /* 03-08-2023 Xiuwen Cai Initial Version 6.2.1 */
86 /* */
87 /**************************************************************************/
_lx_nand_flash_block_data_move(LX_NAND_FLASH * nand_flash,ULONG new_block)88 UINT _lx_nand_flash_block_data_move(LX_NAND_FLASH *nand_flash, ULONG new_block)
89 {
90
91 UINT status;
92 ULONG block;
93 USHORT block_status;
94 USHORT new_block_status;
95 ULONG block_mapping_index;
96
97
98 /* Get the mapped address to move the data. */
99 status = _lx_nand_flash_mapped_block_list_get(nand_flash, &block_mapping_index);
100
101 if (status)
102 {
103
104 /* Return an error. */
105 return(LX_ERROR);
106 }
107
108 /* Find the block number to be moved. */
109 status = _lx_nand_flash_block_find(nand_flash, block_mapping_index * nand_flash -> lx_nand_flash_pages_per_block, &block, &block_status);
110
111 /* Check the status. */
112 if (status)
113 {
114
115 /* Return an error. */
116 return(LX_ERROR);
117 }
118
119 /* Set new block status to allocated for now. */
120 new_block_status = LX_NAND_BLOCK_STATUS_ALLOCATED;
121
122 /* Copy data from old block to new block. */
123 status = _lx_nand_flash_data_page_copy(nand_flash, block_mapping_index * nand_flash -> lx_nand_flash_pages_per_block, block, block_status, new_block, &new_block_status, nand_flash -> lx_nand_flash_pages_per_block);
124
125 /* Check the status. */
126 if (status)
127 {
128
129 /* Call system error handler. */
130 _lx_nand_flash_system_error(nand_flash, status, new_block, 0);
131
132 /* Return an error. */
133 return(LX_ERROR);
134 }
135
136 /* Check if no page was written. */
137 if ((new_block_status & LX_NAND_BLOCK_STATUS_PAGE_NUMBER_MASK) == 0)
138 {
139
140 /* Mark the new block as free. */
141 new_block_status = LX_NAND_BLOCK_STATUS_FREE;
142
143 /* Add the new block to free list. */
144 _lx_nand_flash_free_block_list_add(nand_flash, new_block);
145
146 }
147
148 /* Set the block status for the new block. */
149 status = _lx_nand_flash_block_status_set(nand_flash, new_block, new_block_status);
150
151 /* Check for an error from flash driver. */
152 if (status)
153 {
154
155 /* Call system error handler. */
156 _lx_nand_flash_system_error(nand_flash, status, new_block, 0);
157
158 /* Return an error. */
159 return(LX_ERROR);
160 }
161
162 /* Check if the block is actually mapped. */
163 if (new_block_status == LX_NAND_BLOCK_STATUS_FREE)
164 {
165
166 /* Unmap the block. */
167 new_block = LX_NAND_BLOCK_UNMAPPED;
168 }
169
170 /* Update block mapping. */
171 _lx_nand_flash_block_mapping_set(nand_flash, block_mapping_index * nand_flash -> lx_nand_flash_pages_per_block, new_block);
172
173 /* Check if the block is actually mapped. */
174 if (new_block != LX_NAND_BLOCK_UNMAPPED)
175 {
176
177 /* Add the block to mapped list. */
178 _lx_nand_flash_mapped_block_list_add(nand_flash, block_mapping_index);
179 }
180
181 /* Erase the old block. */
182 status = _lx_nand_flash_driver_block_erase(nand_flash, block, nand_flash -> lx_nand_flash_base_erase_count + nand_flash -> lx_nand_flash_erase_count_table[block] + 1);
183
184 /* Check for an error from flash driver. */
185 if (status)
186 {
187
188 /* Call system error handler. */
189 _lx_nand_flash_system_error(nand_flash, status, block, 0);
190
191 /* Return an error. */
192 return(LX_ERROR);
193 }
194
195 /* Update the erase count for the erased block. */
196 status = _lx_nand_flash_erase_count_set(nand_flash, block, (UCHAR)(nand_flash -> lx_nand_flash_erase_count_table[block] + 1));
197
198 /* Check for an error from flash driver. */
199 if (status)
200 {
201
202 /* Call system error handler. */
203 _lx_nand_flash_system_error(nand_flash, status, block, 0);
204
205 /* Return an error. */
206 return(LX_ERROR);
207 }
208
209 /* Set the block status to free. */
210 status = _lx_nand_flash_block_status_set(nand_flash, block, LX_NAND_BLOCK_STATUS_FREE);
211
212 /* Check for an error from flash driver. */
213 if (status)
214 {
215
216 /* Call system error handler. */
217 _lx_nand_flash_system_error(nand_flash, status, block, 0);
218
219
220 /* Return an error. */
221 return(LX_ERROR);
222 }
223
224 /* Add the block to free block list. */
225 status = _lx_nand_flash_free_block_list_add(nand_flash, block);
226
227 /* Return status. */
228 return(status);
229 }
230
231