Skip to content

Commit 952799c

Browse files
authored
Merge pull request #12270 from VeijoPesonen/bugfix_sfdp_parse_sfdp_headers
BUGFIX: SFDP Sector Map Table Parameter ID LSB is 0x81
2 parents 9e0642d + 2d9cde9 commit 952799c

File tree

6 files changed

+283
-164
lines changed

6 files changed

+283
-164
lines changed

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp

+15-76
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
* limitations under the License.
1515
*/
1616

17+
#include "drivers/internal/SFDP.h"
18+
#include "platform/Callback.h"
1719
#include "QSPIFBlockDevice.h"
1820
#include <string.h>
1921
#include "rtos/ThisThread.h"
@@ -48,8 +50,6 @@ using namespace mbed;
4850
/* SFDP Header Parsing */
4951
/***********************/
5052
#define QSPIF_RSFDP_DUMMY_CYCLES 8
51-
#define QSPIF_SFDP_HEADER_SIZE 8
52-
#define QSPIF_PARAM_HEADER_SIZE 8
5353

5454
/* Basic Parameters Table Parsing */
5555
/**********************************/
@@ -204,10 +204,8 @@ int QSPIFBlockDevice::init()
204204
}
205205

206206
int status = QSPIF_BD_ERROR_OK;
207-
uint32_t basic_table_addr = 0;
208-
size_t basic_table_size = 0;
209-
uint32_t sector_map_table_addr = 0;
210-
size_t sector_map_table_size = 0;
207+
sfdp_hdr_info hdr_info;
208+
memset(&hdr_info, 0, sizeof hdr_info);
211209

212210
_mutex.lock();
213211

@@ -251,14 +249,14 @@ int QSPIFBlockDevice::init()
251249
}
252250

253251
/**************************** Parse SFDP Header ***********************************/
254-
if (0 != _sfdp_parse_sfdp_headers(basic_table_addr, basic_table_size, sector_map_table_addr, sector_map_table_size)) {
252+
if (0 != _sfdp_parse_sfdp_headers(hdr_info)) {
255253
tr_error("Init - Parse SFDP Headers Failed");
256254
status = QSPIF_BD_ERROR_PARSING_FAILED;
257255
goto exit_point;
258256
}
259257

260258
/**************************** Parse Basic Parameters Table ***********************************/
261-
if (0 != _sfdp_parse_basic_param_table(basic_table_addr, basic_table_size)) {
259+
if (0 != _sfdp_parse_basic_param_table(hdr_info.basic_table_addr, hdr_info.basic_table_size)) {
262260
tr_error("Init - Parse Basic Param Table Failed");
263261
status = QSPIF_BD_ERROR_PARSING_FAILED;
264262
goto exit_point;
@@ -269,10 +267,10 @@ int QSPIFBlockDevice::init()
269267
_device_size_bytes; // If there's no region map, we have a single region sized the entire device size
270268
_region_high_boundary[0] = _device_size_bytes - 1;
271269

272-
if ((sector_map_table_addr != 0) && (0 != sector_map_table_size)) {
273-
tr_debug("Init - Parsing Sector Map Table - addr: 0x%lxh, Size: %d", sector_map_table_addr,
274-
sector_map_table_size);
275-
if (0 != _sfdp_parse_sector_map_table(sector_map_table_addr, sector_map_table_size)) {
270+
if ((hdr_info.sector_map_table_addr != 0) && (0 != hdr_info.sector_map_table_size)) {
271+
tr_debug("Init - Parsing Sector Map Table - addr: 0x%lxh, Size: %d", hdr_info.sector_map_table_addr,
272+
hdr_info.sector_map_table_size);
273+
if (0 != _sfdp_parse_sector_map_table(hdr_info.sector_map_table_addr, hdr_info.sector_map_table_size)) {
276274
tr_error("Init - Parse Sector Map Table Failed");
277275
status = QSPIF_BD_ERROR_PARSING_FAILED;
278276
goto exit_point;
@@ -629,75 +627,16 @@ int QSPIFBlockDevice::remove_csel_instance(PinName csel)
629627
/*********************************************************/
630628
/********** SFDP Parsing and Detection Functions *********/
631629
/*********************************************************/
632-
int QSPIFBlockDevice::_sfdp_parse_sfdp_headers(uint32_t &basic_table_addr, size_t &basic_table_size,
633-
uint32_t &sector_map_table_addr, size_t &sector_map_table_size)
630+
int QSPIFBlockDevice::_sfdp_parse_sfdp_headers(mbed::sfdp_hdr_info &hdr_info)
634631
{
635-
uint8_t sfdp_header[QSPIF_SFDP_HEADER_SIZE];
636-
uint8_t param_header[QSPIF_PARAM_HEADER_SIZE];
637-
size_t data_length = QSPIF_SFDP_HEADER_SIZE;
638-
bd_addr_t addr = 0x0;
639-
640-
qspi_status_t status = _qspi_send_read_sfdp_command(addr, (char *) sfdp_header, data_length);
641-
if (status != QSPI_STATUS_OK) {
642-
tr_error("Init - Read SFDP Failed");
643-
return -1;
644-
}
645-
646-
// Verify SFDP signature for sanity
647-
// Also check that major/minor version is acceptable
648-
if (!(memcmp(&sfdp_header[0], "SFDP", 4) == 0 && sfdp_header[5] == 1)) {
649-
tr_error("Init - Verification of SFDP signature and version failed");
650-
return -1;
651-
} else {
652-
tr_debug("Init - Verification of SFDP signature and version succeeded");
653-
}
654-
655-
// Discover Number of Parameter Headers
656-
int number_of_param_headers = (int)(sfdp_header[6]) + 1;
657-
tr_debug("Number of Param Headers: %d", number_of_param_headers);
658-
659-
660-
addr += QSPIF_SFDP_HEADER_SIZE;
661-
data_length = QSPIF_PARAM_HEADER_SIZE;
662-
663-
// Loop over Param Headers and parse them (currently supports Basic Param Table and Sector Region Map Table)
664-
for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) {
665-
status = _qspi_send_read_sfdp_command(addr, (char *) param_header, data_length);
666-
if (status != QSPI_STATUS_OK) {
667-
tr_error("Init - Read Param Table %d Failed", i_ind + 1);
668-
return -1;
669-
}
670-
671-
// The SFDP spec indicates the standard table is always at offset 0
672-
// in the parameter headers, we check just to be safe
673-
if (param_header[2] != 1) {
674-
tr_error("Param Table %d - Major Version should be 1!", i_ind + 1);
675-
return -1;
676-
}
677-
678-
if ((param_header[0] == 0) && (param_header[7] == 0xFF)) {
679-
// Found Basic Params Table: LSB=0x00, MSB=0xFF
680-
tr_debug("Found Basic Param Table at Table: %d", i_ind + 1);
681-
basic_table_addr = ((param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]));
682-
// Supporting up to 64 Bytes Table (16 DWORDS)
683-
basic_table_size = ((param_header[3] * 4) < SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES) ? (param_header[3] * 4) : 64;
684-
} else if ((param_header[0] == 81) && (param_header[7] == 0xFF)) {
685-
// Found Sector Map Table: LSB=0x81, MSB=0xFF
686-
tr_debug("Found Sector Map Table at Table: %d", i_ind + 1);
687-
sector_map_table_addr = ((param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]));
688-
sector_map_table_size = param_header[3] * 4;
689-
}
690-
addr += QSPIF_PARAM_HEADER_SIZE;
691-
}
692-
693-
return 0;
632+
return sfdp_parse_headers(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command), hdr_info);
694633
}
695634

696635
int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size)
697636
{
698637
uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
699638

700-
qspi_status_t status = _qspi_send_read_sfdp_command(basic_table_addr, (char *) param_table, basic_table_size);
639+
int status = _qspi_send_read_sfdp_command(basic_table_addr, (char *)param_table, basic_table_size);
701640
if (status != QSPI_STATUS_OK) {
702641
tr_error("Init - Read SFDP First Table Failed");
703642
return -1;
@@ -1178,7 +1117,7 @@ int QSPIFBlockDevice::_sfdp_parse_sector_map_table(uint32_t sector_map_table_add
11781117
// Default set to all type bits 1-4 are common
11791118
int min_common_erase_type_bits = ERASE_BITMASK_ALL;
11801119

1181-
qspi_status_t status = _qspi_send_read_sfdp_command(sector_map_table_addr, (char *) sector_map_table, sector_map_table_size);
1120+
int status = _qspi_send_read_sfdp_command(sector_map_table_addr, (char *)sector_map_table, sector_map_table_size);
11821121
if (status != QSPI_STATUS_OK) {
11831122
tr_error("Init - Read SFDP First Table Failed");
11841123
return -1;
@@ -1621,7 +1560,7 @@ qspi_status_t QSPIFBlockDevice::_qspi_send_general_command(qspi_inst_t instructi
16211560
return QSPI_STATUS_OK;
16221561
}
16231562

1624-
qspi_status_t QSPIFBlockDevice::_qspi_send_read_sfdp_command(bd_addr_t addr, void *rx_buffer, bd_size_t rx_length)
1563+
int QSPIFBlockDevice::_qspi_send_read_sfdp_command(bd_addr_t addr, void *rx_buffer, bd_size_t rx_length)
16251564
{
16261565
size_t rx_len = rx_length;
16271566

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h

+9-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
#define MBED_QSPIF_BLOCK_DEVICE_H
1818

1919
#include "drivers/QSPI.h"
20+
#include "drivers/internal/SFDP.h"
2021
#include "features/storage/blockdevice/BlockDevice.h"
22+
#include "platform/Callback.h"
2123

2224
#ifndef MBED_CONF_QSPIF_QSPI_IO0
2325
#define MBED_CONF_QSPIF_QSPI_IO0 NC
@@ -248,6 +250,11 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
248250
virtual const char *get_type() const;
249251

250252
private:
253+
254+
// SFDP helpers
255+
friend int mbed::sfdp_parse_headers(mbed::Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
256+
mbed::sfdp_hdr_info &hdr_info);
257+
251258
// Internal functions
252259

253260

@@ -279,7 +286,7 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
279286
mbed::bd_size_t tx_length, const char *rx_buffer, mbed::bd_size_t rx_length);
280287

281288
// Send command to read from the SFDP table
282-
qspi_status_t _qspi_send_read_sfdp_command(mbed::bd_addr_t addr, void *rx_buffer, mbed::bd_size_t rx_length);
289+
int _qspi_send_read_sfdp_command(mbed::bd_addr_t addr, void *rx_buffer, mbed::bd_size_t rx_length);
283290

284291
// Read the contents of status registers 1 and 2 into a buffer (buffer must have a length of 2)
285292
qspi_status_t _qspi_read_status_registers(uint8_t *reg_buffer);
@@ -312,8 +319,7 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
312319
/* SFDP Detection and Parsing Functions */
313320
/****************************************/
314321
// Parse SFDP Headers and retrieve Basic Param and Sector Map Tables (if exist)
315-
int _sfdp_parse_sfdp_headers(uint32_t &basic_table_addr, size_t &basic_table_size,
316-
uint32_t &sector_map_table_addr, size_t &sector_map_table_size);
322+
int _sfdp_parse_sfdp_headers(mbed::sfdp_hdr_info &hdr_info);
317323

318324
// Parse and Detect required Basic Parameters from Table
319325
int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size);

components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp

+27-83
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17+
#include "drivers/internal/SFDP.h"
1718
#include "SPIFBlockDevice.h"
1819
#include "rtos/ThisThread.h"
1920
#include "mbed_critical.h"
@@ -40,11 +41,6 @@ using namespace mbed;
4041
#define SPIF_STATUS_BIT_WIP 0x1 //Write In Progress
4142
#define SPIF_STATUS_BIT_WEL 0x2 // Write Enable Latch
4243

43-
/* SFDP Header Parsing */
44-
/***********************/
45-
#define SPIF_SFDP_HEADER_SIZE 8
46-
#define SPIF_PARAM_HEADER_SIZE 8
47-
4844
/* Basic Parameters Table Parsing */
4945
/**********************************/
5046
#define SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES 64 /* 16 DWORDS */
@@ -133,12 +129,11 @@ int SPIFBlockDevice::init()
133129
uint8_t vendor_device_ids[4];
134130
size_t data_length = 3;
135131
int status = SPIF_BD_ERROR_OK;
136-
uint32_t basic_table_addr = 0;
137-
size_t basic_table_size = 0;
138-
uint32_t sector_map_table_addr = 0;
139-
size_t sector_map_table_size = 0;
132+
struct sfdp_hdr_info hdr_info;
140133
spif_bd_error spi_status = SPIF_BD_ERROR_OK;
141134

135+
memset(&hdr_info, 0, sizeof hdr_info);
136+
142137
_mutex->lock();
143138

144139
if (!_is_initialized) {
@@ -186,15 +181,15 @@ int SPIFBlockDevice::init()
186181
}
187182

188183
/**************************** Parse SFDP Header ***********************************/
189-
if (0 != _sfdp_parse_sfdp_headers(basic_table_addr, basic_table_size, sector_map_table_addr, sector_map_table_size)) {
184+
if (0 != _sfdp_parse_sfdp_headers(hdr_info)) {
190185
tr_error("init - Parse SFDP Headers Failed");
191186
status = SPIF_BD_ERROR_PARSING_FAILED;
192187
goto exit_point;
193188
}
194189

195190

196191
/**************************** Parse Basic Parameters Table ***********************************/
197-
if (0 != _sfdp_parse_basic_param_table(basic_table_addr, basic_table_size)) {
192+
if (0 != _sfdp_parse_basic_param_table(hdr_info.basic_table_addr, hdr_info.basic_table_size)) {
198193
tr_error("init - Parse Basic Param Table Failed");
199194
status = SPIF_BD_ERROR_PARSING_FAILED;
200195
goto exit_point;
@@ -205,10 +200,10 @@ int SPIFBlockDevice::init()
205200
_device_size_bytes; // If there's no region map, we have a single region sized the entire device size
206201
_region_high_boundary[0] = _device_size_bytes - 1;
207202

208-
if ((sector_map_table_addr != 0) && (0 != sector_map_table_size)) {
209-
tr_debug("init - Parsing Sector Map Table - addr: 0x%" PRIx32 "h, Size: %d", sector_map_table_addr,
210-
sector_map_table_size);
211-
if (0 != _sfdp_parse_sector_map_table(sector_map_table_addr, sector_map_table_size)) {
203+
if ((hdr_info.sector_map_table_addr != 0) && (0 != hdr_info.sector_map_table_size)) {
204+
tr_debug("init - Parsing Sector Map Table - addr: 0x%" PRIx32 "h, Size: %d", hdr_info.sector_map_table_addr,
205+
hdr_info.sector_map_table_size);
206+
if (0 != _sfdp_parse_sector_map_table(hdr_info.sector_map_table_addr, hdr_info.sector_map_table_size)) {
212207
tr_error("init - Parse Sector Map Table Failed");
213208
status = SPIF_BD_ERROR_PARSING_FAILED;
214209
goto exit_point;
@@ -533,6 +528,21 @@ spif_bd_error SPIFBlockDevice::_spi_send_read_command(int read_inst, uint8_t *bu
533528
return SPIF_BD_ERROR_OK;
534529
}
535530

531+
int SPIFBlockDevice::_spi_send_read_sfdp_command(bd_addr_t addr, void *rx_buffer, bd_size_t rx_length)
532+
{
533+
// Set 1-1-1 bus mode for SFDP header parsing
534+
// Initial SFDP read tables are read with 8 dummy cycles
535+
_read_dummy_and_mode_cycles = 8;
536+
_dummy_and_mode_cycles = 8;
537+
538+
int status = _spi_send_read_command(SPIF_SFDP, (uint8_t *)rx_buffer, addr, rx_length);
539+
if (status < 0) {
540+
tr_error("_spi_send_read_sfdp_command failed");
541+
}
542+
543+
return status;
544+
}
545+
536546
spif_bd_error SPIFBlockDevice::_spi_send_program_command(int prog_inst, const void *buffer, bd_addr_t addr,
537547
bd_size_t size)
538548
{
@@ -719,75 +729,9 @@ int SPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, si
719729
return 0;
720730
}
721731

722-
int SPIFBlockDevice::_sfdp_parse_sfdp_headers(uint32_t &basic_table_addr, size_t &basic_table_size,
723-
uint32_t &sector_map_table_addr, size_t &sector_map_table_size)
732+
int SPIFBlockDevice::_sfdp_parse_sfdp_headers(sfdp_hdr_info &hdr_info)
724733
{
725-
uint8_t sfdp_header[16];
726-
uint8_t param_header[SPIF_SFDP_HEADER_SIZE];
727-
size_t data_length = SPIF_SFDP_HEADER_SIZE;
728-
bd_addr_t addr = 0x0;
729-
730-
// Set 1-1-1 bus mode for SFDP header parsing
731-
// Initial SFDP read tables are read with 8 dummy cycles
732-
_read_dummy_and_mode_cycles = 8;
733-
_dummy_and_mode_cycles = 8;
734-
735-
spif_bd_error status = _spi_send_read_command(SPIF_SFDP, sfdp_header, addr /*address*/, data_length);
736-
if (status != SPIF_BD_ERROR_OK) {
737-
tr_error("init - Read SFDP Failed");
738-
return -1;
739-
}
740-
741-
// Verify SFDP signature for sanity
742-
// Also check that major/minor version is acceptable
743-
if (!(memcmp(&sfdp_header[0], "SFDP", 4) == 0 && sfdp_header[5] == 1)) {
744-
tr_error("init - _verify SFDP signature and version Failed");
745-
return -1;
746-
} else {
747-
tr_debug("init - verified SFDP Signature and version Successfully");
748-
}
749-
750-
// Discover Number of Parameter Headers
751-
int number_of_param_headers = (int)(sfdp_header[6]) + 1;
752-
tr_debug("number of Param Headers: %d", number_of_param_headers);
753-
754-
addr += SPIF_SFDP_HEADER_SIZE;
755-
data_length = SPIF_PARAM_HEADER_SIZE;
756-
757-
// Loop over Param Headers and parse them (currently supported Basic Param Table and Sector Region Map Table)
758-
for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) {
759-
760-
status = _spi_send_read_command(SPIF_SFDP, param_header, addr, data_length);
761-
if (status != SPIF_BD_ERROR_OK) {
762-
tr_error("init - Read Param Table %d Failed", i_ind + 1);
763-
return -1;
764-
}
765-
766-
// The SFDP spec indicates the standard table is always at offset 0
767-
// in the parameter headers, we check just to be safe
768-
if (param_header[2] != 1) {
769-
tr_error("Param Table %d - Major Version should be 1!", i_ind + 1);
770-
return -1;
771-
}
772-
773-
if ((param_header[0] == 0) && (param_header[7] == 0xFF)) {
774-
// Found Basic Params Table: LSB=0x00, MSB=0xFF
775-
tr_debug("Found Basic Param Table at Table: %d", i_ind + 1);
776-
basic_table_addr = ((param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]));
777-
// Supporting up to 64 Bytes Table (16 DWORDS)
778-
basic_table_size = ((param_header[3] * 4) < SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES) ? (param_header[3] * 4) : 64;
779-
780-
} else if ((param_header[0] == 81) && (param_header[7] == 0xFF)) {
781-
// Found Sector Map Table: LSB=0x81, MSB=0xFF
782-
tr_debug("Found Sector Map Table at Table: %d", i_ind + 1);
783-
sector_map_table_addr = ((param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]));
784-
sector_map_table_size = param_header[3] * 4;
785-
786-
}
787-
addr += SPIF_PARAM_HEADER_SIZE;
788-
789-
}
790-
return 0;
734+
return sfdp_parse_headers(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command), hdr_info);
791735
}
792736

793737
unsigned int SPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size)

0 commit comments

Comments
 (0)