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