16
16
*/
17
17
18
18
#include < algorithm>
19
- #include < cstdint>
20
- #include < cstring>
19
+ #include < memory>
20
+ #include < stdint.h>
21
+ #include < stdlib.h>
22
+ #include < string.h>
23
+
24
+ #include " platform/mbed_error.h"
21
25
#include " drivers/internal/SFDP.h"
22
26
23
27
#if (DEVICE_SPI || DEVICE_QSPI)
@@ -107,20 +111,69 @@ int sfdp_parse_single_param_header(sfdp_prm_hdr *phdr_ptr, sfdp_hdr_info &hdr_in
107
111
return -1 ;
108
112
}
109
113
110
- if ((phdr_ptr->PID_LSB == 0 ) && (sfdp_get_param_id_msb (phdr_ptr->DWORD2 ) == 0xFF )) {
111
- tr_debug (" Parameter header: Basic Parameter Header" );
112
- hdr_info.bptbl .addr = sfdp_get_param_tbl_ptr (phdr_ptr->DWORD2 );
113
- hdr_info.bptbl .size = std::min ((phdr_ptr->P_LEN * 4 ), SFDP_BASIC_PARAMS_TBL_SIZE);
114
+ int param_id_msb = sfdp_get_param_id_msb (phdr_ptr->DWORD2 );
114
115
115
- } else if ((phdr_ptr->PID_LSB == 0x81 ) && (sfdp_get_param_id_msb (phdr_ptr->DWORD2 ) == 0xFF )) {
116
- tr_debug (" Parameter header: Sector Map Parameter Header" );
117
- hdr_info.smptbl .addr = sfdp_get_param_tbl_ptr (phdr_ptr->DWORD2 );
118
- hdr_info.smptbl .size = phdr_ptr->P_LEN * 4 ;
116
+ /* MSB JEDEC ID */
117
+ if (param_id_msb == 0xFF ) {
119
118
120
- } else {
121
- tr_debug (" Parameter header: header vendor specific or unknown. Parameter ID LSB: 0x%" PRIX8 " ; MSB: 0x%" PRIX8 " " ,
119
+ /* LSB JEDEC ID */
120
+ switch (phdr_ptr->PID_LSB ) {
121
+ case 0x0 :
122
+ tr_debug (" Parameter header: JEDEC Basic Flash - Revision %" PRIX8 " .%" PRIX8 " " ,
123
+ phdr_ptr->P_MAJOR ,
124
+ phdr_ptr->P_MINOR );
125
+ hdr_info.bptbl .addr = sfdp_get_param_tbl_ptr (phdr_ptr->DWORD2 );
126
+ hdr_info.bptbl .size = std::min ((phdr_ptr->P_LEN * 4 ), SFDP_BASIC_PARAMS_TBL_SIZE);
127
+ break ;
128
+ case 0x81 :
129
+ tr_info (" Parameter header: Sector Map" );
130
+ hdr_info.smptbl .addr = sfdp_get_param_tbl_ptr (phdr_ptr->DWORD2 );
131
+ hdr_info.smptbl .size = phdr_ptr->P_LEN * 4 ;
132
+ break ;
133
+ /* Unsupported */
134
+ case 0x03 :
135
+ tr_info (" UNSUPPORTED:Parameter header: Replay Protected Monotonic Counters" );
136
+ break ;
137
+ case 0x84 :
138
+ tr_info (" UNSUPPORTED:Parameter header: 4-byte Address Instruction" );
139
+ break ;
140
+ case 0x05 :
141
+ tr_info (" UNSUPPORTED:Parameter header: eXtended Serial Peripheral Interface (xSPI) Profile 1.0" );
142
+ break ;
143
+ case 0x06 :
144
+ tr_info (" UNSUPPORTED:Parameter header: eXtended Serial Peripheral Interface (xSPI) Profile 2.0" );
145
+ break ;
146
+ case 0x87 :
147
+ tr_info (" UNSUPPORTED:Parameter header: SCCR Map for SPI Memory Devices" );
148
+ break ;
149
+ case 0x88 :
150
+ tr_info (" UNSUPPORTED:Parameter header: SCCR Map Offsets for Multi-Chip SPI Memory Devices" );
151
+ break ;
152
+ case 0x09 :
153
+ tr_info (" UNSUPPORTED:Parameter header: SCCR Map for xSPI Profile 2.0 Memory Devices" );
154
+ break ;
155
+ case 0x0A :
156
+ tr_info (" UNSUPPORTED:Parameter header: Command Sequences to Change to Octal DDR (8D-8D-8D) mode" );
157
+ break ;
158
+ case 0x0C :
159
+ tr_info (" UNSUPPORTED:Parameter header: x4 Quad IO with DS" );
160
+ break ;
161
+ case 0x8D :
162
+ tr_info (" UNSUPPORTED:Parameter header: Command Sequences to Change to Quad DDR (4S-4D-4D) mode" );
163
+ break ;
164
+ default :
165
+ tr_debug (" Parameter header: unknown JEDEC header. Parameter ID LSB: 0x%" PRIX8 " ; MSB: 0x%" PRIX8 " " ,
166
+ phdr_ptr->PID_LSB ,
167
+ sfdp_get_param_id_msb (phdr_ptr->DWORD2 ));
168
+ }
169
+ } else if (param_id_msb >= 0x80 ) { // MSB JEDEC ID
170
+ tr_debug (" Parameter header: unknown JEDEC header. Parameter ID LSB: 0x%" PRIX8 " ; MSB: 0x%" PRIX8 " " ,
122
171
phdr_ptr->PID_LSB ,
123
172
sfdp_get_param_id_msb (phdr_ptr->DWORD2 ));
173
+ } else { // MSB Vendor ID
174
+ tr_info (" Parameter header: vendor specific header. Parameter ID LSB: 0x%" PRIX8 " ; MSB: 0x%" PRIX8 " " ,
175
+ phdr_ptr->PID_LSB ,
176
+ sfdp_get_param_id_msb (phdr_ptr->DWORD2 ));
124
177
}
125
178
126
179
return 0 ;
@@ -157,10 +210,10 @@ int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
157
210
int hdr_status;
158
211
159
212
// Loop over Param Headers and parse them (currently supports Basic Param Table and Sector Region Map Table)
160
- for (int i_ind = 0 ; i_ind < number_of_param_headers; i_ind ++) {
213
+ for (int idx = 0 ; idx < number_of_param_headers; idx ++) {
161
214
status = sfdp_reader (addr, param_header, data_length);
162
215
if (status < 0 ) {
163
- tr_error (" Retrieving a parameter header %d failed" , i_ind + 1 );
216
+ tr_error (" Retrieving a parameter header %d failed" , idx + 1 );
164
217
return -1 ;
165
218
}
166
219
@@ -178,9 +231,8 @@ int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
178
231
179
232
int sfdp_parse_sector_map_table (Callback<int (bd_addr_t , void *, bd_size_t )> sfdp_reader, sfdp_hdr_info &sfdp_info)
180
233
{
181
- uint8_t sector_map_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 20 DWORDS = 80 Bytes */
182
234
uint32_t tmp_region_size = 0 ;
183
- int i_ind = 0 ;
235
+ uint8_t type_mask ;
184
236
int prev_boundary = 0 ;
185
237
// Default set to all type bits 1-4 are common
186
238
int min_common_erase_type_bits = SFDP_ERASE_BITMASK_ALL;
@@ -191,25 +243,36 @@ int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp
191
243
192
244
if (!sfdp_info.smptbl .addr || !sfdp_info.smptbl .size ) {
193
245
tr_debug (" No Sector Map Table" );
194
- return 0 ;
246
+ return MBED_SUCCESS ;
195
247
}
196
248
197
- tr_debug (" Parsing Sector Map Table - addr: 0x%" PRIx32 " , Size: %d" , sfdp_info.smptbl .addr , sfdp_info.smptbl .size );
249
+ /* The number of
250
+ * - sector map configuration detection commands
251
+ * - configurations
252
+ * - regions in each configuration
253
+ * is variable -> the size of this table is variable
254
+ */
255
+ auto smptbl_buff = std::make_unique<uint8_t []>(sfdp_info.smptbl .size );
256
+ if (!smptbl_buff) {
257
+ tr_error (" Failed to allocate memory" );
258
+ return -1 ;
259
+ }
198
260
261
+ tr_debug (" Parsing Sector Map Table - addr: 0x%" PRIx32 " , Size: %d" , sfdp_info.smptbl .addr , sfdp_info.smptbl .size );
199
262
200
- int status = sfdp_reader (sfdp_info.smptbl .addr , sector_map_table , sfdp_info.smptbl .size );
263
+ int status = sfdp_reader (sfdp_info.smptbl .addr , smptbl_buff. get () , sfdp_info.smptbl .size );
201
264
if (status < 0 ) {
202
265
tr_error (" Sector Map: Table retrieval failed" );
203
266
return -1 ;
204
267
}
205
268
206
269
// Currently we support only Single Map Descriptor
207
- if (!((sector_map_table [0 ] & 0x3 ) == 0x03 ) && (sector_map_table [1 ] == 0x0 )) {
270
+ if (!((smptbl_buff [0 ] & 0x3 ) == 0x03 ) && (smptbl_buff [1 ] == 0x0 )) {
208
271
tr_error (" Sector Map: Supporting Only Single Map Descriptor (not map commands)" );
209
272
return -1 ;
210
273
}
211
274
212
- sfdp_info.smptbl .region_cnt = sector_map_table [2 ] + 1 ;
275
+ sfdp_info.smptbl .region_cnt = smptbl_buff [2 ] + 1 ;
213
276
if (sfdp_info.smptbl .region_cnt > SFDP_SECTOR_MAP_MAX_REGIONS) {
214
277
tr_error (" Sector Map: Supporting up to %d regions, current setup to %d regions - fail" ,
215
278
SFDP_SECTOR_MAP_MAX_REGIONS,
@@ -219,34 +282,31 @@ int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp
219
282
220
283
// Loop through Regions and set for each one: size, supported erase types, high boundary offset
221
284
// Calculate minimum Common Erase Type for all Regions
222
- for (i_ind = 0 ; i_ind < sfdp_info.smptbl .region_cnt ; i_ind ++) {
223
- tmp_region_size = ((*((uint32_t *)§or_map_table[(i_ind + 1 ) * 4 ])) >> 8 ) & 0x00FFFFFF ; // bits 9-32
224
- sfdp_info.smptbl .region_size [i_ind ] = (tmp_region_size + 1 ) * 256 ; // Region size is 0 based multiple of 256 bytes;
285
+ for (auto idx = 0 ; idx < sfdp_info.smptbl .region_cnt ; idx ++) {
286
+ tmp_region_size = ((*((uint32_t *)&smptbl_buff[(idx + 1 ) * 4 ])) >> 8 ) & 0x00FFFFFF ; // bits 9-32
287
+ sfdp_info.smptbl .region_size [idx ] = (tmp_region_size + 1 ) * 256 ; // Region size is 0 based multiple of 256 bytes;
225
288
226
- sfdp_info.smptbl .region_erase_types_bitfld [i_ind ] = sector_map_table[(i_ind + 1 ) * 4 ] & 0x0F ; // bits 1-4
289
+ sfdp_info.smptbl .region_erase_types_bitfld [idx ] = smptbl_buff[(idx + 1 ) * 4 ] & 0x0F ; // bits 1-4
227
290
228
- min_common_erase_type_bits &= sfdp_info.smptbl .region_erase_types_bitfld [i_ind ];
291
+ min_common_erase_type_bits &= sfdp_info.smptbl .region_erase_types_bitfld [idx ];
229
292
230
- sfdp_info.smptbl .region_high_boundary [i_ind ] = (sfdp_info.smptbl .region_size [i_ind ] - 1 ) + prev_boundary;
293
+ sfdp_info.smptbl .region_high_boundary [idx ] = (sfdp_info.smptbl .region_size [idx ] - 1 ) + prev_boundary;
231
294
232
- prev_boundary = sfdp_info.smptbl .region_high_boundary [i_ind ] + 1 ;
295
+ prev_boundary = sfdp_info.smptbl .region_high_boundary [idx ] + 1 ;
233
296
}
234
297
235
298
// Calc minimum Common Erase Size from min_common_erase_type_bits
236
- uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE1;
237
- for (i_ind = 0 ; i_ind < 4 ; i_ind++) {
299
+ type_mask = SFDP_ERASE_BITMASK_TYPE1;
300
+ // If no common erase type is found between regions
301
+ sfdp_info.smptbl .regions_min_common_erase_size = 0 ;
302
+ for (auto idx = 0 ; idx < 4 ; idx++) {
238
303
if (min_common_erase_type_bits & type_mask) {
239
- sfdp_info.smptbl .regions_min_common_erase_size = sfdp_info.smptbl .erase_type_size_arr [i_ind ];
304
+ sfdp_info.smptbl .regions_min_common_erase_size = sfdp_info.smptbl .erase_type_size_arr [idx ];
240
305
break ;
241
306
}
242
307
type_mask = type_mask << 1 ;
243
308
}
244
309
245
- if (i_ind == 4 ) {
246
- // No common erase type was found between regions
247
- sfdp_info.smptbl .regions_min_common_erase_size = 0 ;
248
- }
249
-
250
310
return 0 ;
251
311
}
252
312
@@ -275,27 +335,27 @@ int sfdp_detect_erase_types_inst_and_size(uint8_t *bptbl_ptr, sfdp_hdr_info &sfd
275
335
// Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K
276
336
if (sfdp_info.bptbl .size > SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE) {
277
337
// Loop Erase Types 1-4
278
- for (int i_ind = 0 ; i_ind < 4 ; i_ind ++) {
279
- sfdp_info.smptbl .erase_type_inst_arr [i_ind ] = -1 ; // Default for unsupported type
280
- sfdp_info.smptbl .erase_type_size_arr [i_ind ] = 1
281
- << bptbl_ptr[SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind ]; // Size is 2^N where N is the table value
282
- tr_debug (" Erase Type(A) %d - Inst: 0x%xh, Size: %d" , (i_ind + 1 ), sfdp_info.smptbl .erase_type_inst_arr [i_ind ],
283
- sfdp_info.smptbl .erase_type_size_arr [i_ind ]);
284
- if (sfdp_info.smptbl .erase_type_size_arr [i_ind ] > 1 ) {
338
+ for (int idx = 0 ; idx < 4 ; idx ++) {
339
+ sfdp_info.smptbl .erase_type_inst_arr [idx ] = -1 ; // Default for unsupported type
340
+ sfdp_info.smptbl .erase_type_size_arr [idx ] = 1
341
+ << bptbl_ptr[SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE + 2 * idx ]; // Size is 2^N where N is the table value
342
+ tr_debug (" Erase Type(A) %d - Inst: 0x%xh, Size: %d" , (idx + 1 ), sfdp_info.smptbl .erase_type_inst_arr [idx ],
343
+ sfdp_info.smptbl .erase_type_size_arr [idx ]);
344
+ if (sfdp_info.smptbl .erase_type_size_arr [idx ] > 1 ) {
285
345
// if size==1 type is not supported
286
- sfdp_info.smptbl .erase_type_inst_arr [i_ind ] = bptbl_ptr[SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE
287
- + 2 * i_ind ];
346
+ sfdp_info.smptbl .erase_type_inst_arr [idx ] = bptbl_ptr[SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE
347
+ + 2 * idx ];
288
348
289
- if ((sfdp_info.smptbl .erase_type_size_arr [i_ind ] < sfdp_info.smptbl .regions_min_common_erase_size )
349
+ if ((sfdp_info.smptbl .erase_type_size_arr [idx ] < sfdp_info.smptbl .regions_min_common_erase_size )
290
350
|| (sfdp_info.smptbl .regions_min_common_erase_size == 0 )) {
291
351
// Set default minimal common erase for signal region
292
- sfdp_info.smptbl .regions_min_common_erase_size = sfdp_info.smptbl .erase_type_size_arr [i_ind ];
352
+ sfdp_info.smptbl .regions_min_common_erase_size = sfdp_info.smptbl .erase_type_size_arr [idx ];
293
353
}
294
354
sfdp_info.smptbl .region_erase_types_bitfld [0 ] |= bitfield; // If there's no region map, set region "0" types bitfield as default
295
355
}
296
356
297
- tr_debug (" Erase Type %d - Inst: 0x%xh, Size: %d" , (i_ind + 1 ), sfdp_info.smptbl .erase_type_inst_arr [i_ind ],
298
- sfdp_info.smptbl .erase_type_size_arr [i_ind ]);
357
+ tr_debug (" Erase Type %d - Inst: 0x%xh, Size: %d" , (idx + 1 ), sfdp_info.smptbl .erase_type_inst_arr [idx ],
358
+ sfdp_info.smptbl .erase_type_size_arr [idx ]);
299
359
bitfield = bitfield << 1 ;
300
360
}
301
361
} else {
@@ -321,10 +381,10 @@ int sfdp_find_addr_region(bd_size_t offset, const sfdp_hdr_info &sfdp_info)
321
381
return 0 ;
322
382
}
323
383
324
- for (int i_ind = sfdp_info.smptbl .region_cnt - 2 ; i_ind >= 0 ; i_ind --) {
384
+ for (int idx = sfdp_info.smptbl .region_cnt - 2 ; idx >= 0 ; idx --) {
325
385
326
- if (offset > sfdp_info.smptbl .region_high_boundary [i_ind ]) {
327
- return (i_ind + 1 );
386
+ if (offset > sfdp_info.smptbl .region_high_boundary [idx ]) {
387
+ return (idx + 1 );
328
388
}
329
389
}
330
390
return -1 ;
@@ -338,11 +398,12 @@ int sfdp_iterate_next_largest_erase_type(uint8_t &bitfield,
338
398
const sfdp_smptbl_info &smptbl)
339
399
{
340
400
uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE4;
341
- int i_ind = 0 ;
342
401
int largest_erase_type = 0 ;
343
- for (i_ind = 3 ; i_ind >= 0 ; i_ind--) {
402
+
403
+ int idx;
404
+ for (idx = 3 ; idx >= 0 ; idx--) {
344
405
if (bitfield & type_mask) {
345
- largest_erase_type = i_ind ;
406
+ largest_erase_type = idx ;
346
407
if ((size > (int )(smptbl.erase_type_size_arr [largest_erase_type])) &&
347
408
((smptbl.region_high_boundary [region] - offset)
348
409
> (int )(smptbl.erase_type_size_arr [largest_erase_type]))) {
@@ -354,7 +415,7 @@ int sfdp_iterate_next_largest_erase_type(uint8_t &bitfield,
354
415
type_mask = type_mask >> 1 ;
355
416
}
356
417
357
- if (i_ind == 4 ) {
418
+ if (idx == - 1 ) {
358
419
tr_error (" No erase type was found for current region addr" );
359
420
}
360
421
return largest_erase_type;
0 commit comments