Skip to content

Commit ca704a4

Browse files
author
Veijo Pesonen
committed
SFDP: consolidates erase region search
Merges erase region search found from SPIFBlockDevice and QSPIFBlockDevice. Moves the implementation within the SFDP component
1 parent ca52ca9 commit ca704a4

File tree

6 files changed

+107
-160
lines changed

6 files changed

+107
-160
lines changed

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp

Lines changed: 17 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,12 @@ PinName *QSPIFBlockDevice::_active_qspif_flash_csel_arr = generate_initialized_a
125125
/********* Public API Functions *********/
126126
/****************************************/
127127
QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName csel,
128-
int clock_mode, int freq)
129-
: _qspi(io0, io1, io2, io3, sclk, csel, clock_mode), _csel(csel), _freq(freq), _device_size_bytes(0),
130-
_init_ref_count(0),
131-
_is_initialized(false)
128+
int clock_mode,
129+
int freq)
130+
:
131+
_qspi(io0, io1, io2, io3, sclk, csel, clock_mode), _csel(csel), _freq(freq),
132+
_init_ref_count(0),
133+
_is_initialized(false)
132134
{
133135
_unique_device_status = add_new_csel_instance(csel);
134136

@@ -142,6 +144,7 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam
142144

143145
// Initialize parameters
144146
_sfdp_info.bptbl.legacy_erase_instruction = QSPIF_INST_LEGACY_ERASE_DEFAULT;
147+
_sfdp_info.bptbl.device_size_bytes = 0;
145148
_sfdp_info.smptbl.regions_min_common_erase_size = 0;
146149
_sfdp_info.smptbl.region_cnt = 1;
147150
_sfdp_info.smptbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE;
@@ -249,9 +252,8 @@ int QSPIFBlockDevice::init()
249252
}
250253

251254
/**************************** Parse Sector Map Table ***********************************/
252-
_sfdp_info.smptbl.region_size[0] =
253-
_device_size_bytes; // If there's no region map, we have a single region sized the entire device size
254-
_sfdp_info.smptbl.region_high_boundary[0] = _device_size_bytes - 1;
255+
_sfdp_info.smptbl.region_size[0] = _sfdp_info.bptbl.device_size_bytes; // If there's no region map, we have a single region sized the entire device size
256+
_sfdp_info.smptbl.region_high_boundary[0] = _sfdp_info.bptbl.device_size_bytes - 1;
255257

256258
if ((_sfdp_info.smptbl.addr != 0) && (0 != _sfdp_info.smptbl.size)) {
257259
tr_debug("Init - Parsing Sector Map Table - addr: 0x%lxh, Size: %d", _sfdp_info.smptbl.addr,
@@ -399,13 +401,13 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
399401
bool erase_failed = false;
400402
int status = QSPIF_BD_ERROR_OK;
401403
// Find region of erased address
402-
int region = _utils_find_addr_region(addr, _sfdp_info.smptbl);
404+
int region = sfdp_find_addr_region(addr, _sfdp_info);
403405
// Erase Types of selected region
404406
uint8_t bitfield = _sfdp_info.smptbl.region_erase_types_bitfld[region];
405407

406408
tr_debug("Erase - addr: %llu, in_size: %llu", addr, in_size);
407409

408-
if ((addr + in_size) > _device_size_bytes) {
410+
if ((addr + in_size) > _sfdp_info.bptbl.device_size_bytes) {
409411
tr_error("Erase exceeds flash device size");
410412
return QSPIF_BD_ERROR_INVALID_ERASE_PARAMS;
411413
}
@@ -421,9 +423,9 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
421423
if (_sfdp_info.bptbl.legacy_erase_instruction == QSPI_NO_INST) {
422424
// Iterate to find next largest erase type that is a) supported by region, and b) smaller than size.
423425
// Find the matching instruction and erase size chunk for that type.
424-
type = _utils_iterate_next_largest_erase_type(bitfield, size, (int)addr,
425-
region,
426-
_sfdp_info.smptbl);
426+
type = sfdp_iterate_next_largest_erase_type(bitfield, size, (int)addr,
427+
region,
428+
_sfdp_info.smptbl);
427429
cur_erase_inst = _sfdp_info.smptbl.erase_type_inst_arr[type];
428430
eu_size = _sfdp_info.smptbl.erase_type_size_arr[type];
429431
} else {
@@ -514,7 +516,7 @@ bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr)
514516
}
515517

516518
// Find region of current address
517-
int region = _utils_find_addr_region(addr, _sfdp_info.smptbl);
519+
int region = sfdp_find_addr_region(addr, _sfdp_info);
518520

519521
int min_region_erase_size = _sfdp_info.smptbl.regions_min_common_erase_size;
520522
int8_t type_mask = SFDP_ERASE_BITMASK_TYPE1;
@@ -543,7 +545,7 @@ bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr)
543545

544546
bd_size_t QSPIFBlockDevice::size() const
545547
{
546-
return _device_size_bytes;
548+
return _sfdp_info.bptbl.device_size_bytes;
547549
}
548550

549551
int QSPIFBlockDevice::get_erase_value() const
@@ -638,7 +640,7 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(Callback<int(bd_addr_t, void
638640
(param_table[6] << 16) |
639641
(param_table[5] << 8) |
640642
param_table[4]);
641-
_device_size_bytes = (density_bits + 1) / 8;
643+
sfdp_info.bptbl.device_size_bytes = (density_bits + 1) / 8;
642644

643645
// Set Page Size (QSPI write must be done on Page limits)
644646
_page_size_bytes = sfdp_detect_page_size(param_table, sfdp_info.bptbl.size);
@@ -1247,61 +1249,6 @@ bool QSPIFBlockDevice::_is_mem_ready()
12471249
return mem_ready;
12481250
}
12491251

1250-
/*********************************************/
1251-
/************* Utility Functions *************/
1252-
/*********************************************/
1253-
int QSPIFBlockDevice::_utils_find_addr_region(bd_size_t offset, sfdp_smptbl_info &smptbl)
1254-
{
1255-
//Find the region to which the given offset belong to
1256-
if ((offset > _device_size_bytes) || (smptbl.region_cnt == 0)) {
1257-
return -1;
1258-
}
1259-
1260-
if (smptbl.region_cnt == 1) {
1261-
return 0;
1262-
}
1263-
1264-
for (int i_ind = smptbl.region_cnt - 2; i_ind >= 0; i_ind--) {
1265-
1266-
if (offset > smptbl.region_high_boundary[i_ind]) {
1267-
return (i_ind + 1);
1268-
}
1269-
}
1270-
return -1;
1271-
1272-
}
1273-
1274-
int QSPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield,
1275-
int size,
1276-
int offset,
1277-
int region,
1278-
sfdp_smptbl_info &smptbl)
1279-
{
1280-
// Iterate on all supported Erase Types of the Region to which the offset belong to.
1281-
// Iterates from highest type to lowest
1282-
uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE4;
1283-
int i_ind = 0;
1284-
int largest_erase_type = 0;
1285-
for (i_ind = 3; i_ind >= 0; i_ind--) {
1286-
if (bitfield & type_mask) {
1287-
largest_erase_type = i_ind;
1288-
if ((size > (int)(smptbl.erase_type_size_arr[largest_erase_type])) &&
1289-
((_sfdp_info.smptbl.region_high_boundary[region] - offset)
1290-
> (int)(smptbl.erase_type_size_arr[largest_erase_type]))) {
1291-
break;
1292-
} else {
1293-
bitfield &= ~type_mask;
1294-
}
1295-
}
1296-
type_mask = type_mask >> 1;
1297-
}
1298-
1299-
if (i_ind == 4) {
1300-
tr_error("No erase type was found for current region addr");
1301-
}
1302-
return largest_erase_type;
1303-
}
1304-
13051252
/***************************************************/
13061253
/*********** QSPI Driver API Functions *************/
13071254
/***************************************************/

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,6 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
396396

397397
unsigned int _page_size_bytes; // Page size - 256 Bytes default
398398
int _freq;
399-
bd_size_t _device_size_bytes;
400399

401400
// Bus speed configuration
402401
qspi_bus_width_t _inst_width; //Bus width for Instruction phase

components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp

Lines changed: 15 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,10 @@ SingletonPtr<PlatformMutex> SPIFBlockDevice::_mutex;
8585
//***********************
8686
// SPIF Block Device APIs
8787
//***********************
88-
SPIFBlockDevice::SPIFBlockDevice(
89-
PinName mosi, PinName miso, PinName sclk, PinName csel, int freq)
88+
SPIFBlockDevice::SPIFBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName csel, int freq)
9089
:
9190
_spi(mosi, miso, sclk), _cs(csel), _prog_instruction(0), _erase_instruction(0),
92-
_page_size_bytes(0),
93-
_device_size_bytes(0), _init_ref_count(0), _is_initialized(false)
91+
_page_size_bytes(0), _init_ref_count(0), _is_initialized(false)
9492
{
9593
_address_size = SPIF_ADDR_SIZE_3_BYTES;
9694
// Initial SFDP read tables are read with 8 dummy cycles
@@ -99,6 +97,7 @@ SPIFBlockDevice::SPIFBlockDevice(
9997
_write_dummy_and_mode_cycles = 0;
10098
_dummy_and_mode_cycles = _read_dummy_and_mode_cycles;
10199

100+
_sfdp_info.bptbl.device_size_bytes = 0;
102101
_sfdp_info.bptbl.legacy_erase_instruction = SPIF_INST_LEGACY_ERASE_DEFAULT;
103102
_sfdp_info.smptbl.regions_min_common_erase_size = 0;
104103
_sfdp_info.smptbl.region_cnt = 1;
@@ -188,9 +187,9 @@ int SPIFBlockDevice::init()
188187
}
189188

190189
/**************************** Parse Sector Map Table ***********************************/
191-
_sfdp_info.smptbl.region_size[0] =
192-
_device_size_bytes; // If there's no region map, we have a single region sized the entire device size
193-
_sfdp_info.smptbl.region_high_boundary[0] = _device_size_bytes - 1;
190+
_sfdp_info.smptbl.region_size[0] = _sfdp_info.bptbl.device_size_bytes;
191+
// If there's no region map, we have a single region sized the entire device size
192+
_sfdp_info.smptbl.region_high_boundary[0] = _sfdp_info.bptbl.device_size_bytes - 1;
194193

195194
if ((_sfdp_info.smptbl.addr != 0) && (0 != _sfdp_info.smptbl.size)) {
196195
tr_debug("init - Parsing Sector Map Table - addr: 0x%" PRIx32 "h, Size: %d", _sfdp_info.smptbl.addr,
@@ -207,9 +206,9 @@ int SPIFBlockDevice::init()
207206
// Dummy And Mode Cycles Back default 0
208207
_dummy_and_mode_cycles = _write_dummy_and_mode_cycles;
209208
_is_initialized = true;
210-
tr_debug("Device size: %llu Kbytes", _device_size_bytes / 1024);
209+
tr_debug("Device size: %llu Kbytes", _sfdp_info.bptbl.device_size_bytes / 1024);
211210

212-
if (_device_size_bytes > (1 << 24)) {
211+
if (_sfdp_info.bptbl.device_size_bytes > (1 << 24)) {
213212
tr_debug("Size is bigger than 16MB and thus address does not fit in 3 byte, switch to 4 byte address mode");
214213
_spi_send_general_command(SPIF_4BEN, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0);
215214
_address_size = SPIF_ADDR_SIZE_4_BYTES;
@@ -340,7 +339,7 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
340339
bool erase_failed = false;
341340
int status = SPIF_BD_ERROR_OK;
342341
// Find region of erased address
343-
int region = _utils_find_addr_region(addr, _sfdp_info.smptbl);
342+
int region = sfdp_find_addr_region(addr, _sfdp_info);
344343
if (region < 0) {
345344
tr_error("no region found for address %llu", addr);
346345
return SPIF_BD_ERROR_INVALID_ERASE_PARAMS;
@@ -350,7 +349,7 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
350349

351350
tr_debug("erase - addr: %llu, in_size: %llu", addr, in_size);
352351

353-
if ((addr + in_size) > _device_size_bytes) {
352+
if ((addr + in_size) > _sfdp_info.bptbl.device_size_bytes) {
354353
tr_error("erase exceeds flash device size");
355354
return SPIF_BD_ERROR_INVALID_ERASE_PARAMS;
356355
}
@@ -365,7 +364,7 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
365364

366365
// iterate to find next Largest erase type ( a. supported by region, b. smaller than size)
367366
// find the matching instruction and erase size chunk for that type.
368-
type = _utils_iterate_next_largest_erase_type(bitfield, size, (unsigned int)addr, region, _sfdp_info.smptbl);
367+
type = sfdp_iterate_next_largest_erase_type(bitfield, size, (unsigned int)addr, region, _sfdp_info.smptbl);
369368
cur_erase_inst = _sfdp_info.smptbl.erase_type_inst_arr[type];
370369
offset = addr % _sfdp_info.smptbl.erase_type_size_arr[type];
371370
chunk = ((offset + size) < _sfdp_info.smptbl.erase_type_size_arr[type]) ?
@@ -436,7 +435,7 @@ bd_size_t SPIFBlockDevice::get_erase_size() const
436435
bd_size_t SPIFBlockDevice::get_erase_size(bd_addr_t addr) const
437436
{
438437
// Find region of current address
439-
int region = _utils_find_addr_region(addr, _sfdp_info.smptbl);
438+
int region = sfdp_find_addr_region(addr, _sfdp_info);
440439

441440
unsigned int min_region_erase_size = _sfdp_info.smptbl.regions_min_common_erase_size;
442441
int8_t type_mask = SFDP_ERASE_BITMASK_TYPE1;
@@ -469,7 +468,7 @@ bd_size_t SPIFBlockDevice::size() const
469468
return 0;
470469
}
471470

472-
return _device_size_bytes;
471+
return _sfdp_info.bptbl.device_size_bytes;
473472
}
474473

475474
int SPIFBlockDevice::get_erase_value() const
@@ -641,8 +640,8 @@ int SPIFBlockDevice::_sfdp_parse_basic_param_table(Callback<int(bd_addr_t, void
641640
(param_table[6] << 16) |
642641
(param_table[5] << 8) |
643642
param_table[4]);
644-
_device_size_bytes = (density_bits + 1) / 8;
645-
tr_debug("Density bits: %" PRIu32 " , device size: %llu bytes", density_bits, _device_size_bytes);
643+
sfdp_info.bptbl.device_size_bytes = (density_bits + 1) / 8;
644+
tr_debug("Density bits: %" PRIu32 " , device size: %llu bytes", density_bits, sfdp_info.bptbl.device_size_bytes);
646645

647646
// Set Default read/program/erase Instructions
648647
_read_instruction = SPIF_READ;
@@ -779,59 +778,3 @@ int SPIFBlockDevice::_set_write_enable()
779778
} while (false);
780779
return status;
781780
}
782-
783-
/*********************************************/
784-
/************* Utility Functions *************/
785-
/*********************************************/
786-
int SPIFBlockDevice::_utils_find_addr_region(bd_size_t offset, const sfdp_smptbl_info &smptbl) const
787-
{
788-
//Find the region to which the given offset belong to
789-
if ((offset > _device_size_bytes) || (smptbl.region_cnt == 0)) {
790-
return -1;
791-
}
792-
793-
if (smptbl.region_cnt == 1) {
794-
return 0;
795-
}
796-
797-
for (int i_ind = smptbl.region_cnt - 2; i_ind >= 0; i_ind--) {
798-
799-
if (offset > smptbl.region_high_boundary[i_ind]) {
800-
return (i_ind + 1);
801-
}
802-
}
803-
return -1;
804-
805-
}
806-
807-
int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield,
808-
int size,
809-
int offset,
810-
int region,
811-
sfdp_smptbl_info &smptbl)
812-
{
813-
// Iterate on all supported Erase Types of the Region to which the offset belong to.
814-
// Iterates from highest type to lowest
815-
uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE4;
816-
int i_ind = 0;
817-
int largest_erase_type = 0;
818-
for (i_ind = 3; i_ind >= 0; i_ind--) {
819-
if (bitfield & type_mask) {
820-
largest_erase_type = i_ind;
821-
if ((size > (int)(smptbl.erase_type_size_arr[largest_erase_type])) &&
822-
((_sfdp_info.smptbl.region_high_boundary[region] - offset)
823-
> (int)(smptbl.erase_type_size_arr[largest_erase_type]))) {
824-
break;
825-
} else {
826-
bitfield &= ~type_mask;
827-
}
828-
}
829-
type_mask = type_mask >> 1;
830-
}
831-
832-
if (i_ind == 4) {
833-
tr_error("No erase type was found for current region addr");
834-
}
835-
return largest_erase_type;
836-
}
837-

components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -230,20 +230,6 @@ class SPIFBlockDevice : public mbed::BlockDevice {
230230
// Detect fastest read Bus mode supported by device
231231
int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, int &read_inst);
232232

233-
/***********************/
234-
/* Utilities Functions */
235-
/***********************/
236-
// Find the region to which the given offset belongs to
237-
int _utils_find_addr_region(bd_size_t offset, const mbed::sfdp_smptbl_info &smptbl) const;
238-
239-
// Iterate on all supported Erase Types of the Region to which the offset belongs to.
240-
// Iterates from highest type to lowest
241-
int _utils_iterate_next_largest_erase_type(uint8_t &bitfield,
242-
int size,
243-
int offset,
244-
int region,
245-
mbed::sfdp_smptbl_info &smptbl);
246-
247233
/********************************/
248234
/* Calls to SPI Driver APIs */
249235
/********************************/

0 commit comments

Comments
 (0)