mirror of https://github.com/ARMmbed/mbed-os.git
SFDP: consolidates erase region search
Merges erase region search found from SPIFBlockDevice and QSPIFBlockDevice. Moves the implementation within the SFDP componentpull/12450/head
parent
ca52ca9277
commit
ca704a4b3d
|
@ -125,10 +125,12 @@ PinName *QSPIFBlockDevice::_active_qspif_flash_csel_arr = generate_initialized_a
|
||||||
/********* Public API Functions *********/
|
/********* Public API Functions *********/
|
||||||
/****************************************/
|
/****************************************/
|
||||||
QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName csel,
|
QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName csel,
|
||||||
int clock_mode, int freq)
|
int clock_mode,
|
||||||
: _qspi(io0, io1, io2, io3, sclk, csel, clock_mode), _csel(csel), _freq(freq), _device_size_bytes(0),
|
int freq)
|
||||||
_init_ref_count(0),
|
:
|
||||||
_is_initialized(false)
|
_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);
|
_unique_device_status = add_new_csel_instance(csel);
|
||||||
|
|
||||||
|
@ -142,6 +144,7 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam
|
||||||
|
|
||||||
// Initialize parameters
|
// Initialize parameters
|
||||||
_sfdp_info.bptbl.legacy_erase_instruction = QSPIF_INST_LEGACY_ERASE_DEFAULT;
|
_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.regions_min_common_erase_size = 0;
|
||||||
_sfdp_info.smptbl.region_cnt = 1;
|
_sfdp_info.smptbl.region_cnt = 1;
|
||||||
_sfdp_info.smptbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE;
|
_sfdp_info.smptbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE;
|
||||||
|
@ -249,9 +252,8 @@ int QSPIFBlockDevice::init()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************** Parse Sector Map Table ***********************************/
|
/**************************** Parse Sector Map Table ***********************************/
|
||||||
_sfdp_info.smptbl.region_size[0] =
|
_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
|
||||||
_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;
|
||||||
_sfdp_info.smptbl.region_high_boundary[0] = _device_size_bytes - 1;
|
|
||||||
|
|
||||||
if ((_sfdp_info.smptbl.addr != 0) && (0 != _sfdp_info.smptbl.size)) {
|
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,
|
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)
|
||||||
bool erase_failed = false;
|
bool erase_failed = false;
|
||||||
int status = QSPIF_BD_ERROR_OK;
|
int status = QSPIF_BD_ERROR_OK;
|
||||||
// Find region of erased address
|
// 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
|
// Erase Types of selected region
|
||||||
uint8_t bitfield = _sfdp_info.smptbl.region_erase_types_bitfld[region];
|
uint8_t bitfield = _sfdp_info.smptbl.region_erase_types_bitfld[region];
|
||||||
|
|
||||||
tr_debug("Erase - addr: %llu, in_size: %llu", addr, 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");
|
tr_error("Erase exceeds flash device size");
|
||||||
return QSPIF_BD_ERROR_INVALID_ERASE_PARAMS;
|
return QSPIF_BD_ERROR_INVALID_ERASE_PARAMS;
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
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.
|
// 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.
|
// Find the matching instruction and erase size chunk for that type.
|
||||||
type = _utils_iterate_next_largest_erase_type(bitfield, size, (int)addr,
|
type = sfdp_iterate_next_largest_erase_type(bitfield, size, (int)addr,
|
||||||
region,
|
region,
|
||||||
_sfdp_info.smptbl);
|
_sfdp_info.smptbl);
|
||||||
cur_erase_inst = _sfdp_info.smptbl.erase_type_inst_arr[type];
|
cur_erase_inst = _sfdp_info.smptbl.erase_type_inst_arr[type];
|
||||||
eu_size = _sfdp_info.smptbl.erase_type_size_arr[type];
|
eu_size = _sfdp_info.smptbl.erase_type_size_arr[type];
|
||||||
} else {
|
} else {
|
||||||
|
@ -514,7 +516,7 @@ bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find region of current address
|
// 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;
|
int min_region_erase_size = _sfdp_info.smptbl.regions_min_common_erase_size;
|
||||||
int8_t type_mask = SFDP_ERASE_BITMASK_TYPE1;
|
int8_t type_mask = SFDP_ERASE_BITMASK_TYPE1;
|
||||||
|
@ -543,7 +545,7 @@ bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr)
|
||||||
|
|
||||||
bd_size_t QSPIFBlockDevice::size() const
|
bd_size_t QSPIFBlockDevice::size() const
|
||||||
{
|
{
|
||||||
return _device_size_bytes;
|
return _sfdp_info.bptbl.device_size_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QSPIFBlockDevice::get_erase_value() const
|
int QSPIFBlockDevice::get_erase_value() const
|
||||||
|
@ -638,7 +640,7 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(Callback<int(bd_addr_t, void
|
||||||
(param_table[6] << 16) |
|
(param_table[6] << 16) |
|
||||||
(param_table[5] << 8) |
|
(param_table[5] << 8) |
|
||||||
param_table[4]);
|
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)
|
// Set Page Size (QSPI write must be done on Page limits)
|
||||||
_page_size_bytes = sfdp_detect_page_size(param_table, sfdp_info.bptbl.size);
|
_page_size_bytes = sfdp_detect_page_size(param_table, sfdp_info.bptbl.size);
|
||||||
|
@ -1247,61 +1249,6 @@ bool QSPIFBlockDevice::_is_mem_ready()
|
||||||
return 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 *************/
|
/*********** QSPI Driver API Functions *************/
|
||||||
/***************************************************/
|
/***************************************************/
|
||||||
|
|
|
@ -396,7 +396,6 @@ private:
|
||||||
|
|
||||||
unsigned int _page_size_bytes; // Page size - 256 Bytes default
|
unsigned int _page_size_bytes; // Page size - 256 Bytes default
|
||||||
int _freq;
|
int _freq;
|
||||||
bd_size_t _device_size_bytes;
|
|
||||||
|
|
||||||
// Bus speed configuration
|
// Bus speed configuration
|
||||||
qspi_bus_width_t _inst_width; //Bus width for Instruction phase
|
qspi_bus_width_t _inst_width; //Bus width for Instruction phase
|
||||||
|
|
|
@ -85,12 +85,10 @@ SingletonPtr<PlatformMutex> SPIFBlockDevice::_mutex;
|
||||||
//***********************
|
//***********************
|
||||||
// SPIF Block Device APIs
|
// SPIF Block Device APIs
|
||||||
//***********************
|
//***********************
|
||||||
SPIFBlockDevice::SPIFBlockDevice(
|
SPIFBlockDevice::SPIFBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName csel, int freq)
|
||||||
PinName mosi, PinName miso, PinName sclk, PinName csel, int freq)
|
|
||||||
:
|
:
|
||||||
_spi(mosi, miso, sclk), _cs(csel), _prog_instruction(0), _erase_instruction(0),
|
_spi(mosi, miso, sclk), _cs(csel), _prog_instruction(0), _erase_instruction(0),
|
||||||
_page_size_bytes(0),
|
_page_size_bytes(0), _init_ref_count(0), _is_initialized(false)
|
||||||
_device_size_bytes(0), _init_ref_count(0), _is_initialized(false)
|
|
||||||
{
|
{
|
||||||
_address_size = SPIF_ADDR_SIZE_3_BYTES;
|
_address_size = SPIF_ADDR_SIZE_3_BYTES;
|
||||||
// Initial SFDP read tables are read with 8 dummy cycles
|
// Initial SFDP read tables are read with 8 dummy cycles
|
||||||
|
@ -99,6 +97,7 @@ SPIFBlockDevice::SPIFBlockDevice(
|
||||||
_write_dummy_and_mode_cycles = 0;
|
_write_dummy_and_mode_cycles = 0;
|
||||||
_dummy_and_mode_cycles = _read_dummy_and_mode_cycles;
|
_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.bptbl.legacy_erase_instruction = SPIF_INST_LEGACY_ERASE_DEFAULT;
|
||||||
_sfdp_info.smptbl.regions_min_common_erase_size = 0;
|
_sfdp_info.smptbl.regions_min_common_erase_size = 0;
|
||||||
_sfdp_info.smptbl.region_cnt = 1;
|
_sfdp_info.smptbl.region_cnt = 1;
|
||||||
|
@ -188,9 +187,9 @@ int SPIFBlockDevice::init()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************** Parse Sector Map Table ***********************************/
|
/**************************** Parse Sector Map Table ***********************************/
|
||||||
_sfdp_info.smptbl.region_size[0] =
|
_sfdp_info.smptbl.region_size[0] = _sfdp_info.bptbl.device_size_bytes;
|
||||||
_device_size_bytes; // If there's no region map, we have a single region sized the entire device size
|
// 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_high_boundary[0] = _sfdp_info.bptbl.device_size_bytes - 1;
|
||||||
|
|
||||||
if ((_sfdp_info.smptbl.addr != 0) && (0 != _sfdp_info.smptbl.size)) {
|
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,
|
tr_debug("init - Parsing Sector Map Table - addr: 0x%" PRIx32 "h, Size: %d", _sfdp_info.smptbl.addr,
|
||||||
|
@ -207,9 +206,9 @@ int SPIFBlockDevice::init()
|
||||||
// Dummy And Mode Cycles Back default 0
|
// Dummy And Mode Cycles Back default 0
|
||||||
_dummy_and_mode_cycles = _write_dummy_and_mode_cycles;
|
_dummy_and_mode_cycles = _write_dummy_and_mode_cycles;
|
||||||
_is_initialized = true;
|
_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");
|
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);
|
_spi_send_general_command(SPIF_4BEN, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0);
|
||||||
_address_size = SPIF_ADDR_SIZE_4_BYTES;
|
_address_size = SPIF_ADDR_SIZE_4_BYTES;
|
||||||
|
@ -340,7 +339,7 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
|
||||||
bool erase_failed = false;
|
bool erase_failed = false;
|
||||||
int status = SPIF_BD_ERROR_OK;
|
int status = SPIF_BD_ERROR_OK;
|
||||||
// Find region of erased address
|
// 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) {
|
if (region < 0) {
|
||||||
tr_error("no region found for address %llu", addr);
|
tr_error("no region found for address %llu", addr);
|
||||||
return SPIF_BD_ERROR_INVALID_ERASE_PARAMS;
|
return SPIF_BD_ERROR_INVALID_ERASE_PARAMS;
|
||||||
|
@ -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);
|
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");
|
tr_error("erase exceeds flash device size");
|
||||||
return SPIF_BD_ERROR_INVALID_ERASE_PARAMS;
|
return SPIF_BD_ERROR_INVALID_ERASE_PARAMS;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
// 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.
|
// 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];
|
cur_erase_inst = _sfdp_info.smptbl.erase_type_inst_arr[type];
|
||||||
offset = addr % _sfdp_info.smptbl.erase_type_size_arr[type];
|
offset = addr % _sfdp_info.smptbl.erase_type_size_arr[type];
|
||||||
chunk = ((offset + size) < _sfdp_info.smptbl.erase_type_size_arr[type]) ?
|
chunk = ((offset + size) < _sfdp_info.smptbl.erase_type_size_arr[type]) ?
|
||||||
|
@ -436,7 +435,7 @@ bd_size_t SPIFBlockDevice::get_erase_size() const
|
||||||
bd_size_t SPIFBlockDevice::get_erase_size(bd_addr_t addr) const
|
bd_size_t SPIFBlockDevice::get_erase_size(bd_addr_t addr) const
|
||||||
{
|
{
|
||||||
// Find region of current address
|
// 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;
|
unsigned int min_region_erase_size = _sfdp_info.smptbl.regions_min_common_erase_size;
|
||||||
int8_t type_mask = SFDP_ERASE_BITMASK_TYPE1;
|
int8_t type_mask = SFDP_ERASE_BITMASK_TYPE1;
|
||||||
|
@ -469,7 +468,7 @@ bd_size_t SPIFBlockDevice::size() const
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _device_size_bytes;
|
return _sfdp_info.bptbl.device_size_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SPIFBlockDevice::get_erase_value() const
|
int SPIFBlockDevice::get_erase_value() const
|
||||||
|
@ -641,8 +640,8 @@ int SPIFBlockDevice::_sfdp_parse_basic_param_table(Callback<int(bd_addr_t, void
|
||||||
(param_table[6] << 16) |
|
(param_table[6] << 16) |
|
||||||
(param_table[5] << 8) |
|
(param_table[5] << 8) |
|
||||||
param_table[4]);
|
param_table[4]);
|
||||||
_device_size_bytes = (density_bits + 1) / 8;
|
sfdp_info.bptbl.device_size_bytes = (density_bits + 1) / 8;
|
||||||
tr_debug("Density bits: %" PRIu32 " , device size: %llu bytes", density_bits, _device_size_bytes);
|
tr_debug("Density bits: %" PRIu32 " , device size: %llu bytes", density_bits, sfdp_info.bptbl.device_size_bytes);
|
||||||
|
|
||||||
// Set Default read/program/erase Instructions
|
// Set Default read/program/erase Instructions
|
||||||
_read_instruction = SPIF_READ;
|
_read_instruction = SPIF_READ;
|
||||||
|
@ -779,59 +778,3 @@ int SPIFBlockDevice::_set_write_enable()
|
||||||
} while (false);
|
} while (false);
|
||||||
return status;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -230,20 +230,6 @@ private:
|
||||||
// Detect fastest read Bus mode supported by device
|
// 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);
|
int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, int &read_inst);
|
||||||
|
|
||||||
/***********************/
|
|
||||||
/* 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 */
|
/* Calls to SPI Driver APIs */
|
||||||
/********************************/
|
/********************************/
|
||||||
|
|
|
@ -51,6 +51,7 @@ constexpr int SFDP_MAX_NUM_OF_ERASE_TYPES = 4; ///< Maximum number of different
|
||||||
struct sfdp_bptbl_info {
|
struct sfdp_bptbl_info {
|
||||||
uint32_t addr; ///< Address
|
uint32_t addr; ///< Address
|
||||||
size_t size; ///< Size
|
size_t size; ///< Size
|
||||||
|
bd_size_t device_size_bytes;
|
||||||
int legacy_erase_instruction; ///< Legacy 4K erase instruction
|
int legacy_erase_instruction; ///< Legacy 4K erase instruction
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,7 +78,7 @@ struct sfdp_hdr_info {
|
||||||
* Retrieves SFDP headers from a device and parses the information contained by the headers
|
* Retrieves SFDP headers from a device and parses the information contained by the headers
|
||||||
*
|
*
|
||||||
* @param sfdp_reader Callback function used to read headers from a device
|
* @param sfdp_reader Callback function used to read headers from a device
|
||||||
* @param hdr_info All information parsed from the headers gets passed back on this structure
|
* @param hdr_info SFDP information structure
|
||||||
*
|
*
|
||||||
* @return 0 on success, negative error code on failure
|
* @return 0 on success, negative error code on failure
|
||||||
*/
|
*/
|
||||||
|
@ -87,7 +88,7 @@ int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
|
||||||
* Retrieves the table from a device and parses the information contained by the table
|
* Retrieves the table from a device and parses the information contained by the table
|
||||||
*
|
*
|
||||||
* @param sfdp_reader Callback function used to read headers from a device
|
* @param sfdp_reader Callback function used to read headers from a device
|
||||||
* @param smtbl All information parsed from the table gets passed back on this structure
|
* @param smtbl Sector Map Table information structure
|
||||||
*
|
*
|
||||||
* @return 0 on success, negative error code on failure
|
* @return 0 on success, negative error code on failure
|
||||||
*/
|
*/
|
||||||
|
@ -105,12 +106,36 @@ size_t sfdp_detect_page_size(uint8_t *bptbl_ptr, size_t bptbl_size);
|
||||||
/** Detect all supported erase types
|
/** Detect all supported erase types
|
||||||
*
|
*
|
||||||
* @param bptbl_ptr Pointer to memory holding a Basic Parameter Table structure
|
* @param bptbl_ptr Pointer to memory holding a Basic Parameter Table structure
|
||||||
* @param smtbl All information parsed from the table gets passed back on this structure
|
* @param smtbl Sector Map Table information structure
|
||||||
*
|
*
|
||||||
* @return 0 on success, negative error code on failure
|
* @return 0 on success, negative error code on failure
|
||||||
*/
|
*/
|
||||||
int sfdp_detect_erase_types_inst_and_size(uint8_t *bptbl_ptr, sfdp_hdr_info &sfdp_info);
|
int sfdp_detect_erase_types_inst_and_size(uint8_t *bptbl_ptr, sfdp_hdr_info &sfdp_info);
|
||||||
|
|
||||||
|
/** Find the region to which the given offset belongs to
|
||||||
|
*
|
||||||
|
* @param offset Offset value
|
||||||
|
* @param smtbl Sector Map Table information structure
|
||||||
|
*/
|
||||||
|
int sfdp_find_addr_region(bd_size_t offset, const sfdp_hdr_info &sfdp_info);
|
||||||
|
|
||||||
|
/** Iterate on all supported Erase Types of the Region to which the offset belongs to
|
||||||
|
*
|
||||||
|
* Iterates from highest type to lowest.
|
||||||
|
*
|
||||||
|
* @param bitfield
|
||||||
|
* @param size
|
||||||
|
* @param region
|
||||||
|
* @param smtbl Sector Map Table information structure
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int sfdp_iterate_next_largest_erase_type(uint8_t &bitfield,
|
||||||
|
int size,
|
||||||
|
int offset,
|
||||||
|
int region,
|
||||||
|
const sfdp_smptbl_info &smptbl);
|
||||||
|
|
||||||
/** @}*/
|
/** @}*/
|
||||||
} /* namespace mbed */
|
} /* namespace mbed */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -295,7 +295,54 @@ int sfdp_detect_erase_types_inst_and_size(uint8_t *bptbl_ptr, sfdp_hdr_info &sfd
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sfdp_find_addr_region(bd_size_t offset, const sfdp_hdr_info &sfdp_info)
|
||||||
|
{
|
||||||
|
if ((offset > sfdp_info.bptbl.device_size_bytes) || (sfdp_info.smptbl.region_cnt == 0)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sfdp_info.smptbl.region_cnt == 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i_ind = sfdp_info.smptbl.region_cnt - 2; i_ind >= 0; i_ind--) {
|
||||||
|
|
||||||
|
if (offset > sfdp_info.smptbl.region_high_boundary[i_ind]) {
|
||||||
|
return (i_ind + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int sfdp_iterate_next_largest_erase_type(uint8_t &bitfield,
|
||||||
|
int size,
|
||||||
|
int offset,
|
||||||
|
int region,
|
||||||
|
const sfdp_smptbl_info &smptbl)
|
||||||
|
{
|
||||||
|
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])) &&
|
||||||
|
((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;
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace mbed */
|
} /* namespace mbed */
|
||||||
#endif /* (DEVICE_SPI || DEVICE_QSPI) */
|
#endif /* (DEVICE_SPI || DEVICE_QSPI) */
|
||||||
|
|
Loading…
Reference in New Issue