Skip to content

SFDP: consolidation of SFDP parsing [3/5] #12450

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 17 additions & 70 deletions components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,12 @@ PinName *QSPIFBlockDevice::_active_qspif_flash_csel_arr = generate_initialized_a
/********* Public API Functions *********/
/****************************************/
QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName csel,
int clock_mode, int freq)
: _qspi(io0, io1, io2, io3, sclk, csel, clock_mode), _csel(csel), _freq(freq), _device_size_bytes(0),
_init_ref_count(0),
_is_initialized(false)
int clock_mode,
int freq)
:
_qspi(io0, io1, io2, io3, sclk, csel, clock_mode), _csel(csel), _freq(freq),
_init_ref_count(0),
_is_initialized(false)
{
_unique_device_status = add_new_csel_instance(csel);

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

// Initialize parameters
_sfdp_info.bptbl.legacy_erase_instruction = QSPIF_INST_LEGACY_ERASE_DEFAULT;
_sfdp_info.bptbl.device_size_bytes = 0;
_sfdp_info.smptbl.regions_min_common_erase_size = 0;
_sfdp_info.smptbl.region_cnt = 1;
_sfdp_info.smptbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE;
Expand Down Expand Up @@ -249,9 +252,8 @@ int QSPIFBlockDevice::init()
}

/**************************** Parse Sector Map Table ***********************************/
_sfdp_info.smptbl.region_size[0] =
_device_size_bytes; // If there's no region map, we have a single region sized the entire device size
_sfdp_info.smptbl.region_high_boundary[0] = _device_size_bytes - 1;
_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
_sfdp_info.smptbl.region_high_boundary[0] = _sfdp_info.bptbl.device_size_bytes - 1;

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

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

if ((addr + in_size) > _device_size_bytes) {
if ((addr + in_size) > _sfdp_info.bptbl.device_size_bytes) {
tr_error("Erase exceeds flash device size");
return QSPIF_BD_ERROR_INVALID_ERASE_PARAMS;
}
Expand All @@ -421,9 +423,9 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
if (_sfdp_info.bptbl.legacy_erase_instruction == QSPI_NO_INST) {
// Iterate to find next largest erase type that is a) supported by region, and b) smaller than size.
// Find the matching instruction and erase size chunk for that type.
type = _utils_iterate_next_largest_erase_type(bitfield, size, (int)addr,
region,
_sfdp_info.smptbl);
type = sfdp_iterate_next_largest_erase_type(bitfield, size, (int)addr,
region,
_sfdp_info.smptbl);
cur_erase_inst = _sfdp_info.smptbl.erase_type_inst_arr[type];
eu_size = _sfdp_info.smptbl.erase_type_size_arr[type];
} else {
Expand Down Expand Up @@ -514,7 +516,7 @@ bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr)
}

// Find region of current address
int region = _utils_find_addr_region(addr, _sfdp_info.smptbl);
int region = sfdp_find_addr_region(addr, _sfdp_info);

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

bd_size_t QSPIFBlockDevice::size() const
{
return _device_size_bytes;
return _sfdp_info.bptbl.device_size_bytes;
}

int QSPIFBlockDevice::get_erase_value() const
Expand Down Expand Up @@ -638,7 +640,7 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(Callback<int(bd_addr_t, void
(param_table[6] << 16) |
(param_table[5] << 8) |
param_table[4]);
_device_size_bytes = (density_bits + 1) / 8;
sfdp_info.bptbl.device_size_bytes = (density_bits + 1) / 8;

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

/*********************************************/
/************* Utility Functions *************/
/*********************************************/
int QSPIFBlockDevice::_utils_find_addr_region(bd_size_t offset, sfdp_smptbl_info &smptbl)
{
//Find the region to which the given offset belong to
if ((offset > _device_size_bytes) || (smptbl.region_cnt == 0)) {
return -1;
}

if (smptbl.region_cnt == 1) {
return 0;
}

for (int i_ind = smptbl.region_cnt - 2; i_ind >= 0; i_ind--) {

if (offset > smptbl.region_high_boundary[i_ind]) {
return (i_ind + 1);
}
}
return -1;

}

int QSPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield,
int size,
int offset,
int region,
sfdp_smptbl_info &smptbl)
{
// Iterate on all supported Erase Types of the Region to which the offset belong to.
// Iterates from highest type to lowest
uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE4;
int i_ind = 0;
int largest_erase_type = 0;
for (i_ind = 3; i_ind >= 0; i_ind--) {
if (bitfield & type_mask) {
largest_erase_type = i_ind;
if ((size > (int)(smptbl.erase_type_size_arr[largest_erase_type])) &&
((_sfdp_info.smptbl.region_high_boundary[region] - offset)
> (int)(smptbl.erase_type_size_arr[largest_erase_type]))) {
break;
} else {
bitfield &= ~type_mask;
}
}
type_mask = type_mask >> 1;
}

if (i_ind == 4) {
tr_error("No erase type was found for current region addr");
}
return largest_erase_type;
}

/***************************************************/
/*********** QSPI Driver API Functions *************/
/***************************************************/
Expand Down
12 changes: 0 additions & 12 deletions components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,6 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
virtual const char *get_type() const;

private:

// SFDP helpers
friend int mbed::sfdp_parse_headers(mbed::Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
mbed::sfdp_hdr_info &hdr_info);

// Internal functions


/********************************/
/* Different Device Csel Mgmt */
/********************************/
Expand Down Expand Up @@ -334,9 +326,6 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
// Enable QPI mode (4-4-4)
int _sfdp_set_qpi_enabled(uint8_t *basic_param_table_ptr);

// Set Page size for program
int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size);

// Detect 4-byte addressing mode and enable it if supported
int _sfdp_detect_and_enable_4byte_addressing(uint8_t *basic_param_table_ptr, int basic_param_table_size);

Expand Down Expand Up @@ -407,7 +396,6 @@ class QSPIFBlockDevice : public mbed::BlockDevice {

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

// Bus speed configuration
qspi_bus_width_t _inst_width; //Bus width for Instruction phase
Expand Down
87 changes: 15 additions & 72 deletions components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,10 @@ SingletonPtr<PlatformMutex> SPIFBlockDevice::_mutex;
//***********************
// SPIF Block Device APIs
//***********************
SPIFBlockDevice::SPIFBlockDevice(
PinName mosi, PinName miso, PinName sclk, PinName csel, int freq)
SPIFBlockDevice::SPIFBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName csel, int freq)
:
_spi(mosi, miso, sclk), _cs(csel), _prog_instruction(0), _erase_instruction(0),
_page_size_bytes(0),
_device_size_bytes(0), _init_ref_count(0), _is_initialized(false)
_page_size_bytes(0), _init_ref_count(0), _is_initialized(false)
{
_address_size = SPIF_ADDR_SIZE_3_BYTES;
// Initial SFDP read tables are read with 8 dummy cycles
Expand All @@ -99,6 +97,7 @@ SPIFBlockDevice::SPIFBlockDevice(
_write_dummy_and_mode_cycles = 0;
_dummy_and_mode_cycles = _read_dummy_and_mode_cycles;

_sfdp_info.bptbl.device_size_bytes = 0;
_sfdp_info.bptbl.legacy_erase_instruction = SPIF_INST_LEGACY_ERASE_DEFAULT;
_sfdp_info.smptbl.regions_min_common_erase_size = 0;
_sfdp_info.smptbl.region_cnt = 1;
Expand Down Expand Up @@ -188,9 +187,9 @@ int SPIFBlockDevice::init()
}

/**************************** Parse Sector Map Table ***********************************/
_sfdp_info.smptbl.region_size[0] =
_device_size_bytes; // If there's no region map, we have a single region sized the entire device size
_sfdp_info.smptbl.region_high_boundary[0] = _device_size_bytes - 1;
_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
_sfdp_info.smptbl.region_high_boundary[0] = _sfdp_info.bptbl.device_size_bytes - 1;

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

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

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

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

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

unsigned int min_region_erase_size = _sfdp_info.smptbl.regions_min_common_erase_size;
int8_t type_mask = SFDP_ERASE_BITMASK_TYPE1;
Expand Down Expand Up @@ -469,7 +468,7 @@ bd_size_t SPIFBlockDevice::size() const
return 0;
}

return _device_size_bytes;
return _sfdp_info.bptbl.device_size_bytes;
}

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

// Set Default read/program/erase Instructions
_read_instruction = SPIF_READ;
Expand Down Expand Up @@ -779,59 +778,3 @@ int SPIFBlockDevice::_set_write_enable()
} while (false);
return status;
}

/*********************************************/
/************* Utility Functions *************/
/*********************************************/
int SPIFBlockDevice::_utils_find_addr_region(bd_size_t offset, const sfdp_smptbl_info &smptbl) const
{
//Find the region to which the given offset belong to
if ((offset > _device_size_bytes) || (smptbl.region_cnt == 0)) {
return -1;
}

if (smptbl.region_cnt == 1) {
return 0;
}

for (int i_ind = smptbl.region_cnt - 2; i_ind >= 0; i_ind--) {

if (offset > smptbl.region_high_boundary[i_ind]) {
return (i_ind + 1);
}
}
return -1;

}

int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield,
int size,
int offset,
int region,
sfdp_smptbl_info &smptbl)
{
// Iterate on all supported Erase Types of the Region to which the offset belong to.
// Iterates from highest type to lowest
uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE4;
int i_ind = 0;
int largest_erase_type = 0;
for (i_ind = 3; i_ind >= 0; i_ind--) {
if (bitfield & type_mask) {
largest_erase_type = i_ind;
if ((size > (int)(smptbl.erase_type_size_arr[largest_erase_type])) &&
((_sfdp_info.smptbl.region_high_boundary[region] - offset)
> (int)(smptbl.erase_type_size_arr[largest_erase_type]))) {
break;
} else {
bitfield &= ~type_mask;
}
}
type_mask = type_mask >> 1;
}

if (i_ind == 4) {
tr_error("No erase type was found for current region addr");
}
return largest_erase_type;
}

24 changes: 0 additions & 24 deletions components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,13 +217,6 @@ class SPIFBlockDevice : public mbed::BlockDevice {
virtual const char *get_type() const;

private:

// Internal functions

// SFDP helpers
friend int mbed::sfdp_parse_headers(mbed::Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
mbed::sfdp_hdr_info &hdr_info);

/****************************************/
/* SFDP Detection and Parsing Functions */
/****************************************/
Expand All @@ -237,23 +230,6 @@ class SPIFBlockDevice : public mbed::BlockDevice {
// Detect fastest read Bus mode supported by device
int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, int &read_inst);

// Set Page size for program
unsigned int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size);

/***********************/
/* Utilities Functions */
/***********************/
// Find the region to which the given offset belongs to
int _utils_find_addr_region(bd_size_t offset, const mbed::sfdp_smptbl_info &smptbl) const;

// Iterate on all supported Erase Types of the Region to which the offset belongs to.
// Iterates from highest type to lowest
int _utils_iterate_next_largest_erase_type(uint8_t &bitfield,
int size,
int offset,
int region,
mbed::sfdp_smptbl_info &smptbl);

/********************************/
/* Calls to SPI Driver APIs */
/********************************/
Expand Down
Loading