Q/SPIFBlockDevice: Separates SFDP Header retrieval

Separates SFDP header retrieval and moves it as a part of the earlier
introduced SFDP file.

Purpose is to abstract away differences between SPIF and QSPIF devices
when it comes to fetching the SFDP headers from a device.
pull/12270/head
Veijo Pesonen 2020-01-20 15:50:37 +02:00
parent aa599412e6
commit 6bd3933652
6 changed files with 100 additions and 102 deletions

View File

@ -15,6 +15,7 @@
*/
#include "drivers/internal/SFDP.h"
#include "platform/Callback.h"
#include "QSPIFBlockDevice.h"
#include <string.h>
#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;

View File

@ -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<int(bd_addr_t, void *, bd_size_t)> 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);

View File

@ -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)

View File

@ -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<int(bd_addr_t, void *, bd_size_t)> 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];

View File

@ -20,6 +20,8 @@
#include <cstddef>
#include <cstdint>
#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<int(bd_addr_t, void *, bd_size_t)> sfdp_reader, sfdp_hdr_info &hdr_info);
} /* namespace mbed */
#endif

View File

@ -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<int(bd_addr_t, void *, bd_size_t)> 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) */