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_metadata_write PORTABLE C */
42 /* 6.2.1 */
43 /* AUTHOR */
44 /* */
45 /* Xiuwen Cai, Microsoft Corporation */
46 /* */
47 /* DESCRIPTION */
48 /* */
49 /* This function writes metadata pages into current metadata block and */
50 /* allocates new blocks for metadata. */
51 /* */
52 /* INPUT */
53 /* */
54 /* nand_flash NAND flash instance */
55 /* main_buffer Main page buffer */
56 /* spare_value Value for spare bytes */
57 /* */
58 /* OUTPUT */
59 /* */
60 /* return status */
61 /* */
62 /* CALLS */
63 /* */
64 /* lx_nand_flash_driver_pages_write Driver pages write */
65 /* _lx_nand_flash_metadata_allocate Allocate blocks for metadata */
66 /* _lx_nand_flash_system_error Internal system error handler */
67 /* */
68 /* CALLED BY */
69 /* */
70 /* Internal LevelX */
71 /* */
72 /* RELEASE HISTORY */
73 /* */
74 /* DATE NAME DESCRIPTION */
75 /* */
76 /* 03-08-2023 Xiuwen Cai Initial Version 6.2.1 */
77 /* */
78 /**************************************************************************/
_lx_nand_flash_metadata_write(LX_NAND_FLASH * nand_flash,UCHAR * main_buffer,ULONG spare_value)79 UINT _lx_nand_flash_metadata_write(LX_NAND_FLASH *nand_flash, UCHAR* main_buffer, ULONG spare_value)
80 {
81
82 ULONG block;
83 ULONG page;
84 UINT status;
85 UCHAR *spare_buffer_ptr;
86
87
88 /* Setup spare buffer pointer. */
89 spare_buffer_ptr = nand_flash -> lx_nand_flash_page_buffer + nand_flash -> lx_nand_flash_bytes_per_page;
90
91 /* Initialize the spare buffer. */
92 LX_MEMSET(spare_buffer_ptr, 0xFF, nand_flash -> lx_nand_flash_spare_total_length);
93
94 /* Check if there is enough spare data for metadata block number. */
95 if (nand_flash -> lx_nand_flash_spare_data2_length >= 2)
96 {
97
98 /* Save metadata block number in spare bytes. */
99 LX_UTILITY_SHORT_SET(&spare_buffer_ptr[nand_flash -> lx_nand_flash_spare_data2_offset], nand_flash -> lx_nand_flash_metadata_block_number);
100 }
101
102 /* Save metadata type data in spare bytes. */
103 LX_UTILITY_LONG_SET(&spare_buffer_ptr[nand_flash -> lx_nand_flash_spare_data1_offset], spare_value);
104
105 /* Get current metadata block number. */
106 block = nand_flash -> lx_nand_flash_metadata_block_number_current;
107
108 /* Get current metadata page number. */
109 page = nand_flash -> lx_nand_flash_metadata_block_current_page;
110
111 /* Write the page. */
112 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
113 status = (nand_flash -> lx_nand_flash_driver_pages_write)(nand_flash, block, page, main_buffer, spare_buffer_ptr, 1);
114 #else
115 status = (nand_flash -> lx_nand_flash_driver_pages_write)(block, page, main_buffer, spare_buffer_ptr, 1);
116 #endif
117
118 /* Check for an error from flash driver. */
119 if (status)
120 {
121
122 /* Call system error handler. */
123 _lx_nand_flash_system_error(nand_flash, status, block, 0);
124
125 /* Return an error. */
126 return(status);
127 }
128
129 /* Increase current page for metadata block. */
130 nand_flash -> lx_nand_flash_metadata_block_current_page++;
131
132 /* Get current backup metadata block number. */
133 block = nand_flash -> lx_nand_flash_backup_metadata_block_number_current;
134
135 /* Get current backup metadata page number. */
136 page = nand_flash -> lx_nand_flash_backup_metadata_block_current_page;
137
138 /* Write the page. */
139 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
140 status = (nand_flash -> lx_nand_flash_driver_pages_write)(nand_flash, block, page, main_buffer, spare_buffer_ptr, 1);
141 #else
142 status = (nand_flash -> lx_nand_flash_driver_pages_write)(block, page, main_buffer, spare_buffer_ptr, 1);
143 #endif
144
145 /* Check for an error from flash driver. */
146 if (status)
147 {
148
149 /* Call system error handler. */
150 _lx_nand_flash_system_error(nand_flash, status, block, 0);
151
152 /* Return an error. */
153 return(status);
154 }
155
156 /* Increase current page for backup metadata block. */
157 nand_flash -> lx_nand_flash_backup_metadata_block_current_page++;
158
159 /* Allocate new block for metadata if necessary. */
160 _lx_nand_flash_metadata_allocate(nand_flash);
161
162 /* Return sector not found status. */
163 return(status);
164 }
165
166