Background flash operation blocking program execution
ID: COBALTSDK-1169
Status: Open
First reported: 10.2.4.44
Fixed in: TBD
Description
The OQSPI Background Flash Operations block every time a new Sector Erase operation is registered, until the respective operation is completed. This prevents the program execution (XiP) until the completion of the operation, thus causing significant delays and practically cancelling the scope of the Background Flash Operations.
Workaround
in sdk/bsp/system/sys_man/sys_background_flash_ops.c:
@@ -215,7 +215,7 @@ __RETAINED_CODE bool sys_background_flash_ops_handle(void)
break;
case BACKGROUND_OP_STATUS_RESUMED:
if (backops_active->operation == BACKGROUND_OP_ERASE) {
- oqspi_automode_erase_flash_sector(backops_active->flash_op.addr);
+ oqspi_automode_int_erase_flash_sector_manual(backops_active->flash_op.addr);
} else { // program
op_completed = handle_pending_write_operation();
}
in sdk/bsp/memory/src/oqspi_automode.c:
@@ -426,18 +426,7 @@ __RETAINED_CODE uint32_t oqspi_automode_int_flash_write_page(uint32_t addr, cons
return i;
}
-#if !dgconfigOQSPI_ERASE_IN_AUTOMODE
-/*
- * Erase a sector of the Flash in manual mode.
- *
- * Before calling this function you need to disable the interrupts and switch to Manual Access Mode
- * calling the oqspi_enter_manual_access_mode().
- *
- * This function does not block until the Flash has
- * processed the command! When calling this function the OQSPI controller remains to manual mode.
- * The function must be called with interrupts disabled.
- */
-__RETAINED_CODE static void oqspi_flash_erase_sector_manual(uint32_t addr)
+__RETAINED_CODE void oqspi_automode_int_erase_flash_sector_manual(uint32_t addr)
{
__DBG_OQSPI_VOLATILE__ HW_OQSPI_BUS_MODE write_enable_bus_mode = OQSPI_GET_DEVICE_PARAM(write_enable_instr_cfg.opcode_bus_mode);
__DBG_OQSPI_VOLATILE__ HW_OQSPI_BUS_MODE opcode_bus_mode = OQSPI_GET_DEVICE_PARAM(erase_instr_cfg.opcode_bus_mode);
@@ -446,6 +435,8 @@ __RETAINED_CODE static void oqspi_flash_erase_sector_manual(uint32_t addr)
__DBG_OQSPI_VOLATILE__ HW_OQSPI_ADDR_SIZE addr_size = OQSPI_GET_DEVICE_PARAM(address_size);
__DBG_OQSPI_VOLATILE__ uint8_t opcode = OQSPI_GET_DEVICE_PARAM(erase_instr_cfg.opcode);
+ DBG_SET_HIGH(FLASH_DEBUG, FLASHDBG_SECTOR_ERASE);
+
oqspi_enter_manual_access_mode();
oqspi_set_manual_access_bus_mode(write_enable_bus_mode, false);
oqspi_flash_write_enable(write_enable_bus_mode);
@@ -471,12 +462,9 @@ __RETAINED_CODE static void oqspi_flash_erase_sector_manual(uint32_t addr)
}
hw_oqspi_cs_disable();
- /*
- * Flash stays in manual mode.
- */
+ DBG_SET_LOW(FLASH_DEBUG, FLASHDBG_SECTOR_ERASE);
}
-#endif /* !dgconfigOQSPI_ERASE_IN_AUTOMODE */
#if dg_configUSE_SYS_BACKGROUND_FLASH_OPS
__RETAINED_CODE void oqspi_automode_int_resume(void)
@@ -642,29 +630,29 @@ __RETAINED_CODE uint32_t oqspi_automode_write_flash_page(uint32_t addr, const ui
__RETAINED_CODE void oqspi_automode_erase_flash_sector(uint32_t addr)
{
+#if dgconfigOQSPI_ERASE_IN_AUTOMODE
DBG_SET_HIGH(FLASH_DEBUG, FLASHDBG_SECTOR_ERASE);
while (!oqspi_flash_is_writable());
-#if dgconfigOQSPI_ERASE_IN_AUTOMODE
hw_oqspi_erase_block(addr);
while (hw_oqspi_get_erase_status() != HW_OQSPI_ERASE_STATUS_NO);
+
+ DBG_SET_LOW(FLASH_DEBUG, FLASHDBG_SECTOR_ERASE);
#else
__DBG_OQSPI_VOLATILE__ HW_OQSPI_BUS_MODE busy_bus_mode = OQSPI_GET_DEVICE_PARAM(read_status_instr_cfg.opcode_bus_mode);
// Disable the interrupts as long as the OQSPIC remains in manual access mode
GLOBAL_INT_DISABLE();
- oqspi_enter_manual_access_mode();
- oqspi_flash_erase_sector_manual(addr);
+ oqspi_automode_int_erase_flash_sector_manual(addr);
while (oqspi_flash_is_busy(busy_bus_mode));
oqspi_automode_int_enter_auto_access_mode();
// Re-enable the interrupts since the OQSPIC switched back to auto access mode
GLOBAL_INT_RESTORE();
#endif
- DBG_SET_LOW(FLASH_DEBUG, FLASHDBG_SECTOR_ERASE);
}
void oqspi_automode_erase_chip(void)
in sdk/bsp/memory/src/oqspi_automode_internal.h:
@@ -47,6 +47,31 @@ __RETAINED_CODE void oqspi_automode_int_enter_auto_access_mode(void);
*/
__RETAINED_CODE uint32_t oqspi_automode_int_flash_write_page(uint32_t addr, const uint8_t *buf, uint32_t size);
+
+/*
+ * Erase a sector of the Flash in manual mode.
+ *
+ *
+ *
+ * This function does not block until the Flash has
+ * processed the command! When calling this function the OQSPI controller remains to manual mode.
+ * The function must be called with interrupts disabled.
+ */
+
+/**
+ * \brief Erase Flash Sector in manual access mode
+ *
+ * \param [in] addr The address of the sector to be erased.
+ *
+ * \warning Before calling this function is mandatory to disable the global interrupts.
+ *
+ * \warning This function switches the OQSPI controller to manual access mode. It's a responsibility
+ * of the caller to switch the controller back to auto access mode in order to re-enable
+ * eXecute in Place.
+ *
+ */
+__RETAINED_CODE void oqspi_automode_int_erase_flash_sector_manual(uint32_t addr);
+
#if dg_configUSE_SYS_BACKGROUND_FLASH_OPS
/**