Skip to content

Commit 64d965b

Browse files
committed
fix crash during FlashIAP by temporarily increase Flash latency
fix init-deinit-init sequence of OSPIFBlockDevice by performing a soft reset at deinit
1 parent e1e2419 commit 64d965b

File tree

3 files changed

+92
-75
lines changed

3 files changed

+92
-75
lines changed

storage/blockdevice/COMPONENT_OSPIF/include/OSPIF/OSPIFBlockDevice.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@ enum ospif_polarity_mode {
104104
OSPIF_POLARITY_MODE_1 /* CPOL=1, CPHA=1 */
105105
};
106106

107+
/** Enum ospif soft reset modes
108+
*
109+
* @enum ospif_soft_reset_mode
110+
*/
111+
enum ospif_soft_reset_mode {
112+
OSPIF_SOFT_RESET_UNSUPPORTED = 0, /* Soft reset not supported */
113+
OSPIF_DIERCT_SOFT_RESET, /* Direct soft reset mode */
114+
OSPIF_ENABLE_AND_SOFT_RESET /* Enable and soft reset mode */
115+
};
116+
107117
#define OSPIF_MAX_ACTIVE_FLASH_DEVICES 10
108118

109119
/** BlockDevice for SFDP based flash devices over OSPI bus
@@ -389,6 +399,9 @@ class OSPIFBlockDevice : public mbed::BlockDevice {
389399
// Enable Quad mode if supported (1-1-4, 1-4-4, 4-4-4 bus modes)
390400
int _sfdp_set_quad_enabled(uint8_t *basic_param_table_ptr);
391401

402+
// Perform soft reset if supported - returns error if soft reset is not supported
403+
int _soft_reset();
404+
392405
// Enable QPI mode (4-4-4)
393406
int _sfdp_set_qpi_enabled(uint8_t *basic_param_table_ptr);
394407

@@ -461,6 +474,8 @@ class OSPIFBlockDevice : public mbed::BlockDevice {
461474
uint8_t _dummy_cycles; //Number of Dummy cycles required by Current Bus Mode
462475
ospi_bus_width_t _data_width; //Bus width for Data phase
463476

477+
ospif_soft_reset_mode _soft_reset_mode; // Soft Reset mode
478+
464479
uint32_t _init_ref_count;
465480
bool _is_initialized;
466481
#ifdef MX_FLASH_SUPPORT_RWW

storage/blockdevice/COMPONENT_OSPIF/source/OSPIFBlockDevice.cpp

Lines changed: 53 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,8 @@ OSPIFBlockDevice::OSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam
201201
int clock_mode, int freq)
202202
: _ospi(io0, io1, io2, io3, io4, io5, io6, io7, sclk, csel, dqs, clock_mode), _csel(csel), _freq(freq),
203203
_init_ref_count(0),
204-
_is_initialized(false)
204+
_is_initialized(false),
205+
_soft_reset_mode(OSPIF_SOFT_RESET_UNSUPPORTED)
205206
{
206207
_unique_device_status = add_new_csel_instance(csel);
207208

@@ -389,14 +390,7 @@ int OSPIFBlockDevice::deinit()
389390
_wait_flag = NOT_STARTED;
390391
#endif
391392

392-
change_mode(OSPIF_OPI_MODE_SPI);
393-
394-
// Disable Device for Writing
395-
ospi_status_t status = _ospi_send_general_command(OSPIF_INST_WRDI, OSPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0);
396-
if (status != OSPI_STATUS_OK) {
397-
tr_error("Write Disable failed");
398-
result = OSPIF_BD_ERROR_DEVICE_ERROR;
399-
}
393+
result = _soft_reset();
400394

401395
_is_initialized = false;
402396

@@ -746,10 +740,6 @@ int OSPIFBlockDevice::change_mode(int mode)
746740
tr_error(" Writing Config Register2 Failed");
747741
return -1;
748742
}
749-
750-
// Configure BUS Mode to 1_1_1
751-
_ospi.configure_format(OSPI_CFG_BUS_SINGLE, OSPI_CFG_INST_SIZE_8, OSPI_CFG_BUS_SINGLE, OSPI_CFG_ADDR_SIZE_32,
752-
OSPI_CFG_BUS_SINGLE, 0, OSPI_CFG_BUS_SINGLE, 0);
753743
}
754744

755745
_ospi.configure_format(OSPI_CFG_BUS_SINGLE, OSPI_CFG_INST_SIZE_8, OSPI_CFG_BUS_SINGLE, OSPI_CFG_ADDR_SIZE_32,
@@ -793,15 +783,11 @@ int OSPIFBlockDevice::change_mode(int mode)
793783

794784
if (OSPI_STATUS_OK == _ospi_send_general_command(OSPIF_INST_WRCR2, OSPIF_CR2_OPI_EN_ADDR, &config_reg2,
795785
1, NULL, 0)) {
796-
tr_debug("OPI mode enable - Writing Config Register2 Success: value = 0x%x", config_reg2);
786+
tr_debug("OPI mode disable - Writing Config Register2 Success: value = 0x%x", config_reg2);
797787
} else {
798-
tr_error("OPI mode enable - Writing Config Register2 failed");
788+
tr_error("OPI mode disable - Writing Config Register2 failed");
799789
return -1;
800790
}
801-
802-
// Configure BUS Mode to 1_1_1
803-
_ospi.configure_format(OSPI_CFG_BUS_SINGLE, OSPI_CFG_INST_SIZE_8, OSPI_CFG_BUS_SINGLE, OSPI_CFG_ADDR_SIZE_32,
804-
OSPI_CFG_BUS_SINGLE, 0, OSPI_CFG_BUS_SINGLE, 0);
805791
}
806792

807793
_ospi.configure_format(OSPI_CFG_BUS_SINGLE, OSPI_CFG_INST_SIZE_8, OSPI_CFG_BUS_SINGLE, OSPI_CFG_ADDR_SIZE_32,
@@ -834,32 +820,8 @@ int OSPIFBlockDevice::change_mode(int mode)
834820
_ospi.configure_format(_inst_width, _inst_size, _address_width, _address_size, OSPI_CFG_BUS_SINGLE,
835821
0, _data_width, 0);
836822
} else if (mode == OSPIF_OPI_MODE_SPI) {
837-
// Write new Status Register Setup
838-
if (_set_write_enable() != 0) {
839-
tr_error("Write Enabe failed");
840-
return -1;
841-
}
842-
843-
config_reg2 = 0x00;
844-
845-
if (OSPI_STATUS_OK == _ospi_send_general_command(OSPIF_INST_WRCR2, OSPIF_CR2_OPI_EN_ADDR, &config_reg2,
846-
1, NULL, 0)) {
847-
tr_debug("OPI mode enable - Writing Config Register2 Success: value = 0x%x", config_reg2);
848-
} else {
849-
tr_error("OPI mode enable - Writing Config Register2 failed");
850-
return -1;
851-
}
852-
_read_instruction = OSPIF_INST_READ_4B;
853-
_dummy_cycles = 0;
854-
855-
_inst_width = OSPI_CFG_BUS_SINGLE;
856-
_inst_size = OSPI_CFG_INST_SIZE_8;
857-
_address_width = OSPI_CFG_BUS_SINGLE;
858-
_address_size = OSPI_CFG_ADDR_SIZE_32;
859-
_data_width = OSPI_CFG_BUS_SINGLE;
860-
861-
_ospi.configure_format(_inst_width, _inst_size, _address_width, _address_size, OSPI_CFG_BUS_SINGLE,
862-
0, _data_width, _dummy_cycles);
823+
// Perform a soft reset to switch to SPI mode as suggested by Copilot
824+
status = _soft_reset();
863825
}
864826
return status;
865827
}
@@ -1364,8 +1326,6 @@ int OSPIFBlockDevice::_sfdp_detect_and_enable_4byte_addressing(uint8_t *basic_pa
13641326

13651327
int OSPIFBlockDevice::_sfdp_detect_reset_protocol_and_reset(uint8_t *basic_param_table_ptr)
13661328
{
1367-
int status = OSPIF_BD_ERROR_OK;
1368-
13691329
#if RESET_SEQUENCE_FROM_SFDP
13701330
uint8_t examined_byte = basic_param_table_ptr[OSPIF_BASIC_PARAM_TABLE_SOFT_RESET_BYTE];
13711331

@@ -1374,38 +1334,68 @@ int OSPIFBlockDevice::_sfdp_detect_reset_protocol_and_reset(uint8_t *basic_param
13741334
#endif
13751335

13761336
#if !MBED_CONF_OSPIF_ENABLE_AND_RESET // i.e. direct reset, or determined from SFDP
1377-
// Issue instruction 0xF0 to reset the device
1378-
ospi_status_t ospi_status = _ospi_send_general_command(0xF0, OSPI_NO_ADDRESS_COMMAND, // Send reset instruction
1379-
NULL, 0, NULL, 0);
1380-
status = (ospi_status == OSPI_STATUS_OK) ? OSPIF_BD_ERROR_OK : OSPIF_BD_ERROR_PARSING_FAILED;
1337+
_soft_reset_mode = OSPIF_DIERCT_SOFT_RESET;
13811338
#endif
13821339

13831340
#if RESET_SEQUENCE_FROM_SFDP
13841341
} else if (examined_byte & SOFT_RESET_ENABLE_AND_RESET_INST_BITMASK) {
13851342
#endif
13861343

13871344
#if !MBED_CONF_OSPIF_DIRECT_RESET // i.e. enable and reset, or determined from SFDP
1388-
// Issue instruction 66h to enable resets on the device
1389-
// Then issue instruction 99h to reset the device
1390-
ospi_status_t ospi_status = _ospi_send_general_command(0x66, OSPI_NO_ADDRESS_COMMAND, // Send reset enable instruction
1391-
NULL, 0, NULL, 0);
1392-
if (ospi_status == OSPI_STATUS_OK) {
1393-
ospi_status = _ospi_send_general_command(0x99, OSPI_NO_ADDRESS_COMMAND, // Send reset instruction
1394-
NULL, 0, NULL, 0);
1395-
}
1396-
status = (ospi_status == OSPI_STATUS_OK) ? OSPIF_BD_ERROR_OK : OSPIF_BD_ERROR_PARSING_FAILED;
1345+
_soft_reset_mode = OSPIF_ENABLE_AND_SOFT_RESET;
13971346
#endif
13981347

13991348
#if RESET_SEQUENCE_FROM_SFDP
14001349
} else {
14011350
// Soft reset either is not supported or requires direct control over data lines
1402-
tr_error("Failed to determine soft reset sequence. If your device has a legacy SFDP table, please manually set enable-and-reset or direct-reset.");
1403-
1404-
status = OSPIF_BD_ERROR_PARSING_FAILED;
1351+
_soft_reset_mode = OSPIF_SOFT_RESET_UNSUPPORTED;
14051352
}
14061353
#endif
14071354

1355+
return _soft_reset();
1356+
}
1357+
1358+
int OSPIFBlockDevice::_soft_reset()
1359+
{
1360+
int status = OSPIF_BD_ERROR_OK;
1361+
ospi_status_t ospi_status = OSPI_STATUS_OK;
1362+
1363+
switch(_soft_reset_mode) {
1364+
case OSPIF_SOFT_RESET_UNSUPPORTED:
1365+
status = OSPIF_BD_ERROR_PARSING_FAILED;
1366+
break;
1367+
case OSPIF_DIERCT_SOFT_RESET:
1368+
// Issue instruction 0xF0 to reset the device
1369+
ospi_status = _ospi_send_general_command(0xF0, OSPI_NO_ADDRESS_COMMAND, // Send reset instruction
1370+
NULL, 0, NULL, 0);
1371+
status = (ospi_status == OSPI_STATUS_OK) ? OSPIF_BD_ERROR_OK : OSPIF_BD_ERROR_PARSING_FAILED;
1372+
break;
1373+
case OSPIF_ENABLE_AND_SOFT_RESET:
1374+
// Issue instruction 66h to enable resets on the device
1375+
// Then issue instruction 99h to reset the device
1376+
ospi_status = _ospi_send_general_command(0x66, OSPI_NO_ADDRESS_COMMAND, // Send reset enable instruction
1377+
NULL, 0, NULL, 0);
1378+
if (ospi_status == OSPI_STATUS_OK) {
1379+
ospi_status = _ospi_send_general_command(0x99, OSPI_NO_ADDRESS_COMMAND, // Send reset instruction
1380+
NULL, 0, NULL, 0);
1381+
}
1382+
status = (ospi_status == OSPI_STATUS_OK) ? OSPIF_BD_ERROR_OK : OSPIF_BD_ERROR_PARSING_FAILED;
1383+
break;
1384+
}
14081385
if (status == OSPIF_BD_ERROR_OK) {
1386+
// Set SPI format after soft reset
1387+
_read_instruction = OSPIF_INST_READ_4B;
1388+
_dummy_cycles = 0;
1389+
1390+
_inst_width = OSPI_CFG_BUS_SINGLE;
1391+
_inst_size = OSPI_CFG_INST_SIZE_8;
1392+
_address_width = OSPI_CFG_BUS_SINGLE;
1393+
_address_size = OSPI_CFG_ADDR_SIZE_32;
1394+
_data_width = OSPI_CFG_BUS_SINGLE;
1395+
1396+
_ospi.configure_format(_inst_width, _inst_size, _address_width, _address_size, OSPI_CFG_BUS_SINGLE,
1397+
0, _data_width, _dummy_cycles);
1398+
14091399
if (false == _is_mem_ready()) {
14101400
tr_error("Device not ready, reset failed");
14111401
status = OSPIF_BD_ERROR_READY_FAILED;

targets/TARGET_STM/TARGET_STM32H5/flash_api.c

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,12 @@ int32_t flash_erase_sector(flash_t *obj, uint32_t address)
9393
return -1;
9494
}
9595

96-
if (HAL_FLASH_Unlock() != HAL_OK) {
96+
if (HAL_ICACHE_Disable() != HAL_OK)
97+
{
9798
return -1;
9899
}
99100

100-
if (HAL_ICACHE_Disable() != HAL_OK)
101-
{
101+
if (HAL_FLASH_Unlock() != HAL_OK) {
102102
return -1;
103103
}
104104

@@ -107,6 +107,9 @@ int32_t flash_erase_sector(flash_t *obj, uint32_t address)
107107
/* Clear error programming flags */
108108
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
109109

110+
/* Increase Flash latency while programming */
111+
__HAL_FLASH_SET_LATENCY(6);
112+
110113
/* MBED HAL erases 1 page / sector at a time */
111114
/* Fill EraseInit structure*/
112115
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
@@ -118,14 +121,17 @@ int32_t flash_erase_sector(flash_t *obj, uint32_t address)
118121
status = -1;
119122
}
120123

124+
/* Restore normal Flash latency */
125+
__HAL_FLASH_SET_LATENCY(5);
126+
121127
core_util_critical_section_exit();
122128

123-
if (HAL_ICACHE_Enable() != HAL_OK)
124-
{
129+
if (HAL_FLASH_Lock() != HAL_OK) {
125130
return -1;
126131
}
127132

128-
if (HAL_FLASH_Lock() != HAL_OK) {
133+
if (HAL_ICACHE_Enable() != HAL_OK)
134+
{
129135
return -1;
130136
}
131137

@@ -158,18 +164,21 @@ int32_t flash_program_page(flash_t *obj, uint32_t address,
158164
return -1;
159165
}
160166

161-
if (HAL_FLASH_Unlock() != HAL_OK) {
167+
if (HAL_ICACHE_Disable() != HAL_OK)
168+
{
162169
return -1;
163170
}
164171

165-
if (HAL_ICACHE_Disable() != HAL_OK)
166-
{
172+
if (HAL_FLASH_Unlock() != HAL_OK) {
167173
return -1;
168174
}
169175

170176
/* Clear error programming flags */
171177
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
172178

179+
/* Increase Flash latency while programming */
180+
__HAL_FLASH_SET_LATENCY(6);
181+
173182
/* Program the user Flash area word by word */
174183
StartAddress = address;
175184

@@ -184,12 +193,15 @@ int32_t flash_program_page(flash_t *obj, uint32_t address,
184193
}
185194
}
186195

187-
if (HAL_ICACHE_Enable() != HAL_OK)
188-
{
196+
/* Restore normal Flash latency */
197+
__HAL_FLASH_SET_LATENCY(5);
198+
199+
if (HAL_FLASH_Lock() != HAL_OK) {
189200
return -1;
190201
}
191202

192-
if (HAL_FLASH_Lock() != HAL_OK) {
203+
if (HAL_ICACHE_Enable() != HAL_OK)
204+
{
193205
return -1;
194206
}
195207

0 commit comments

Comments
 (0)