mirror of https://github.com/ARMmbed/mbed-os.git
SFDP: Add more parameters to the reader callback
The SFDP functions parse SFDP data which is fetched by a callback
called `sfdp_reader` provided by {SPIF,QSPIF,OSPIF}BlockDevice.
Currently, this callback interface only takes a read address and an RX
buffer to store output data. This has been enough, because other SPI
parameters are always the same when fetching the SFDP table only -
they are just hardcoded in each reader.
But in the future we will add support for flash devices with multiple
configurations (in a subsequent commit), and to detect which
configuration is enabled, we will need to send detection commands
which require device-dependent SPI parameters:
* address size
* instruction
* dummy cycles
This commit
* turns the above SPI parameters from predefined/hardcoded values
into parameters of the callback
* lets the SFDP functions pass the above parameters to the callback
(Note: To read the SFDP table itself, those values are constants
defined by the standard, not tied to any particular device, so they
can be known to the SFDP functions)
* updates the callbacks implemented by {SPIF,QSPIF,OSPIF}BlockDevice
* updates the mock callback for unit tests and expectations
pull/14989/head
parent
2581254492
commit
b5e7dd9d32
|
|
@ -327,7 +327,9 @@ private:
|
|||
mbed::bd_size_t tx_length, const char *rx_buffer, mbed::bd_size_t rx_length);
|
||||
|
||||
// Send command to read from the SFDP table
|
||||
int _ospi_send_read_sfdp_command(mbed::bd_addr_t addr, void *rx_buffer, mbed::bd_size_t rx_length);
|
||||
int _ospi_send_read_sfdp_command(mbed::bd_addr_t addr, mbed::sfdp_cmd_addr_size_t addr_size,
|
||||
uint8_t inst, uint8_t dummy_cycles,
|
||||
void *rx_buffer, mbed::bd_size_t rx_length);
|
||||
|
||||
// Read the contents of status registers 1 and 2 into a buffer (buffer must have a length of 2)
|
||||
ospi_status_t _ospi_read_status_registers(uint8_t *reg_buffer);
|
||||
|
|
@ -366,11 +368,11 @@ private:
|
|||
/* SFDP Detection and Parsing Functions */
|
||||
/****************************************/
|
||||
// Parse and Detect required Basic Parameters from Table
|
||||
int _sfdp_parse_basic_param_table(mbed::Callback<int(mbed::bd_addr_t, void *, mbed::bd_size_t)> sfdp_reader,
|
||||
int _sfdp_parse_basic_param_table(mbed::Callback<int(mbed::bd_addr_t, mbed::sfdp_cmd_addr_size_t, uint8_t, uint8_t, void *, mbed::bd_size_t)> sfdp_reader,
|
||||
mbed::sfdp_hdr_info &sfdp_info);
|
||||
|
||||
// Parse and Detect 4-Byte Address Instruction Parameters from Table
|
||||
int _sfdp_parse_4_byte_inst_table(mbed::Callback<int(mbed::bd_addr_t, void *, mbed::bd_size_t)> sfdp_reader,
|
||||
int _sfdp_parse_4_byte_inst_table(mbed::Callback<int(mbed::bd_addr_t, mbed::sfdp_cmd_addr_size_t, uint8_t, uint8_t, void *, mbed::bd_size_t)> sfdp_reader,
|
||||
mbed::sfdp_hdr_info &sfdp_info);
|
||||
|
||||
// Detect the soft reset protocol and reset - returns error if soft reset is not supported
|
||||
|
|
|
|||
|
|
@ -921,12 +921,19 @@ int OSPIFBlockDevice::remove_csel_instance(PinName csel)
|
|||
/*********************************************************/
|
||||
/********** SFDP Parsing and Detection Functions *********/
|
||||
/*********************************************************/
|
||||
int OSPIFBlockDevice::_sfdp_parse_basic_param_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
|
||||
int OSPIFBlockDevice::_sfdp_parse_basic_param_table(Callback<int(bd_addr_t, mbed::sfdp_cmd_addr_size_t, uint8_t, uint8_t, void *, bd_size_t)> sfdp_reader,
|
||||
sfdp_hdr_info &sfdp_info)
|
||||
{
|
||||
uint8_t param_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 20 DWORDS = 80 Bytes */
|
||||
|
||||
int status = sfdp_reader(sfdp_info.bptbl.addr, param_table, sfdp_info.bptbl.size);
|
||||
int status = sfdp_reader(
|
||||
sfdp_info.bptbl.addr,
|
||||
SFDP_READ_CMD_ADDR_TYPE,
|
||||
SFDP_READ_CMD_INST,
|
||||
SFDP_READ_CMD_DUMMY_CYCLES,
|
||||
param_table,
|
||||
sfdp_info.bptbl.size
|
||||
);
|
||||
if (status != OSPI_STATUS_OK) {
|
||||
tr_error("Init - Read SFDP First Table Failed");
|
||||
return -1;
|
||||
|
|
@ -1383,12 +1390,19 @@ int OSPIFBlockDevice::_sfdp_detect_reset_protocol_and_reset(uint8_t *basic_param
|
|||
return status;
|
||||
}
|
||||
|
||||
int OSPIFBlockDevice::_sfdp_parse_4_byte_inst_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
|
||||
int OSPIFBlockDevice::_sfdp_parse_4_byte_inst_table(Callback<int(mbed::bd_addr_t, mbed::sfdp_cmd_addr_size_t, uint8_t, uint8_t, void *, mbed::bd_size_t)> sfdp_reader,
|
||||
sfdp_hdr_info &sfdp_info)
|
||||
{
|
||||
uint8_t four_byte_inst_table[SFDP_DEFAULT_4_BYTE_INST_TABLE_SIZE_BYTES]; /* Up To 2 DWORDS = 8 Bytes */
|
||||
|
||||
int status = sfdp_reader(sfdp_info.fbatbl.addr, four_byte_inst_table, sfdp_info.fbatbl.size);
|
||||
int status = sfdp_reader(
|
||||
sfdp_info.fbatbl.addr,
|
||||
SFDP_READ_CMD_ADDR_TYPE,
|
||||
SFDP_READ_CMD_INST,
|
||||
SFDP_READ_CMD_DUMMY_CYCLES,
|
||||
four_byte_inst_table,
|
||||
sfdp_info.fbatbl.size
|
||||
);
|
||||
if (status != OSPI_STATUS_OK) {
|
||||
tr_error("Init - Read SFDP Four Byte Inst Table Failed");
|
||||
return -1;
|
||||
|
|
@ -1823,13 +1837,39 @@ ospi_status_t OSPIFBlockDevice::_ospi_send_general_command(ospi_inst_t instructi
|
|||
return OSPI_STATUS_OK;
|
||||
}
|
||||
|
||||
int OSPIFBlockDevice::_ospi_send_read_sfdp_command(bd_addr_t addr, void *rx_buffer, bd_size_t rx_length)
|
||||
int OSPIFBlockDevice::_ospi_send_read_sfdp_command(mbed::bd_addr_t addr, mbed::sfdp_cmd_addr_size_t addr_size,
|
||||
uint8_t inst, uint8_t dummy_cycles,
|
||||
void *rx_buffer, mbed::bd_size_t rx_length)
|
||||
{
|
||||
size_t rx_len = rx_length;
|
||||
uint8_t *rx_buffer_tmp = (uint8_t *)rx_buffer;
|
||||
|
||||
// Set default here to avoid uninitialized variable warning
|
||||
ospi_address_size_t address_size = _address_size;
|
||||
int address = addr;
|
||||
switch (addr_size) {
|
||||
case SFDP_CMD_ADDR_3_BYTE:
|
||||
address_size = OSPI_CFG_ADDR_SIZE_24;
|
||||
break;
|
||||
case SFDP_CMD_ADDR_4_BYTE:
|
||||
address_size = OSPI_CFG_ADDR_SIZE_32;
|
||||
break;
|
||||
case SFDP_CMD_ADDR_SIZE_VARIABLE: // use current setting
|
||||
break;
|
||||
case SFDP_CMD_ADDR_NONE: // no address in command
|
||||
address = static_cast<int>(OSPI_NO_ADDRESS_COMMAND);
|
||||
break;
|
||||
default:
|
||||
tr_error("Invalid SFDP command address size: 0x%02X", addr_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dummy_cycles == SFDP_CMD_DUMMY_CYCLES_VARIABLE) {
|
||||
// use current setting
|
||||
dummy_cycles = _dummy_cycles;
|
||||
}
|
||||
|
||||
// SFDP read instruction requires 1-1-1 bus mode with 8 dummy cycles and a 3-byte address
|
||||
ospi_status_t status = _ospi.configure_format(OSPI_CFG_BUS_SINGLE, OSPI_CFG_INST_SIZE_8, OSPI_CFG_BUS_SINGLE, OSPI_CFG_ADDR_SIZE_24, OSPI_CFG_BUS_SINGLE, 0, OSPI_CFG_BUS_SINGLE, OSPIF_RSFDP_DUMMY_CYCLES);
|
||||
ospi_status_t status = _ospi.configure_format(OSPI_CFG_BUS_SINGLE, OSPI_CFG_INST_SIZE_8, OSPI_CFG_BUS_SINGLE, address_size, OSPI_CFG_BUS_SINGLE, 0, OSPI_CFG_BUS_SINGLE, dummy_cycles);
|
||||
if (OSPI_STATUS_OK != status) {
|
||||
tr_error("_ospi_configure_format failed");
|
||||
return status;
|
||||
|
|
@ -1837,7 +1877,8 @@ int OSPIFBlockDevice::_ospi_send_read_sfdp_command(bd_addr_t addr, void *rx_buff
|
|||
|
||||
// Don't check the read status until after we've configured the format back to 1-1-1, to avoid leaving the interface in an
|
||||
// incorrect state if the read fails.
|
||||
status = _ospi.read(OSPIF_INST_RSFDP, -1, (unsigned int) addr, (char *) rx_buffer, &rx_len);
|
||||
size_t rx_len = rx_length;
|
||||
status = _ospi.read(inst, -1, address, static_cast<char *>(rx_buffer), &rx_len);
|
||||
|
||||
ospi_status_t format_status = _ospi.configure_format(OSPI_CFG_BUS_SINGLE, OSPI_CFG_INST_SIZE_8, OSPI_CFG_BUS_SINGLE, _address_size, OSPI_CFG_BUS_SINGLE, 0, OSPI_CFG_BUS_SINGLE, 0);
|
||||
// All commands other than Read and RSFDP use default 1-1-1 bus mode (Program/Erase are constrained by flash memory performance more than bus performance)
|
||||
|
|
|
|||
|
|
@ -277,7 +277,9 @@ private:
|
|||
mbed::bd_size_t tx_length, const char *rx_buffer, mbed::bd_size_t rx_length);
|
||||
|
||||
// Send command to read from the SFDP table
|
||||
int _qspi_send_read_sfdp_command(mbed::bd_addr_t addr, void *rx_buffer, mbed::bd_size_t rx_length);
|
||||
int _qspi_send_read_sfdp_command(mbed::bd_addr_t addr, mbed::sfdp_cmd_addr_size_t addr_size,
|
||||
uint8_t inst, uint8_t dummy_cycles,
|
||||
void *rx_buffer, mbed::bd_size_t rx_length);
|
||||
|
||||
// Read the contents of status registers 1 and 2 into a buffer (buffer must have a length of 2)
|
||||
qspi_status_t _qspi_read_status_registers(uint8_t *reg_buffer);
|
||||
|
|
@ -313,7 +315,7 @@ private:
|
|||
/* SFDP Detection and Parsing Functions */
|
||||
/****************************************/
|
||||
// Parse and Detect required Basic Parameters from Table
|
||||
int _sfdp_parse_basic_param_table(mbed::Callback<int(mbed::bd_addr_t, void *, mbed::bd_size_t)> sfdp_reader,
|
||||
int _sfdp_parse_basic_param_table(mbed::Callback<int(bd_addr_t, mbed::sfdp_cmd_addr_size_t, uint8_t, uint8_t, void *, bd_size_t)> sfdp_reader,
|
||||
mbed::sfdp_hdr_info &sfdp_info);
|
||||
|
||||
// Detect the soft reset protocol and reset - returns error if soft reset is not supported
|
||||
|
|
|
|||
|
|
@ -614,12 +614,19 @@ int QSPIFBlockDevice::remove_csel_instance(PinName csel)
|
|||
/*********************************************************/
|
||||
/********** SFDP Parsing and Detection Functions *********/
|
||||
/*********************************************************/
|
||||
int QSPIFBlockDevice::_sfdp_parse_basic_param_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
|
||||
int QSPIFBlockDevice::_sfdp_parse_basic_param_table(Callback<int(bd_addr_t, mbed::sfdp_cmd_addr_size_t, uint8_t, uint8_t, void *, bd_size_t)> sfdp_reader,
|
||||
sfdp_hdr_info &sfdp_info)
|
||||
{
|
||||
uint8_t param_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 20 DWORDS = 80 Bytes */
|
||||
|
||||
int status = sfdp_reader(sfdp_info.bptbl.addr, param_table, sfdp_info.bptbl.size);
|
||||
int status = sfdp_reader(
|
||||
sfdp_info.bptbl.addr,
|
||||
SFDP_READ_CMD_ADDR_TYPE,
|
||||
SFDP_READ_CMD_INST,
|
||||
SFDP_READ_CMD_DUMMY_CYCLES,
|
||||
param_table,
|
||||
sfdp_info.bptbl.size
|
||||
);
|
||||
if (status != QSPI_STATUS_OK) {
|
||||
tr_error("Init - Read SFDP First Table Failed");
|
||||
return -1;
|
||||
|
|
@ -1405,23 +1412,53 @@ qspi_status_t QSPIFBlockDevice::_qspi_send_general_command(qspi_inst_t instructi
|
|||
return QSPI_STATUS_OK;
|
||||
}
|
||||
|
||||
int QSPIFBlockDevice::_qspi_send_read_sfdp_command(bd_addr_t addr, void *rx_buffer, bd_size_t rx_length)
|
||||
int QSPIFBlockDevice::_qspi_send_read_sfdp_command(mbed::bd_addr_t addr, mbed::sfdp_cmd_addr_size_t addr_size,
|
||||
uint8_t inst, uint8_t dummy_cycles,
|
||||
void *rx_buffer, mbed::bd_size_t rx_length)
|
||||
{
|
||||
size_t rx_len = rx_length;
|
||||
// Set default here to avoid uninitialized variable warning
|
||||
qspi_address_size_t address_size = _address_size;
|
||||
int address = addr;
|
||||
switch (addr_size) {
|
||||
case SFDP_CMD_ADDR_3_BYTE:
|
||||
address_size = QSPI_CFG_ADDR_SIZE_24;
|
||||
break;
|
||||
case SFDP_CMD_ADDR_4_BYTE:
|
||||
address_size = QSPI_CFG_ADDR_SIZE_32;
|
||||
break;
|
||||
case SFDP_CMD_ADDR_SIZE_VARIABLE: // use current setting
|
||||
break;
|
||||
case SFDP_CMD_ADDR_NONE: // no address in command
|
||||
address = static_cast<int>(QSPI_NO_ADDRESS_COMMAND);
|
||||
break;
|
||||
default:
|
||||
tr_error("Invalid SFDP command address size: 0x%02X", addr_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// SFDP read instruction requires 1-1-1 bus mode with 8 dummy cycles and a 3-byte address
|
||||
qspi_status_t status = _qspi.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, 0, QSPI_CFG_BUS_SINGLE, QSPIF_RSFDP_DUMMY_CYCLES);
|
||||
if (dummy_cycles == SFDP_CMD_DUMMY_CYCLES_VARIABLE) {
|
||||
// use current setting
|
||||
dummy_cycles = _dummy_cycles;
|
||||
}
|
||||
|
||||
qspi_status_t status = _qspi.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE,
|
||||
address_size, QSPI_CFG_BUS_SINGLE,
|
||||
0, QSPI_CFG_BUS_SINGLE, dummy_cycles);
|
||||
if (QSPI_STATUS_OK != status) {
|
||||
tr_error("_qspi_configure_format failed");
|
||||
return status;
|
||||
}
|
||||
|
||||
// Don't check the read status until after we've configured the format back to 1-1-1, to avoid leaving the interface in an
|
||||
// incorrect state if the read fails.
|
||||
status = _qspi.read(QSPIF_INST_RSFDP, -1, (unsigned int) addr, (char *) rx_buffer, &rx_len);
|
||||
// Don't check the read status until after we've configured the format back to 1-1-1,
|
||||
// to avoid leaving the interface in an incorrect state if the read fails.
|
||||
size_t rx_len = rx_length;
|
||||
status = _qspi.read(inst, -1, address, static_cast<char *>(rx_buffer), &rx_len);
|
||||
|
||||
qspi_status_t format_status = _qspi.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, _address_size, QSPI_CFG_BUS_SINGLE, 0, QSPI_CFG_BUS_SINGLE, 0);
|
||||
// All commands other than Read and RSFDP use default 1-1-1 bus mode (Program/Erase are constrained by flash memory performance more than bus performance)
|
||||
qspi_status_t format_status = _qspi.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE,
|
||||
address_size, QSPI_CFG_BUS_SINGLE,
|
||||
0, QSPI_CFG_BUS_SINGLE, 0);
|
||||
// All commands other than Read and RSFDP use default 1-1-1 bus mode
|
||||
// (Program/Erase are constrained by flash memory performance more than bus performance)
|
||||
if (QSPI_STATUS_OK != format_status) {
|
||||
tr_error("_qspi_configure_format failed");
|
||||
return format_status;
|
||||
|
|
|
|||
|
|
@ -221,10 +221,12 @@ private:
|
|||
/* SFDP Detection and Parsing Functions */
|
||||
/****************************************/
|
||||
// Send SFDP Read command to Driver
|
||||
int _spi_send_read_sfdp_command(mbed::bd_addr_t addr, void *rx_buffer, mbed::bd_size_t rx_length);
|
||||
int _spi_send_read_sfdp_command(mbed::bd_addr_t addr, mbed::sfdp_cmd_addr_size_t addr_size,
|
||||
uint8_t inst, uint8_t dummy_cycles,
|
||||
void *rx_buffer, mbed::bd_size_t rx_length);
|
||||
|
||||
// Parse and Detect required Basic Parameters from Table
|
||||
int _sfdp_parse_basic_param_table(mbed::Callback<int(mbed::bd_addr_t, void *, mbed::bd_size_t)> sfdp_reader,
|
||||
int _sfdp_parse_basic_param_table(mbed::Callback<int(bd_addr_t, mbed::sfdp_cmd_addr_size_t, uint8_t, uint8_t, void *, bd_size_t)> sfdp_reader,
|
||||
mbed::sfdp_hdr_info &hdr_info);
|
||||
|
||||
// Detect fastest read Bus mode supported by device
|
||||
|
|
|
|||
|
|
@ -497,13 +497,32 @@ spif_bd_error SPIFBlockDevice::_spi_send_read_command(int read_inst, uint8_t *bu
|
|||
return SPIF_BD_ERROR_OK;
|
||||
}
|
||||
|
||||
int SPIFBlockDevice::_spi_send_read_sfdp_command(bd_addr_t addr, void *rx_buffer, bd_size_t rx_length)
|
||||
int SPIFBlockDevice::_spi_send_read_sfdp_command(mbed::bd_addr_t addr, mbed::sfdp_cmd_addr_size_t addr_size,
|
||||
uint8_t inst, uint8_t dummy_cycles,
|
||||
void *rx_buffer, mbed::bd_size_t rx_length)
|
||||
{
|
||||
// Set 1-1-1 bus mode for SFDP header parsing
|
||||
// Initial SFDP read tables are read with 8 dummy cycles
|
||||
_dummy_and_mode_cycles = 8;
|
||||
switch (addr_size) {
|
||||
case SFDP_CMD_ADDR_3_BYTE:
|
||||
_address_size = SPIF_ADDR_SIZE_3_BYTES;
|
||||
break;
|
||||
case SFDP_CMD_ADDR_4_BYTE:
|
||||
_address_size = SPIF_ADDR_SIZE_4_BYTES;
|
||||
break;
|
||||
case SFDP_CMD_ADDR_SIZE_VARIABLE: // use current setting
|
||||
break;
|
||||
case SFDP_CMD_ADDR_NONE: // no address in command
|
||||
addr = static_cast<int>(SPI_NO_ADDRESS_COMMAND);
|
||||
break;
|
||||
default:
|
||||
tr_error("Invalid SFDP command address size: 0x%02X", addr_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int status = _spi_send_read_command(SPIF_SFDP, (uint8_t *)rx_buffer, addr, rx_length);
|
||||
if (dummy_cycles != SFDP_CMD_DUMMY_CYCLES_VARIABLE) {
|
||||
_dummy_and_mode_cycles = dummy_cycles;
|
||||
}
|
||||
|
||||
int status = _spi_send_read_command(inst, static_cast<uint8_t *>(rx_buffer), addr, rx_length);
|
||||
if (status < 0) {
|
||||
tr_error("_spi_send_read_sfdp_command failed");
|
||||
}
|
||||
|
|
@ -588,12 +607,19 @@ spif_bd_error SPIFBlockDevice::_spi_send_general_command(int instruction, bd_add
|
|||
/*********************************************************/
|
||||
/********** SFDP Parsing and Detection Functions *********/
|
||||
/*********************************************************/
|
||||
int SPIFBlockDevice::_sfdp_parse_basic_param_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
|
||||
mbed::sfdp_hdr_info &sfdp_info)
|
||||
int SPIFBlockDevice::_sfdp_parse_basic_param_table(Callback<int(bd_addr_t, mbed::sfdp_cmd_addr_size_t, uint8_t, uint8_t, void *, bd_size_t)> sfdp_reader,
|
||||
sfdp_hdr_info &sfdp_info)
|
||||
{
|
||||
uint8_t param_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 20 DWORDS = 80 Bytes */
|
||||
|
||||
int status = sfdp_reader(sfdp_info.bptbl.addr, param_table, sfdp_info.bptbl.size);
|
||||
int status = sfdp_reader(
|
||||
sfdp_info.bptbl.addr,
|
||||
SFDP_READ_CMD_ADDR_TYPE,
|
||||
SFDP_READ_CMD_INST,
|
||||
SFDP_READ_CMD_DUMMY_CYCLES,
|
||||
param_table,
|
||||
sfdp_info.bptbl.size
|
||||
);
|
||||
if (status != SPIF_BD_ERROR_OK) {
|
||||
tr_error("init - Read SFDP First Table Failed");
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,22 @@ constexpr int SFDP_ERASE_BITMASK_ALL = 0x0F; ///< Erase type All
|
|||
|
||||
constexpr int SFDP_MAX_NUM_OF_ERASE_TYPES = 4; ///< Maximum number of different erase types (erase granularity)
|
||||
|
||||
// Size of a command specified by SFDP
|
||||
enum sfdp_cmd_addr_size_t {
|
||||
SFDP_CMD_ADDR_NONE = 0x00, // No address in command
|
||||
SFDP_CMD_ADDR_3_BYTE = 0x01, // 3-byte address
|
||||
SFDP_CMD_ADDR_4_BYTE = 0x02, // 4-byte address
|
||||
SFDP_CMD_ADDR_SIZE_VARIABLE = 0x03 // Address size from current setting
|
||||
};
|
||||
|
||||
// Parameters for SFDP Read command
|
||||
constexpr sfdp_cmd_addr_size_t SFDP_READ_CMD_ADDR_TYPE = SFDP_CMD_ADDR_3_BYTE; // Read SFDP has 3-byte address
|
||||
constexpr uint8_t SFDP_READ_CMD_INST = 0x5A; // Read SFDP instruction
|
||||
constexpr uint8_t SFDP_READ_CMD_DUMMY_CYCLES = 8; // READ SFDP dummy cycles
|
||||
|
||||
// Special value from SFDP for using dummy cycles from current setting
|
||||
constexpr uint8_t SFDP_CMD_DUMMY_CYCLES_VARIABLE = 0xF;
|
||||
|
||||
/** JEDEC Basic Flash Parameter Table info */
|
||||
struct sfdp_bptbl_info {
|
||||
uint32_t addr; ///< Address
|
||||
|
|
@ -92,7 +108,7 @@ struct sfdp_hdr_info {
|
|||
*
|
||||
* @return MBED_SUCCESS on success, negative error code on failure
|
||||
*/
|
||||
int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader, sfdp_hdr_info &sfdp_info);
|
||||
int sfdp_parse_headers(Callback<int(bd_addr_t, sfdp_cmd_addr_size_t, uint8_t, uint8_t, void *, bd_size_t)> sfdp_reader, sfdp_hdr_info &sfdp_info);
|
||||
|
||||
/** Parse Sector Map Parameter Table
|
||||
* Retrieves the table from a device and parses the information contained by the table
|
||||
|
|
@ -102,7 +118,7 @@ int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
|
|||
*
|
||||
* @return MBED_SUCCESS on success, negative error code on failure
|
||||
*/
|
||||
int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader, sfdp_hdr_info &sfdp_info);
|
||||
int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, sfdp_cmd_addr_size_t, uint8_t, uint8_t, void *, bd_size_t)> sfdp_reader, sfdp_hdr_info &sfdp_info);
|
||||
|
||||
/** Detect page size used for writing on flash
|
||||
*
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ int sfdp_parse_single_param_header(sfdp_prm_hdr *phdr_ptr, sfdp_hdr_info &hdr_in
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader, sfdp_hdr_info &sfdp_info)
|
||||
int sfdp_parse_headers(Callback<int(bd_addr_t, sfdp_cmd_addr_size_t, uint8_t, uint8_t, void *, bd_size_t)> sfdp_reader, sfdp_hdr_info &sfdp_info)
|
||||
{
|
||||
bd_addr_t addr = 0x0;
|
||||
int number_of_param_headers = 0;
|
||||
|
|
@ -191,7 +191,14 @@ int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
|
|||
data_length = SFDP_HEADER_SIZE;
|
||||
uint8_t sfdp_header[SFDP_HEADER_SIZE];
|
||||
|
||||
int status = sfdp_reader(addr, sfdp_header, data_length);
|
||||
int status = sfdp_reader(
|
||||
addr,
|
||||
SFDP_READ_CMD_ADDR_TYPE,
|
||||
SFDP_READ_CMD_INST,
|
||||
SFDP_READ_CMD_DUMMY_CYCLES,
|
||||
sfdp_header,
|
||||
data_length
|
||||
);
|
||||
if (status < 0) {
|
||||
tr_error("Retrieving SFDP Header failed");
|
||||
return -1;
|
||||
|
|
@ -213,7 +220,14 @@ int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
|
|||
|
||||
// Loop over Param Headers and parse them (currently supports Basic Param Table and Sector Region Map Table)
|
||||
for (int idx = 0; idx < number_of_param_headers; idx++) {
|
||||
status = sfdp_reader(addr, param_header, data_length);
|
||||
status = sfdp_reader(
|
||||
addr,
|
||||
SFDP_READ_CMD_ADDR_TYPE,
|
||||
SFDP_READ_CMD_INST,
|
||||
SFDP_READ_CMD_DUMMY_CYCLES,
|
||||
param_header,
|
||||
data_length
|
||||
);
|
||||
if (status < 0) {
|
||||
tr_error("Retrieving a parameter header %d failed", idx + 1);
|
||||
return -1;
|
||||
|
|
@ -231,7 +245,7 @@ int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader, sfdp_hdr_info &sfdp_info)
|
||||
int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, sfdp_cmd_addr_size_t, uint8_t, uint8_t, void *, bd_size_t)> sfdp_reader, sfdp_hdr_info &sfdp_info)
|
||||
{
|
||||
uint32_t tmp_region_size = 0;
|
||||
uint8_t type_mask;
|
||||
|
|
@ -264,7 +278,14 @@ int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp
|
|||
|
||||
tr_debug("Parsing Sector Map Table - addr: 0x%" PRIx32 ", Size: %d", sfdp_info.smptbl.addr, sfdp_info.smptbl.size);
|
||||
|
||||
int status = sfdp_reader(sfdp_info.smptbl.addr, smptbl_buff.get(), sfdp_info.smptbl.size);
|
||||
int status = sfdp_reader(
|
||||
sfdp_info.smptbl.addr,
|
||||
SFDP_READ_CMD_ADDR_TYPE,
|
||||
SFDP_READ_CMD_INST,
|
||||
SFDP_READ_CMD_DUMMY_CYCLES,
|
||||
smptbl_buff.get(),
|
||||
sfdp_info.smptbl.size
|
||||
);
|
||||
if (status < 0) {
|
||||
tr_error("Sector Map: Table retrieval failed");
|
||||
return -1;
|
||||
|
|
@ -314,6 +335,7 @@ int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
size_t sfdp_detect_page_size(uint8_t *basic_param_table_ptr, size_t basic_param_table_size)
|
||||
{
|
||||
constexpr int SFDP_BASIC_PARAM_TABLE_PAGE_SIZE = 40;
|
||||
|
|
|
|||
|
|
@ -62,14 +62,14 @@ static const uint8_t sector_map_single_descriptor_twelve_regions[] {
|
|||
class TestSFDP : public testing::Test {
|
||||
|
||||
public:
|
||||
mbed::Callback<int(mbed::bd_addr_t, void*, bd_size_t)> sfdp_reader_callback;
|
||||
mbed::Callback<int(mbed::bd_addr_t, mbed::sfdp_cmd_addr_size_t, uint8_t, uint8_t, void*, bd_size_t)> sfdp_reader_callback;
|
||||
|
||||
protected:
|
||||
TestSFDP() : sfdp_reader_callback(this, &TestSFDP::sfdp_reader) {};
|
||||
|
||||
int sfdp_reader(mbed::bd_addr_t addr, void *buff, bd_size_t buff_size)
|
||||
int sfdp_reader(mbed::bd_addr_t addr, mbed::sfdp_cmd_addr_size_t addr_size, uint8_t instr, uint8_t cycles, void *buff, bd_size_t buff_size)
|
||||
{
|
||||
int mock_return = sfdp_reader_mock.Call(addr, buff, buff_size);
|
||||
int mock_return = sfdp_reader_mock.Call(addr, addr_size, instr, cycles, buff, buff_size);
|
||||
if (mock_return != 0) {
|
||||
return mock_return;
|
||||
}
|
||||
|
|
@ -87,7 +87,7 @@ protected:
|
|||
sector_descriptors_size = table_size;
|
||||
}
|
||||
|
||||
MockFunction<int(mbed::bd_addr_t, void*, bd_size_t)> sfdp_reader_mock;
|
||||
MockFunction<int(mbed::bd_addr_t, uint8_t, uint8_t, uint8_t, void*, bd_size_t)> sfdp_reader_mock;
|
||||
const uint8_t *sector_descriptors;
|
||||
bd_size_t sector_descriptors_size;
|
||||
};
|
||||
|
|
@ -191,7 +191,7 @@ TEST_F(TestSFDP, TestNoSectorMap)
|
|||
header_info.bptbl.device_size_bytes = device_size;
|
||||
|
||||
// No need to read anything
|
||||
EXPECT_CALL(sfdp_reader_mock, Call(_, _, _)).Times(0);
|
||||
EXPECT_CALL(sfdp_reader_mock, Call(_, _, _, _, _, _)).Times(0);
|
||||
|
||||
EXPECT_EQ(0, sfdp_parse_sector_map_table(sfdp_reader_callback, header_info));
|
||||
|
||||
|
|
@ -208,9 +208,17 @@ TEST_F(TestSFDP, TestSingleSectorConfig)
|
|||
mbed::sfdp_hdr_info header_info;
|
||||
set_sector_map_param_table(header_info.smptbl, sector_map_single_descriptor, sizeof(sector_map_single_descriptor));
|
||||
|
||||
EXPECT_CALL(sfdp_reader_mock, Call(sector_map_start_addr, _, sizeof(sector_map_single_descriptor)))
|
||||
.Times(1)
|
||||
.WillOnce(Return(0));
|
||||
EXPECT_CALL(
|
||||
sfdp_reader_mock,
|
||||
Call(
|
||||
sector_map_start_addr,
|
||||
mbed::SFDP_READ_CMD_ADDR_TYPE,
|
||||
mbed::SFDP_READ_CMD_INST,
|
||||
mbed::SFDP_READ_CMD_DUMMY_CYCLES,
|
||||
_,
|
||||
sizeof(sector_map_single_descriptor)
|
||||
)
|
||||
).Times(1).WillOnce(Return(0));
|
||||
|
||||
EXPECT_EQ(0, sfdp_parse_sector_map_table(sfdp_reader_callback, header_info));
|
||||
|
||||
|
|
@ -241,9 +249,17 @@ TEST_F(TestSFDP, TestSFDPReadFailure)
|
|||
mbed::sfdp_hdr_info header_info;
|
||||
set_sector_map_param_table(header_info.smptbl, sector_map_single_descriptor, sizeof(sector_map_single_descriptor));
|
||||
|
||||
EXPECT_CALL(sfdp_reader_mock, Call(sector_map_start_addr, _, sizeof(sector_map_single_descriptor)))
|
||||
.Times(1)
|
||||
.WillOnce(Return(-1)); // Emulate read failure
|
||||
EXPECT_CALL(
|
||||
sfdp_reader_mock,
|
||||
Call(
|
||||
sector_map_start_addr,
|
||||
mbed::SFDP_READ_CMD_ADDR_TYPE,
|
||||
mbed::SFDP_READ_CMD_INST,
|
||||
mbed::SFDP_READ_CMD_DUMMY_CYCLES,
|
||||
_,
|
||||
sizeof(sector_map_single_descriptor)
|
||||
)
|
||||
).Times(1).WillOnce(Return(-1)); // Emulate read failure
|
||||
|
||||
EXPECT_EQ(-1, sfdp_parse_sector_map_table(sfdp_reader_callback, header_info));
|
||||
}
|
||||
|
|
@ -261,9 +277,17 @@ TEST_F(TestSFDP, TestMoreRegionsThanSupported)
|
|||
sizeof(sector_map_single_descriptor_twelve_regions)
|
||||
);
|
||||
|
||||
EXPECT_CALL(sfdp_reader_mock, Call(sector_map_start_addr, _, sizeof(sector_map_single_descriptor_twelve_regions)))
|
||||
.Times(1)
|
||||
.WillOnce(Return(0));
|
||||
EXPECT_CALL(
|
||||
sfdp_reader_mock,
|
||||
Call(
|
||||
sector_map_start_addr,
|
||||
mbed::SFDP_READ_CMD_ADDR_TYPE,
|
||||
mbed::SFDP_READ_CMD_INST,
|
||||
mbed::SFDP_READ_CMD_DUMMY_CYCLES,
|
||||
_,
|
||||
sizeof(sector_map_single_descriptor_twelve_regions)
|
||||
)
|
||||
).Times(1).WillOnce(Return(0));
|
||||
|
||||
EXPECT_EQ(-1, sfdp_parse_sector_map_table(sfdp_reader_callback, header_info));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue