Skip to content

Commit 5aab4c4

Browse files
authored
Merge pull request #12524 from VeijoPesonen/sfdp_split_4
Bugfix: Concurrent SFDP header address init fixed
2 parents ea3761f + 2605ce6 commit 5aab4c4

File tree

6 files changed

+175
-123
lines changed

6 files changed

+175
-123
lines changed

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp

+27-36
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam
179179

180180
int QSPIFBlockDevice::init()
181181
{
182+
int status = QSPIF_BD_ERROR_OK;
183+
182184
if (_unique_device_status == 0) {
183185
tr_debug("QSPIFBlockDevice csel: %d", (int)_csel);
184186
} else if (_unique_device_status == -1) {
@@ -189,12 +191,6 @@ int QSPIFBlockDevice::init()
189191
return QSPIF_BD_ERROR_DEVICE_MAX_EXCEED;
190192
}
191193

192-
int status = QSPIF_BD_ERROR_OK;
193-
_sfdp_info.bptbl.addr = 0x0;
194-
_sfdp_info.bptbl.size = 0;
195-
_sfdp_info.smptbl.addr = 0x0;
196-
_sfdp_info.smptbl.size = 0;
197-
198194
_mutex.lock();
199195

200196
// 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)
@@ -230,36 +226,33 @@ int QSPIFBlockDevice::init()
230226
goto exit_point;
231227
}
232228

233-
if (0 != _handle_vendor_quirks()) {
229+
if (_handle_vendor_quirks() < 0) {
234230
tr_error("Init - Could not read vendor id");
235231
status = QSPIF_BD_ERROR_DEVICE_ERROR;
236232
goto exit_point;
237233
}
238234

239-
/**************************** Parse SFDP Header ***********************************/
240-
if (sfdp_parse_headers(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command), _sfdp_info) < 0) {
241-
tr_error("Init - Parse SFDP Headers Failed");
242-
status = QSPIF_BD_ERROR_PARSING_FAILED;
243-
goto exit_point;
244-
}
235+
/**************************** Parse SFDP data ***********************************/
236+
{
237+
_sfdp_info.bptbl.addr = 0x0;
238+
_sfdp_info.bptbl.size = 0;
239+
_sfdp_info.smptbl.addr = 0x0;
240+
_sfdp_info.smptbl.size = 0;
245241

246-
/**************************** Parse Basic Parameters Table ***********************************/
247-
if (_sfdp_parse_basic_param_table(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command),
248-
_sfdp_info) < 0) {
249-
tr_error("Init - Parse Basic Param Table Failed");
250-
status = QSPIF_BD_ERROR_PARSING_FAILED;
251-
goto exit_point;
252-
}
242+
if (sfdp_parse_headers(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command), _sfdp_info) < 0) {
243+
tr_error("Init - Parse SFDP Headers Failed");
244+
status = QSPIF_BD_ERROR_PARSING_FAILED;
245+
goto exit_point;
246+
}
253247

254-
/**************************** Parse Sector Map Table ***********************************/
255-
_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
256-
_sfdp_info.smptbl.region_high_boundary[0] = _sfdp_info.bptbl.device_size_bytes - 1;
248+
if (_sfdp_parse_basic_param_table(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command),
249+
_sfdp_info) < 0) {
250+
tr_error("Init - Parse Basic Param Table Failed");
251+
status = QSPIF_BD_ERROR_PARSING_FAILED;
252+
goto exit_point;
253+
}
257254

258-
if ((_sfdp_info.smptbl.addr != 0) && (0 != _sfdp_info.smptbl.size)) {
259-
tr_debug("Init - Parsing Sector Map Table - addr: 0x%lxh, Size: %d", _sfdp_info.smptbl.addr,
260-
_sfdp_info.smptbl.size);
261-
if (sfdp_parse_sector_map_table(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command),
262-
_sfdp_info.smptbl) < 0) {
255+
if (sfdp_parse_sector_map_table(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command), _sfdp_info) < 0) {
263256
tr_error("Init - Parse Sector Map Table Failed");
264257
status = QSPIF_BD_ERROR_PARSING_FAILED;
265258
goto exit_point;
@@ -630,17 +623,15 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(Callback<int(bd_addr_t, void
630623
}
631624

632625
// Check that density is not greater than 4 gigabits (i.e. that addressing beyond 4 bytes is not required)
633-
if ((param_table[7] & 0x80) != 0) {
634-
tr_error("Init - verify flash density failed");
626+
if (sfdp_detect_addressability(param_table, _sfdp_info.bptbl) < 0) {
627+
tr_error("Verify 4byte addressing failed");
635628
return -1;
636629
}
637630

638-
// Get device density (stored in bits - 1)
639-
uint32_t density_bits = ((param_table[7] << 24) |
640-
(param_table[6] << 16) |
641-
(param_table[5] << 8) |
642-
param_table[4]);
643-
sfdp_info.bptbl.device_size_bytes = (density_bits + 1) / 8;
631+
if (sfdp_detect_device_density(param_table, _sfdp_info.bptbl) < 0) {
632+
tr_error("Detecting device density failed");
633+
return -1;
634+
}
644635

645636
// Set Page Size (QSPI write must be done on Page limits)
646637
_page_size_bytes = sfdp_detect_page_size(param_table, sfdp_info.bptbl.size);

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h

+3-17
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,9 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
306306
// Enable Fast Mode - for flash chips with low power default
307307
int _enable_fast_mode();
308308

309+
// Query vendor ID and handle special behavior that isn't covered by SFDP data
310+
int _handle_vendor_quirks();
311+
309312
/****************************************/
310313
/* SFDP Detection and Parsing Functions */
311314
/****************************************/
@@ -329,23 +332,6 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
329332
// Detect 4-byte addressing mode and enable it if supported
330333
int _sfdp_detect_and_enable_4byte_addressing(uint8_t *basic_param_table_ptr, int basic_param_table_size);
331334

332-
// Query vendor ID and handle special behavior that isn't covered by SFDP data
333-
int _handle_vendor_quirks();
334-
335-
/***********************/
336-
/* Utilities Functions */
337-
/***********************/
338-
// Find the region to which the given offset belong to
339-
int _utils_find_addr_region(mbed::bd_size_t offset, mbed::sfdp_smptbl_info &smptbl);
340-
341-
// Iterate on all supported Erase Types of the Region to which the offset belong to.
342-
// Iterates from highest type to lowest
343-
int _utils_iterate_next_largest_erase_type(uint8_t &bitfield,
344-
int size,
345-
int offset,
346-
int region,
347-
mbed::sfdp_smptbl_info &smptbl);
348-
349335
private:
350336
enum qspif_clear_protection_method_t {
351337
QSPIF_BP_ULBPR, // Issue global protection unlock instruction

components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp

+54-54
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,7 @@ SPIFBlockDevice::SPIFBlockDevice(PinName mosi, PinName miso, PinName sclk, PinNa
115115

116116
int SPIFBlockDevice::init()
117117
{
118-
uint8_t vendor_device_ids[4];
119-
size_t data_length = 3;
120118
int status = SPIF_BD_ERROR_OK;
121-
spif_bd_error spi_status = SPIF_BD_ERROR_OK;
122-
123-
_sfdp_info.bptbl.addr = 0x0;
124-
_sfdp_info.bptbl.size = 0;
125-
_sfdp_info.smptbl.addr = 0x0;
126-
_sfdp_info.smptbl.size = 0;
127119

128120
_mutex->lock();
129121

@@ -146,56 +138,39 @@ int SPIFBlockDevice::init()
146138
tr_debug("Initialize flash memory OK");
147139
}
148140

149-
/* Read Manufacturer ID (1byte), and Device ID (2bytes)*/
150-
spi_status = _spi_send_general_command(SPIF_RDID, SPI_NO_ADDRESS_COMMAND, NULL, 0, (char *)vendor_device_ids,
151-
data_length);
152-
if (spi_status != SPIF_BD_ERROR_OK) {
153-
tr_error("init - Read Vendor ID Failed");
141+
if (_handle_vendor_quirks() < 0) {
142+
tr_error("Init - Could not read vendor id");
154143
status = SPIF_BD_ERROR_DEVICE_ERROR;
155144
goto exit_point;
156145
}
157146

158-
switch (vendor_device_ids[0]) {
159-
case 0xbf:
160-
// SST devices come preset with block protection
161-
// enabled for some regions, issue global protection unlock to clear
162-
_set_write_enable();
163-
_spi_send_general_command(SPIF_ULBPR, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0);
164-
break;
165-
}
166-
167147
//Synchronize Device
168148
if (false == _is_mem_ready()) {
169149
tr_error("init - _is_mem_ready Failed");
170150
status = SPIF_BD_ERROR_READY_FAILED;
171151
goto exit_point;
172152
}
173153

174-
/**************************** Parse SFDP Header ***********************************/
175-
if (sfdp_parse_headers(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command), _sfdp_info) < 0) {
176-
tr_error("init - Parse SFDP Headers Failed");
177-
status = SPIF_BD_ERROR_PARSING_FAILED;
178-
goto exit_point;
179-
}
180-
154+
/**************************** Parse SFDP headers and tables ***********************************/
155+
{
156+
_sfdp_info.bptbl.addr = 0x0;
157+
_sfdp_info.bptbl.size = 0;
158+
_sfdp_info.smptbl.addr = 0x0;
159+
_sfdp_info.smptbl.size = 0;
181160

182-
/**************************** Parse Basic Parameters Table ***********************************/
183-
if (_sfdp_parse_basic_param_table(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command), _sfdp_info) < 0) {
184-
tr_error("init - Parse Basic Param Table Failed");
185-
status = SPIF_BD_ERROR_PARSING_FAILED;
186-
goto exit_point;
187-
}
161+
if (sfdp_parse_headers(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command), _sfdp_info) < 0) {
162+
tr_error("init - Parse SFDP Headers Failed");
163+
status = SPIF_BD_ERROR_PARSING_FAILED;
164+
goto exit_point;
165+
}
188166

189-
/**************************** Parse Sector Map Table ***********************************/
190-
_sfdp_info.smptbl.region_size[0] = _sfdp_info.bptbl.device_size_bytes;
191-
// If there's no region map, we have a single region sized the entire device size
192-
_sfdp_info.smptbl.region_high_boundary[0] = _sfdp_info.bptbl.device_size_bytes - 1;
167+
if (_sfdp_parse_basic_param_table(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command), _sfdp_info) < 0) {
168+
tr_error("init - Parse Basic Param Table Failed");
169+
status = SPIF_BD_ERROR_PARSING_FAILED;
170+
goto exit_point;
171+
}
193172

194-
if ((_sfdp_info.smptbl.addr != 0) && (0 != _sfdp_info.smptbl.size)) {
195-
tr_debug("init - Parsing Sector Map Table - addr: 0x%" PRIx32 "h, Size: %d", _sfdp_info.smptbl.addr,
196-
_sfdp_info.smptbl.size);
197-
if (sfdp_parse_sector_map_table(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command),
198-
_sfdp_info.smptbl) < 0) {
173+
if (sfdp_parse_sector_map_table(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command), _sfdp_info) < 0) {
199174
tr_error("init - Parse Sector Map Table Failed");
200175
status = SPIF_BD_ERROR_PARSING_FAILED;
201176
goto exit_point;
@@ -629,19 +604,15 @@ int SPIFBlockDevice::_sfdp_parse_basic_param_table(Callback<int(bd_addr_t, void
629604
}
630605

631606
// Check address size, currently only supports 3byte addresses
632-
if ((param_table[2] & 0x4) != 0 || (param_table[7] & 0x80) != 0) {
633-
tr_error("init - verify 3byte addressing Failed");
607+
if (sfdp_detect_addressability(param_table, _sfdp_info.bptbl) < 0) {
608+
tr_error("Verify 3byte addressing failed");
634609
return -1;
635610
}
636611

637-
// Get device density (stored in bits - 1)
638-
uint32_t density_bits = (
639-
(param_table[7] << 24) |
640-
(param_table[6] << 16) |
641-
(param_table[5] << 8) |
642-
param_table[4]);
643-
sfdp_info.bptbl.device_size_bytes = (density_bits + 1) / 8;
644-
tr_debug("Density bits: %" PRIu32 " , device size: %llu bytes", density_bits, sfdp_info.bptbl.device_size_bytes);
612+
if (sfdp_detect_device_density(param_table, _sfdp_info.bptbl) < 0) {
613+
tr_error("Detecting device density failed");
614+
return -1;
615+
}
645616

646617
// Set Default read/program/erase Instructions
647618
_read_instruction = SPIF_READ;
@@ -778,3 +749,32 @@ int SPIFBlockDevice::_set_write_enable()
778749
} while (false);
779750
return status;
780751
}
752+
753+
int SPIFBlockDevice::_handle_vendor_quirks()
754+
{
755+
uint8_t vendor_device_ids[4];
756+
size_t data_length = 3;
757+
758+
/* Read Manufacturer ID (1byte), and Device ID (2bytes)*/
759+
spif_bd_error spi_status = _spi_send_general_command(SPIF_RDID, SPI_NO_ADDRESS_COMMAND, NULL, 0,
760+
(char *)vendor_device_ids,
761+
data_length);
762+
763+
if (spi_status != SPIF_BD_ERROR_OK) {
764+
tr_error("Read Vendor ID Failed");
765+
return -1;
766+
}
767+
768+
tr_debug("Vendor device ID = 0x%x 0x%x 0x%x", vendor_device_ids[0], vendor_device_ids[1], vendor_device_ids[2]);
769+
770+
switch (vendor_device_ids[0]) {
771+
case 0xbf:
772+
// SST devices come preset with block protection
773+
// enabled for some regions, issue global protection unlock to clear
774+
_set_write_enable();
775+
_spi_send_general_command(SPIF_ULBPR, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0);
776+
break;
777+
}
778+
779+
return 0;
780+
}

components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h

+3
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ class SPIFBlockDevice : public mbed::BlockDevice {
260260
// Wait on status register until write not-in-progress
261261
bool _is_mem_ready();
262262

263+
// Query vendor ID and handle special behavior that isn't covered by SFDP data
264+
int _handle_vendor_quirks();
265+
263266
private:
264267
// Master side hardware
265268
mbed::SPI _spi;

drivers/internal/SFDP.h

+21-3
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,11 @@ int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
9090
* Retrieves the table from a device and parses the information contained by the table
9191
*
9292
* @param sfdp_reader Callback function used to read headers from within a device
93-
* @param[out] smtbl Contains the results of parsing the JEDEC Sector Map Table
93+
* @param[out] sfdp_info Contains the results of parsing the JEDEC Sector Map Table
9494
*
9595
* @return MBED_SUCCESS on success, negative error code on failure
9696
*/
97-
int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader, sfdp_smptbl_info &smtbl);
97+
int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader, sfdp_hdr_info &sfdp_info);
9898

9999
/** Detect page size used for writing on flash
100100
*
@@ -131,7 +131,7 @@ int sfdp_find_addr_region(bd_size_t offset, const sfdp_hdr_info &sfdp_info);
131131
* @param size Upper limit for region size
132132
* @param offset Offset value
133133
* @param region Region number
134-
* @param smtbl Information about different erase types
134+
* @param smptbl Information about different erase types
135135
*
136136
* @return Largest erase type
137137
*/
@@ -141,6 +141,24 @@ int sfdp_iterate_next_largest_erase_type(uint8_t &bitfield,
141141
int region,
142142
const sfdp_smptbl_info &smptbl);
143143

144+
/** Detect device density
145+
*
146+
* @param bptbl_ptr Pointer to memory holding a Basic Parameter Table structure
147+
* @param bptbl_info Basic Parameter Table information structure
148+
*
149+
* @return 0 on success, negative error code on failure
150+
*/
151+
int sfdp_detect_device_density(uint8_t *bptbl_ptr, sfdp_bptbl_info &bptbl_info);
152+
153+
/** Detect is it possible to access the whole memory region
154+
*
155+
* @param bptbl_ptr Pointer to memory holding a Basic Parameter Table structure
156+
* @param bptbl_info Basic Parameter Table information structure
157+
*
158+
* @return 0 on success, negative error code on failure
159+
*/
160+
int sfdp_detect_addressability(uint8_t *bptbl_ptr, sfdp_bptbl_info &bptbl_info);
161+
144162
/** @}*/
145163
} /* namespace mbed */
146164
#endif

0 commit comments

Comments
 (0)