diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp index bf054c650e..da1bddeeef 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp @@ -15,6 +15,7 @@ */ #include "drivers/internal/SFDP.h" +#include "platform/Callback.h" #include "QSPIFBlockDevice.h" #include #include "rtos/ThisThread.h" @@ -628,59 +629,14 @@ int QSPIFBlockDevice::remove_csel_instance(PinName csel) /*********************************************************/ int QSPIFBlockDevice::_sfdp_parse_sfdp_headers(mbed::sfdp_hdr_info &hdr_info) { - bd_addr_t addr = 0x0; - int number_of_param_headers = 0; - size_t data_length; - - { - data_length = SFDP_HEADER_SIZE; - uint8_t sfdp_header[SFDP_HEADER_SIZE]; - - qspi_status_t status = _qspi_send_read_sfdp_command(addr, (char *)sfdp_header, data_length); - if (status != QSPI_STATUS_OK) { - tr_error("init - Retrieving SFDP Header failed"); - return -1; - } - - number_of_param_headers = sfdp_parse_sfdp_header((sfdp_hdr *)sfdp_header); - if (number_of_param_headers < 0) { - return number_of_param_headers; - } - } - - addr += SFDP_HEADER_SIZE; - - { - data_length = SFDP_HEADER_SIZE; - uint8_t param_header[SFDP_HEADER_SIZE]; - qspi_status_t status; - int hdr_status; - - // Loop over Param Headers and parse them (currently supports Basic Param Table and Sector Region Map Table) - for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) { - status = _qspi_send_read_sfdp_command(addr, (char *)param_header, data_length); - if (status != QSPI_STATUS_OK) { - tr_error("init - Retrieving Parameter Header %d failed", i_ind + 1); - return -1; - } - - hdr_status = sfdp_parse_single_param_header((sfdp_prm_hdr *)param_header, hdr_info); - if (hdr_status < 0) { - return hdr_status; - } - - addr += SFDP_HEADER_SIZE; - } - } - - return 0; + return sfdp_parse_headers(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command), hdr_info); } int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size) { uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */ - qspi_status_t status = _qspi_send_read_sfdp_command(basic_table_addr, (char *) param_table, basic_table_size); + int status = _qspi_send_read_sfdp_command(basic_table_addr, (char *)param_table, basic_table_size); if (status != QSPI_STATUS_OK) { tr_error("Init - Read SFDP First Table Failed"); return -1; @@ -1161,7 +1117,7 @@ int QSPIFBlockDevice::_sfdp_parse_sector_map_table(uint32_t sector_map_table_add // Default set to all type bits 1-4 are common int min_common_erase_type_bits = ERASE_BITMASK_ALL; - qspi_status_t status = _qspi_send_read_sfdp_command(sector_map_table_addr, (char *) sector_map_table, sector_map_table_size); + int status = _qspi_send_read_sfdp_command(sector_map_table_addr, (char *)sector_map_table, sector_map_table_size); if (status != QSPI_STATUS_OK) { tr_error("Init - Read SFDP First Table Failed"); return -1; @@ -1604,7 +1560,7 @@ qspi_status_t QSPIFBlockDevice::_qspi_send_general_command(qspi_inst_t instructi return QSPI_STATUS_OK; } -qspi_status_t 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(bd_addr_t addr, void *rx_buffer, bd_size_t rx_length) { size_t rx_len = rx_length; diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h index 352a1b9c17..a3ca84ada2 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h @@ -19,6 +19,7 @@ #include "drivers/QSPI.h" #include "drivers/internal/SFDP.h" #include "features/storage/blockdevice/BlockDevice.h" +#include "platform/Callback.h" #ifndef MBED_CONF_QSPIF_QSPI_IO0 #define MBED_CONF_QSPIF_QSPI_IO0 NC @@ -249,6 +250,11 @@ public: virtual const char *get_type() const; private: + + // SFDP helpers + friend int mbed::sfdp_parse_headers(mbed::Callback sfdp_reader, + mbed::sfdp_hdr_info &hdr_info); + // Internal functions @@ -280,7 +286,7 @@ 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 - qspi_status_t _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, 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); diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp index 0f6fac4721..3d2966dec2 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp @@ -528,6 +528,21 @@ 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) +{ + // Set 1-1-1 bus mode for SFDP header parsing + // Initial SFDP read tables are read with 8 dummy cycles + _read_dummy_and_mode_cycles = 8; + _dummy_and_mode_cycles = 8; + + int status = _spi_send_read_command(SPIF_SFDP, (uint8_t *)rx_buffer, addr, rx_length); + if (status < 0) { + tr_error("_spi_send_read_sfdp_command failed"); + } + + return status; +} + spif_bd_error SPIFBlockDevice::_spi_send_program_command(int prog_inst, const void *buffer, bd_addr_t addr, bd_size_t size) { @@ -716,57 +731,7 @@ int SPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, si int SPIFBlockDevice::_sfdp_parse_sfdp_headers(sfdp_hdr_info &hdr_info) { - bd_addr_t addr = 0x0; - int number_of_param_headers = 0; - size_t data_length; - - { - data_length = SFDP_HEADER_SIZE; - uint8_t sfdp_header[SFDP_HEADER_SIZE]; - - // Set 1-1-1 bus mode for SFDP header parsing - // Initial SFDP read tables are read with 8 dummy cycles - _read_dummy_and_mode_cycles = 8; - _dummy_and_mode_cycles = 8; - - spif_bd_error status = _spi_send_read_command(SPIF_SFDP, sfdp_header, addr /*address*/, data_length); - if (status != SPIF_BD_ERROR_OK) { - tr_error("init - Read SFDP Failed"); - return -1; - } - - number_of_param_headers = sfdp_parse_sfdp_header((sfdp_hdr *)sfdp_header); - if (number_of_param_headers < 0) { - return number_of_param_headers; - } - } - - addr += SFDP_HEADER_SIZE; - - { - data_length = SFDP_HEADER_SIZE; - uint8_t param_header[SFDP_HEADER_SIZE]; - spif_bd_error status; - int hdr_status; - - // Loop over Param Headers and parse them (currently supported Basic Param Table and Sector Region Map Table) - for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) { - - status = _spi_send_read_command(SPIF_SFDP, param_header, addr, data_length); - if (status != SPIF_BD_ERROR_OK) { - tr_error("init - Read Param Table %d Failed", i_ind + 1); - return -1; - } - - hdr_status = sfdp_parse_single_param_header((sfdp_prm_hdr *)param_header, hdr_info); - if (hdr_status < 0) { - return hdr_status; - } - - addr += SFDP_HEADER_SIZE; - } - } - return 0; + return sfdp_parse_headers(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command), hdr_info); } unsigned int SPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size) diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h index 6d8b7e62f0..d847d364b1 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h @@ -225,6 +225,9 @@ 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); + // Parse SFDP Headers and retrieve Basic Param and Sector Map Tables (if exist) int _sfdp_parse_sfdp_headers(mbed::sfdp_hdr_info &hdr_info); @@ -301,6 +304,11 @@ private: int _erase_instruction; int _erase4k_inst; // Legacy 4K erase instruction (default 0x20h) + // SFDP helpers + friend int mbed::sfdp_parse_headers(mbed::Callback sfdp_reader, + mbed::sfdp_hdr_info &hdr_info); + + // Up To 4 Erase Types are supported by SFDP (each with its own command Instruction and Size) int _erase_type_inst_arr[MAX_NUM_OF_ERASE_TYPES]; unsigned int _erase_type_size_arr[MAX_NUM_OF_ERASE_TYPES]; diff --git a/drivers/internal/SFDP.h b/drivers/internal/SFDP.h index 52af7b0fe8..012b033a6f 100644 --- a/drivers/internal/SFDP.h +++ b/drivers/internal/SFDP.h @@ -20,6 +20,8 @@ #include #include +#include "features/storage/blockdevice/BlockDevice.h" +#include "platform/Callback.h" namespace mbed { @@ -61,12 +63,22 @@ struct sfdp_prm_hdr { */ int sfdp_parse_sfdp_header(sfdp_hdr *sfdp_hdr_ptr); -/** Parse Parameter Headers +/** Parse Parameter Header * @param parameter_header Pointer to memory holding a single SFDP Parameter header * @param hdr_info Reference to a Parameter Table structure where info about the table is written * @return 0 on success, -1 on failure */ int sfdp_parse_single_param_header(sfdp_prm_hdr *parameter_header, sfdp_hdr_info &hdr_info); +/** Parse SFDP 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 hdr_info All information parsed from the headers gets passed back on this structure + * + * @return 0 on success, negative error code on failure + */ +int sfdp_parse_headers(Callback sfdp_reader, sfdp_hdr_info &hdr_info); + } /* namespace mbed */ #endif diff --git a/drivers/source/SFDP.cpp b/drivers/source/SFDP.cpp index 587fe890aa..906b5b750d 100644 --- a/drivers/source/SFDP.cpp +++ b/drivers/source/SFDP.cpp @@ -83,5 +83,56 @@ int sfdp_parse_single_param_header(sfdp_prm_hdr *phdr, sfdp_hdr_info &hdr_info) return 0; } + +int sfdp_parse_headers(Callback sfdp_reader, sfdp_hdr_info &hdr_info) +{ + bd_addr_t addr = 0x0; + int number_of_param_headers = 0; + size_t data_length; + + { + data_length = SFDP_HEADER_SIZE; + uint8_t sfdp_header[SFDP_HEADER_SIZE]; + + int status = sfdp_reader(addr, sfdp_header, data_length); + if (status < 0) { + tr_error("retrieving SFDP Header failed"); + return -1; + } + + number_of_param_headers = sfdp_parse_sfdp_header((sfdp_hdr *)sfdp_header); + if (number_of_param_headers < 0) { + return number_of_param_headers; + } + } + + addr += SFDP_HEADER_SIZE; + + { + data_length = SFDP_HEADER_SIZE; + uint8_t param_header[SFDP_HEADER_SIZE]; + int status; + int hdr_status; + + // Loop over Param Headers and parse them (currently supports Basic Param Table and Sector Region Map Table) + for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) { + status = sfdp_reader(addr, param_header, data_length); + if (status < 0) { + tr_error("retrieving Parameter Header %d failed", i_ind + 1); + return -1; + } + + hdr_status = sfdp_parse_single_param_header((sfdp_prm_hdr *)param_header, hdr_info); + if (hdr_status < 0) { + return hdr_status; + } + + addr += SFDP_HEADER_SIZE; + } + } + + return 0; +} + } /* namespace mbed */ #endif /* (DEVICE_SPI || DEVICE_QSPI) */