Skip to content

Commit 5772266

Browse files
author
Veijo Pesonen
committed
SPIFBlockDevice: Consolidates SFDP info data
This far all SFDP Sector Map Table related data has been found in small pieces inside SPIFBlockDevice. Purpose was to consolidate the data under one SFDP structure where all the information gathered from SFDP tables is stored. More generic version of a function used for parsing a Sector Map Table was taken into use to avoid duplicate code. The implementation taken into use is the one which got split from QSPIFBlockDevice and resides now under the SFDP module.
1 parent 83c0fdf commit 5772266

File tree

3 files changed

+68
-130
lines changed

3 files changed

+68
-130
lines changed

components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp

Lines changed: 53 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,9 @@ SPIFBlockDevice::SPIFBlockDevice(
107107
_write_dummy_and_mode_cycles = 0;
108108
_dummy_and_mode_cycles = _read_dummy_and_mode_cycles;
109109

110-
_min_common_erase_size = 0;
111-
_regions_count = 1;
112-
_region_erase_types_bitfield[0] = SFDP_ERASE_BITMASK_NONE;
110+
_sfdp_info.smtbl.regions_min_common_erase_size = 0;
111+
_sfdp_info.smtbl.region_cnt = 1;
112+
_sfdp_info.smtbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE;
113113

114114
if (SPIF_BD_ERROR_OK != _spi_set_frequency(freq)) {
115115
tr_error("SPI Set Frequency Failed");
@@ -190,14 +190,15 @@ int SPIFBlockDevice::init()
190190
}
191191

192192
/**************************** Parse Sector Map Table ***********************************/
193-
_region_size_bytes[0] =
193+
_sfdp_info.smtbl.region_size[0] =
194194
_device_size_bytes; // If there's no region map, we have a single region sized the entire device size
195-
_region_high_boundary[0] = _device_size_bytes - 1;
195+
_sfdp_info.smtbl.region_high_boundary[0] = _device_size_bytes - 1;
196196

197197
if ((hdr_info.smtbl.addr != 0) && (0 != hdr_info.smtbl.size)) {
198198
tr_debug("init - Parsing Sector Map Table - addr: 0x%" PRIx32 "h, Size: %d", hdr_info.smtbl.addr,
199199
hdr_info.smtbl.size);
200-
if (0 != _sfdp_parse_sector_map_table(hdr_info.smtbl.addr, hdr_info.smtbl.size)) {
200+
if (sfdp_parse_sector_map_table(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command),
201+
_sfdp_info.smtbl) < 0) {
201202
tr_error("init - Parse Sector Map Table Failed");
202203
status = SPIF_BD_ERROR_PARSING_FAILED;
203204
goto exit_point;
@@ -341,13 +342,13 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
341342
bool erase_failed = false;
342343
int status = SPIF_BD_ERROR_OK;
343344
// Find region of erased address
344-
int region = _utils_find_addr_region(addr);
345+
int region = _utils_find_addr_region(addr, _sfdp_info.smtbl);
345346
if (region < 0) {
346347
tr_error("no region found for address %llu", addr);
347348
return SPIF_BD_ERROR_INVALID_ERASE_PARAMS;
348349
}
349350
// Erase Types of selected region
350-
uint8_t bitfield = _region_erase_types_bitfield[region];
351+
uint8_t bitfield = _sfdp_info.smtbl.region_erase_types_bitfld[region];
351352

352353
tr_debug("erase - addr: %llu, in_size: %llu", addr, in_size);
353354

@@ -366,10 +367,11 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
366367

367368
// iterate to find next Largest erase type ( a. supported by region, b. smaller than size)
368369
// find the matching instruction and erase size chunk for that type.
369-
type = _utils_iterate_next_largest_erase_type(bitfield, size, (unsigned int)addr, _region_high_boundary[region]);
370-
cur_erase_inst = _erase_type_inst_arr[type];
371-
offset = addr % _erase_type_size_arr[type];
372-
chunk = ((offset + size) < _erase_type_size_arr[type]) ? size : (_erase_type_size_arr[type] - offset);
370+
type = _utils_iterate_next_largest_erase_type(bitfield, size, (unsigned int)addr, region, _sfdp_info.smtbl);
371+
cur_erase_inst = _sfdp_info.smtbl.erase_type_inst_arr[type];
372+
offset = addr % _sfdp_info.smtbl.erase_type_size_arr[type];
373+
chunk = ((offset + size) < _sfdp_info.smtbl.erase_type_size_arr[type]) ?
374+
size : (_sfdp_info.smtbl.erase_type_size_arr[type] - offset);
373375

374376
tr_debug("erase - addr: %llu, size:%d, Inst: 0x%xh, chunk: %" PRIu32 " , ",
375377
addr, size, cur_erase_inst, chunk);
@@ -390,10 +392,10 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
390392
addr += chunk;
391393
size -= chunk;
392394

393-
if ((size > 0) && (addr > _region_high_boundary[region])) {
395+
if ((size > 0) && (addr > _sfdp_info.smtbl.region_high_boundary[region])) {
394396
// erase crossed to next region
395397
region++;
396-
bitfield = _region_erase_types_bitfield[region];
398+
bitfield = _sfdp_info.smtbl.region_erase_types_bitfld[region];
397399
}
398400

399401
if (false == _is_mem_ready()) {
@@ -429,16 +431,16 @@ bd_size_t SPIFBlockDevice::get_program_size() const
429431
bd_size_t SPIFBlockDevice::get_erase_size() const
430432
{
431433
// return minimal erase size supported by all regions (0 if none exists)
432-
return _min_common_erase_size;
434+
return _sfdp_info.smtbl.regions_min_common_erase_size;
433435
}
434436

435437
// Find minimal erase size supported by the region to which the address belongs to
436438
bd_size_t SPIFBlockDevice::get_erase_size(bd_addr_t addr) const
437439
{
438440
// Find region of current address
439-
int region = _utils_find_addr_region(addr);
441+
int region = _utils_find_addr_region(addr, _sfdp_info.smtbl);
440442

441-
unsigned int min_region_erase_size = _min_common_erase_size;
443+
unsigned int min_region_erase_size = _sfdp_info.smtbl.regions_min_common_erase_size;
442444
int8_t type_mask = SFDP_ERASE_BITMASK_TYPE1;
443445
int i_ind = 0;
444446

@@ -447,9 +449,9 @@ bd_size_t SPIFBlockDevice::get_erase_size(bd_addr_t addr) const
447449

448450
for (i_ind = 0; i_ind < 4; i_ind++) {
449451
// loop through erase types bitfield supported by region
450-
if (_region_erase_types_bitfield[region] & type_mask) {
452+
if (_sfdp_info.smtbl.region_erase_types_bitfld[region] & type_mask) {
451453

452-
min_region_erase_size = _erase_type_size_arr[i_ind];
454+
min_region_erase_size = _sfdp_info.smtbl.erase_type_size_arr[i_ind];
453455
break;
454456
}
455457
type_mask = type_mask << 1;
@@ -618,65 +620,6 @@ spif_bd_error SPIFBlockDevice::_spi_send_general_command(int instruction, bd_add
618620
/*********************************************************/
619621
/********** SFDP Parsing and Detection Functions *********/
620622
/*********************************************************/
621-
int SPIFBlockDevice::_sfdp_parse_sector_map_table(uint32_t sector_map_table_addr, size_t sector_map_table_size)
622-
{
623-
uint8_t sector_map_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
624-
uint32_t tmp_region_size = 0;
625-
int i_ind = 0;
626-
int prev_boundary = 0;
627-
// Default set to all type bits 1-4 are common
628-
int min_common_erase_type_bits = SFDP_ERASE_BITMASK_ALL;
629-
630-
631-
spif_bd_error status = _spi_send_read_command(SPIF_SFDP, sector_map_table, sector_map_table_addr /*address*/,
632-
sector_map_table_size);
633-
if (status != SPIF_BD_ERROR_OK) {
634-
tr_error("init - Read SFDP First Table Failed");
635-
return -1;
636-
}
637-
638-
// Currently we support only Single Map Descriptor
639-
if (!((sector_map_table[0] & 0x3) == 0x03) && (sector_map_table[1] == 0x0)) {
640-
tr_error("Sector Map - Supporting Only Single! Map Descriptor (not map commands)");
641-
return -1;
642-
}
643-
644-
_regions_count = sector_map_table[2] + 1;
645-
if (_regions_count > SPIF_MAX_REGIONS) {
646-
tr_error("Supporting up to %d regions, current setup to %d regions - fail",
647-
SPIF_MAX_REGIONS, _regions_count);
648-
return -1;
649-
}
650-
651-
// Loop through Regions and set for each one: size, supported erase types, high boundary offset
652-
// Calculate minimum Common Erase Type for all Regions
653-
for (i_ind = 0; i_ind < _regions_count; i_ind++) {
654-
tmp_region_size = ((*((uint32_t *)&sector_map_table[(i_ind + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32
655-
_region_size_bytes[i_ind] = (tmp_region_size + 1) * 256; // Region size is 0 based multiple of 256 bytes;
656-
_region_erase_types_bitfield[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4
657-
min_common_erase_type_bits &= _region_erase_types_bitfield[i_ind];
658-
_region_high_boundary[i_ind] = (_region_size_bytes[i_ind] - 1) + prev_boundary;
659-
prev_boundary = _region_high_boundary[i_ind] + 1;
660-
}
661-
662-
// Calc minimum Common Erase Size from min_common_erase_type_bits
663-
uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE1;
664-
for (i_ind = 0; i_ind < 4; i_ind++) {
665-
if (min_common_erase_type_bits & type_mask) {
666-
_min_common_erase_size = _erase_type_size_arr[i_ind];
667-
break;
668-
}
669-
type_mask = type_mask << 1;
670-
}
671-
672-
if (i_ind == 4) {
673-
// No common erase type was found between regions
674-
_min_common_erase_size = 0;
675-
}
676-
677-
return 0;
678-
}
679-
680623
int SPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size)
681624
{
682625
uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
@@ -713,8 +656,7 @@ int SPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, si
713656
_page_size_bytes = _sfdp_detect_page_size(param_table, basic_table_size);
714657

715658
// Detect and Set Erase Types
716-
_sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _erase4k_inst, _erase_type_inst_arr,
717-
_erase_type_size_arr);
659+
_sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _erase4k_inst, _sfdp_info.smtbl);
718660
_erase_instruction = _erase4k_inst;
719661

720662
// Detect and Set fastest Bus mode (default 1-1-1)
@@ -745,7 +687,7 @@ unsigned int SPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_
745687

746688
int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size,
747689
int &erase4k_inst,
748-
int *erase_type_inst_arr, unsigned int *erase_type_size_arr)
690+
sfdp_smtbl_info &smtbl)
749691
{
750692
erase4k_inst = 0xff;
751693
bool found_4Kerase_type = false;
@@ -757,34 +699,36 @@ int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param
757699
if (basic_param_table_size > SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE) {
758700
// Loop Erase Types 1-4
759701
for (int i_ind = 0; i_ind < 4; i_ind++) {
760-
erase_type_inst_arr[i_ind] = 0xff; //0xFF default for unsupported type
761-
erase_type_size_arr[i_ind] = local_math_power(2,
762-
basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); // Size given as 2^N
763-
tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), erase_type_inst_arr[i_ind],
764-
erase_type_size_arr[i_ind]);
765-
if (erase_type_size_arr[i_ind] > 1) {
702+
smtbl.erase_type_inst_arr[i_ind] = 0xff; //0xFF default for unsupported type
703+
smtbl.erase_type_size_arr[i_ind] = local_math_power(
704+
2, basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); // Size given as 2^N
705+
tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smtbl.erase_type_inst_arr[i_ind],
706+
smtbl.erase_type_size_arr[i_ind]);
707+
if (smtbl.erase_type_size_arr[i_ind] > 1) {
766708
// if size==1 type is not supported
767-
erase_type_inst_arr[i_ind] = basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind];
709+
smtbl.erase_type_inst_arr[i_ind] =
710+
basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind];
768711

769-
if ((erase_type_size_arr[i_ind] < _min_common_erase_size) || (_min_common_erase_size == 0)) {
712+
if ((smtbl.erase_type_size_arr[i_ind] < smtbl.regions_min_common_erase_size)
713+
|| (smtbl.regions_min_common_erase_size == 0)) {
770714
//Set default minimal common erase for singal region
771-
_min_common_erase_size = erase_type_size_arr[i_ind];
715+
smtbl.regions_min_common_erase_size = smtbl.erase_type_size_arr[i_ind];
772716
}
773717

774718
// SFDP standard requires 4K Erase type to exist and its instruction to be identical to legacy field erase instruction
775-
if (erase_type_size_arr[i_ind] == 4096) {
719+
if (smtbl.erase_type_size_arr[i_ind] == 4096) {
776720
found_4Kerase_type = true;
777-
if (erase4k_inst != erase_type_inst_arr[i_ind]) {
721+
if (erase4k_inst != smtbl.erase_type_inst_arr[i_ind]) {
778722
//Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table
779-
erase4k_inst = erase_type_inst_arr[i_ind];
723+
erase4k_inst = smtbl.erase_type_inst_arr[i_ind];
780724
tr_warning("_detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K");
781725

782726
}
783727
}
784-
_region_erase_types_bitfield[0] |= bitfield; // If there's no region map, set region "0" types bitfield as defualt;
728+
smtbl.region_erase_types_bitfld[0] |= bitfield; // no region map, set region "0" types bitfield as default
785729
}
786730
tr_info("Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1),
787-
erase_type_inst_arr[i_ind], erase_type_size_arr[i_ind]);
731+
smtbl.erase_type_inst_arr[i_ind], smtbl.erase_type_size_arr[i_ind]);
788732
bitfield = bitfield << 1;
789733
}
790734
}
@@ -912,28 +856,32 @@ int SPIFBlockDevice::_set_write_enable()
912856
/*********************************************/
913857
/************* Utility Functions *************/
914858
/*********************************************/
915-
int SPIFBlockDevice::_utils_find_addr_region(bd_size_t offset) const
859+
int SPIFBlockDevice::_utils_find_addr_region(bd_size_t offset, const sfdp_smtbl_info &smtbl) const
916860
{
917861
//Find the region to which the given offset belong to
918-
if ((offset > _device_size_bytes) || (_regions_count == 0)) {
862+
if ((offset > _device_size_bytes) || (smtbl.region_cnt == 0)) {
919863
return -1;
920864
}
921865

922-
if (_regions_count == 1) {
866+
if (smtbl.region_cnt == 1) {
923867
return 0;
924868
}
925869

926-
for (int i_ind = _regions_count - 2; i_ind >= 0; i_ind--) {
870+
for (int i_ind = smtbl.region_cnt - 2; i_ind >= 0; i_ind--) {
927871

928-
if (offset > _region_high_boundary[i_ind]) {
872+
if (offset > smtbl.region_high_boundary[i_ind]) {
929873
return (i_ind + 1);
930874
}
931875
}
932876
return -1;
933877

934878
}
935879

936-
int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry)
880+
int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield,
881+
int size,
882+
int offset,
883+
int region,
884+
sfdp_smtbl_info &smtbl)
937885
{
938886
// Iterate on all supported Erase Types of the Region to which the offset belong to.
939887
// Iterates from highest type to lowest
@@ -943,8 +891,9 @@ int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, i
943891
for (i_ind = 3; i_ind >= 0; i_ind--) {
944892
if (bitfield & type_mask) {
945893
largest_erase_type = i_ind;
946-
if ((size > (int)(_erase_type_size_arr[largest_erase_type])) &&
947-
((boundry - offset) > (int)(_erase_type_size_arr[largest_erase_type]))) {
894+
if ((size > (int)(smtbl.erase_type_size_arr[largest_erase_type])) &&
895+
((_sfdp_info.smtbl.region_high_boundary[region] - offset)
896+
> (int)(smtbl.erase_type_size_arr[largest_erase_type]))) {
948897
break;
949898
} else {
950899
bitfield &= ~type_mask;
@@ -954,10 +903,9 @@ int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, i
954903
}
955904

956905
if (i_ind == 4) {
957-
tr_error("no erase type was found for current region addr");
906+
tr_error("No erase type was found for current region addr");
958907
}
959908
return largest_erase_type;
960-
961909
}
962910

963911
/*********************************************/

components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,6 @@ enum spif_bd_error {
5252
};
5353

5454

55-
#define SPIF_MAX_REGIONS 10
56-
#define MAX_NUM_OF_ERASE_TYPES 4
57-
5855
/** BlockDevice for SFDP based flash devices over SPI bus
5956
*
6057
* @code
@@ -222,6 +219,10 @@ class SPIFBlockDevice : public mbed::BlockDevice {
222219

223220
// Internal functions
224221

222+
// SFDP helpers
223+
friend int mbed::sfdp_parse_headers(mbed::Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
224+
mbed::sfdp_hdr_info &hdr_info);
225+
225226
/****************************************/
226227
/* SFDP Detection and Parsing Functions */
227228
/****************************************/
@@ -234,9 +235,6 @@ class SPIFBlockDevice : public mbed::BlockDevice {
234235
// Parse and Detect required Basic Parameters from Table
235236
int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size);
236237

237-
// Parse and read information required by Regions Sector Map
238-
int _sfdp_parse_sector_map_table(uint32_t sector_map_table_addr, size_t sector_map_table_size);
239-
240238
// Detect fastest read Bus mode supported by device
241239
int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, int &read_inst);
242240

@@ -246,17 +244,21 @@ class SPIFBlockDevice : public mbed::BlockDevice {
246244
// Detect all supported erase types
247245
int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size,
248246
int &erase4k_inst,
249-
int *erase_type_inst_arr, unsigned int *erase_type_size_arr);
247+
mbed::sfdp_smtbl_info &smtbl);
250248

251249
/***********************/
252250
/* Utilities Functions */
253251
/***********************/
254252
// Find the region to which the given offset belongs to
255-
int _utils_find_addr_region(bd_size_t offset) const;
253+
int _utils_find_addr_region(bd_size_t offset, const mbed::sfdp_smtbl_info &smtbl) const;
256254

257255
// Iterate on all supported Erase Types of the Region to which the offset belongs to.
258256
// Iterates from highest type to lowest
259-
int _utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry);
257+
int _utils_iterate_next_largest_erase_type(uint8_t &bitfield,
258+
int size,
259+
int offset,
260+
int region,
261+
mbed::sfdp_smtbl_info &smtbl);
260262

261263
/********************************/
262264
/* Calls to SPI Driver APIs */
@@ -304,22 +306,8 @@ class SPIFBlockDevice : public mbed::BlockDevice {
304306
int _erase_instruction;
305307
int _erase4k_inst; // Legacy 4K erase instruction (default 0x20h)
306308

307-
// SFDP helpers
308-
friend int mbed::sfdp_parse_headers(mbed::Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
309-
mbed::sfdp_hdr_info &hdr_info);
310-
311-
312-
// Up To 4 Erase Types are supported by SFDP (each with its own command Instruction and Size)
313-
int _erase_type_inst_arr[MAX_NUM_OF_ERASE_TYPES];
314-
unsigned int _erase_type_size_arr[MAX_NUM_OF_ERASE_TYPES];
315-
316-
// Sector Regions Map
317-
int _regions_count; //number of regions
318-
int _region_size_bytes[SPIF_MAX_REGIONS]; //regions size in bytes
319-
bd_size_t _region_high_boundary[SPIF_MAX_REGIONS]; //region high address offset boundary
320-
//Each Region can support a bit combination of any of the 4 Erase Types
321-
uint8_t _region_erase_types_bitfield[SPIF_MAX_REGIONS];
322-
unsigned int _min_common_erase_size; // minimal common erase size for all regions (0 if none exists)
309+
// Data extracted from the devices SFDP structure
310+
mbed::sfdp_hdr_info _sfdp_info;
323311

324312
unsigned int _page_size_bytes; // Page size - 256 Bytes default
325313
bd_size_t _device_size_bytes;

drivers/internal/SFDP.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ static const int SFDP_SECTOR_MAP_MAX_REGIONS = 10;
3131

3232
// Erase Types Per Region BitMask
3333
static const int SFDP_ERASE_BITMASK_TYPE4 = 0x08;
34+
static const int SFDP_ERASE_BITMASK_TYPE3 = 0x04;
35+
static const int SFDP_ERASE_BITMASK_TYPE2 = 0x02;
3436
static const int SFDP_ERASE_BITMASK_TYPE1 = 0x01;
3537
static const int SFDP_ERASE_BITMASK_NONE = 0x00;
3638
static const int SFDP_ERASE_BITMASK_ALL = 0x0F;

0 commit comments

Comments
 (0)