diff --git a/ion/src/device/shared/drivers/external_flash.cpp b/ion/src/device/shared/drivers/external_flash.cpp index 6598e22dc..031dd6e02 100644 --- a/ion/src/device/shared/drivers/external_flash.cpp +++ b/ion/src/device/shared/drivers/external_flash.cpp @@ -178,6 +178,22 @@ static void unset_memory_mapped_mode() { } static void send_command_full(QUADSPI::CCR::FunctionalMode functionalMode, QUADSPI::CCR::OperatingMode operatingMode, Command c, uint8_t * address, uint32_t altBytes, size_t numberOfAltBytes, uint8_t dummyCycles, uint8_t * data, size_t dataLength) { + /* According to ST's Errata Sheet ES0360, "Wrong data can be read in + * memory-mapped after an indirect mode operation". This is the workaround. */ + if (functionalMode == QUADSPI::CCR::FunctionalMode::MemoryMapped) { + QUADSPI::CCR::FunctionalMode previousMode = QUADSPI.CCR()->getFMODE(); + if (previousMode == QUADSPI::CCR::FunctionalMode::IndirectWrite || previousMode == QUADSPI::CCR::FunctionalMode::IndirectRead) { + // Reset the address register + QUADSPI.AR()->set(0); // No write to DR should be done after this + if (previousMode == QUADSPI::CCR::FunctionalMode::IndirectRead) { + // Make an abort request to stop the reading and clear the busy bit + QUADSPI.CR()->setABORT(true); + while (QUADSPI.CR()->getABORT()) { + } + } + } + } + class QUADSPI::CCR ccr(0); ccr.setFMODE(functionalMode); if (data != nullptr || functionalMode == QUADSPI::CCR::FunctionalMode::MemoryMapped) { diff --git a/ion/src/device/shared/regs/quadspi.h b/ion/src/device/shared/regs/quadspi.h index c2b924eea..99806df93 100644 --- a/ion/src/device/shared/regs/quadspi.h +++ b/ion/src/device/shared/regs/quadspi.h @@ -16,6 +16,7 @@ public: public: using Register32::Register32; REGS_BOOL_FIELD(EN, 0); + REGS_BOOL_FIELD(ABORT, 1); REGS_BOOL_FIELD(TCEN, 3); // Lower-power timeout counter enable in memory-mapped mode REGS_BOOL_FIELD(SSHIFT, 4); REGS_FIELD(PRESCALER, uint8_t, 31, 24);