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 /** NOR Flash Simulator */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22
23 /* Include necessary files. */
24
25 #include "lx_api.h"
26
27 /* Define constants for the NOR flash simulation. */
28
29 /* This configuration is for one physical sector of overhead. */
30
31
32 #define TOTAL_BLOCKS 8
33 #define PHYSICAL_SECTORS_PER_BLOCK 16 /* Min value of 2, max value of 120 for 1 sector of overhead. */
34 #define WORDS_PER_PHYSICAL_SECTOR 128
35 #define FREE_BIT_MAP_WORDS ((PHYSICAL_SECTORS_PER_BLOCK-1)/32)+1
36 #define USABLE_SECTORS_PER_BLOCK (PHYSICAL_SECTORS_PER_BLOCK-1)
37 #define UNUSED_METADATA_WORDS_PER_BLOCK (WORDS_PER_PHYSICAL_SECTOR-(3+FREE_BIT_MAP_WORDS+USABLE_SECTORS_PER_BLOCK))
38
39
40 typedef struct PHYSICAL_SECTOR_STRUCT
41 {
42 unsigned long memory[WORDS_PER_PHYSICAL_SECTOR];
43 } PHYSICAL_SECTOR;
44
45
46 typedef struct FLASH_BLOCK_STRUCT
47 {
48 unsigned long erase_count;
49 unsigned long min_log_sector;
50 unsigned long max_log_sector;
51 unsigned long free_bit_map[FREE_BIT_MAP_WORDS];
52 unsigned long sector_metadata[USABLE_SECTORS_PER_BLOCK];
53 unsigned long unused_words[UNUSED_METADATA_WORDS_PER_BLOCK];
54 PHYSICAL_SECTOR physical_sectors[USABLE_SECTORS_PER_BLOCK];
55 } FLASH_BLOCK;
56
57 FLASH_BLOCK nor_memory_area[TOTAL_BLOCKS];
58
59 ULONG nor_sector_memory[WORDS_PER_PHYSICAL_SECTOR];
60
61 UINT _lx_nor_flash_simulator_initialize(LX_NOR_FLASH *nor_flash);
62 UINT _lx_nor_flash_simulator_erase_all(VOID);
63 #ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
64 UINT _lx_nor_flash_simulator_read(LX_NOR_FLASH *nor_flash, ULONG *flash_address, ULONG *destination, ULONG words);
65 UINT _lx_nor_flash_simulator_write(LX_NOR_FLASH *nor_flash, ULONG *flash_address, ULONG *source, ULONG words);
66 UINT _lx_nor_flash_simulator_block_erase(LX_NOR_FLASH *nor_flash, ULONG block, ULONG erase_count);
67 UINT _lx_nor_flash_simulator_block_erased_verify(LX_NOR_FLASH *nor_flash, ULONG block);
68 UINT _lx_nor_flash_simulator_system_error(LX_NOR_FLASH *nor_flash, UINT error_code, ULONG block, ULONG sector);
69 #else
70 UINT _lx_nor_flash_simulator_read(ULONG *flash_address, ULONG *destination, ULONG words);
71 UINT _lx_nor_flash_simulator_write(ULONG *flash_address, ULONG *source, ULONG words);
72 UINT _lx_nor_flash_simulator_block_erase(ULONG block, ULONG erase_count);
73 UINT _lx_nor_flash_simulator_block_erased_verify(ULONG block);
74 UINT _lx_nor_flash_simulator_system_error(UINT error_code, ULONG block, ULONG sector);
75 #endif
76
77
_lx_nor_flash_simulator_initialize(LX_NOR_FLASH * nor_flash)78 UINT _lx_nor_flash_simulator_initialize(LX_NOR_FLASH *nor_flash)
79 {
80
81 /* Setup the base address of the flash memory. */
82 nor_flash -> lx_nor_flash_base_address = (ULONG *) &nor_memory_area[0];
83
84 /* Setup geometry of the flash. */
85 nor_flash -> lx_nor_flash_total_blocks = TOTAL_BLOCKS;
86 nor_flash -> lx_nor_flash_words_per_block = sizeof(FLASH_BLOCK)/sizeof(ULONG);
87
88 /* Setup function pointers for the NOR flash services. */
89 nor_flash -> lx_nor_flash_driver_read = _lx_nor_flash_simulator_read;
90 nor_flash -> lx_nor_flash_driver_write = _lx_nor_flash_simulator_write;
91 nor_flash -> lx_nor_flash_driver_block_erase = _lx_nor_flash_simulator_block_erase;
92 nor_flash -> lx_nor_flash_driver_block_erased_verify = _lx_nor_flash_simulator_block_erased_verify;
93
94 /* Setup local buffer for NOR flash operation. This buffer must be the sector size of the NOR flash memory. */
95 nor_flash -> lx_nor_flash_sector_buffer = &nor_sector_memory[0];
96
97 /* Return success. */
98 return(LX_SUCCESS);
99 }
100
101 #ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nor_flash_simulator_read(LX_NOR_FLASH * nor_flash,ULONG * flash_address,ULONG * destination,ULONG words)102 UINT _lx_nor_flash_simulator_read(LX_NOR_FLASH *nor_flash, ULONG *flash_address, ULONG *destination, ULONG words)
103 #else
104 UINT _lx_nor_flash_simulator_read(ULONG *flash_address, ULONG *destination, ULONG words)
105 #endif
106 {
107
108 #ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
109 LX_PARAMETER_NOT_USED(nor_flash);
110 #endif
111
112 /* Loop to read flash. */
113 while (words--)
114 {
115 /* Copy word. */
116 *destination++ = *flash_address++;
117 }
118
119 return(LX_SUCCESS);
120 }
121
122
123 #ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nor_flash_simulator_write(LX_NOR_FLASH * nor_flash,ULONG * flash_address,ULONG * source,ULONG words)124 UINT _lx_nor_flash_simulator_write(LX_NOR_FLASH *nor_flash, ULONG *flash_address, ULONG *source, ULONG words)
125 #else
126 UINT _lx_nor_flash_simulator_write(ULONG *flash_address, ULONG *source, ULONG words)
127 #endif
128 {
129
130 #ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
131 LX_PARAMETER_NOT_USED(nor_flash);
132 #endif
133
134 /* Loop to write flash. */
135 while (words--)
136 {
137
138 /* Copy word. */
139 *flash_address++ = *source++;
140 }
141
142 return(LX_SUCCESS);
143 }
144
145 #ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nor_flash_simulator_block_erase(LX_NOR_FLASH * nor_flash,ULONG block,ULONG erase_count)146 UINT _lx_nor_flash_simulator_block_erase(LX_NOR_FLASH *nor_flash, ULONG block, ULONG erase_count)
147 #else
148 UINT _lx_nor_flash_simulator_block_erase(ULONG block, ULONG erase_count)
149 #endif
150 {
151
152 ULONG *pointer;
153 ULONG words;
154
155 #ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
156 LX_PARAMETER_NOT_USED(nor_flash);
157 #endif
158 LX_PARAMETER_NOT_USED(erase_count);
159
160 /* Setup pointer. */
161 pointer = (ULONG *) &nor_memory_area[block];
162
163 /* Loop to erase block. */
164 words = sizeof(FLASH_BLOCK)/sizeof(ULONG);
165 while (words--)
166 {
167
168 /* Erase word of block. */
169 *pointer++ = (ULONG) 0xFFFFFFFF;
170 }
171
172 return(LX_SUCCESS);
173 }
174
175
_lx_nor_flash_simulator_erase_all(VOID)176 UINT _lx_nor_flash_simulator_erase_all(VOID)
177 {
178
179 ULONG *pointer;
180 ULONG words;
181
182
183 /* Setup pointer. */
184 pointer = (ULONG *) &nor_memory_area[0];
185
186 /* Loop to erase block. */
187 words = sizeof(nor_memory_area)/(sizeof(ULONG));
188 while (words--)
189 {
190
191 /* Erase word of block. */
192 *pointer++ = (ULONG) 0xFFFFFFFF;
193 }
194
195 return(LX_SUCCESS);
196 }
197
198
199 #ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nor_flash_simulator_block_erased_verify(LX_NOR_FLASH * nor_flash,ULONG block)200 UINT _lx_nor_flash_simulator_block_erased_verify(LX_NOR_FLASH *nor_flash, ULONG block)
201 #else
202 UINT _lx_nor_flash_simulator_block_erased_verify(ULONG block)
203 #endif
204 {
205
206 ULONG *word_ptr;
207 ULONG words;
208
209 #ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
210 LX_PARAMETER_NOT_USED(nor_flash);
211 #endif
212
213 /* Determine if the block is completely erased. */
214
215 /* Pickup the pointer to the first word of the block. */
216 word_ptr = (ULONG *) &nor_memory_area[block].erase_count;
217
218 /* Calculate the number of words in a block. */
219 words = sizeof(FLASH_BLOCK)/sizeof(ULONG);
220
221 /* Loop to check if the block is erased. */
222 while (words--)
223 {
224
225 /* Is this word erased? */
226 if (*word_ptr++ != 0xFFFFFFFF)
227 return(LX_ERROR);
228 }
229
230 /* Return success. */
231 return(LX_SUCCESS);
232 }
233
234 #ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nor_flash_simulator_system_error(LX_NOR_FLASH * nor_flash,UINT error_code,ULONG block,ULONG sector)235 UINT _lx_nor_flash_simulator_system_error(LX_NOR_FLASH *nor_flash, UINT error_code, ULONG block, ULONG sector)
236 #else
237 UINT _lx_nor_flash_simulator_system_error(UINT error_code, ULONG block, ULONG sector)
238 #endif
239 {
240
241 #ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
242 LX_PARAMETER_NOT_USED(nor_flash);
243 #endif
244 LX_PARAMETER_NOT_USED(error_code);
245 LX_PARAMETER_NOT_USED(block);
246 LX_PARAMETER_NOT_USED(sector);
247
248 /* Custom processing goes here... all errors are fatal. */
249 return(LX_ERROR);
250 }
251
252