I'm implementing communication between an IMX8MN6 CM7 core and an FPGA via FlexSPI in octal mode. I'm seeing the problem that a FlexSPI write transaction inserts random frames into the write transaction that are not in any way specified by the LUT entries.
FlexSPI is configured with "SCLK output free-running", but I was also able to see the error without this setting.
Originally I started with this sequence of FlexSPI LUT entries for a write transaction:
{// Write command is first byte with LSB = 1
FLEXSPI_LUT_SEQ(
// Command "write" is one byte with LSB = 1.
kFLEXSPI_Command_SDR, kFLEXSPI_8PAD, 0x01,
// The row address is written in octal mode, 2 bytes = 16 bits.
kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_8PAD, 16),
FLEXSPI_LUT_SEQ(
// Write the data in octal mode, the operand is irrelevant.
kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_8PAD, 0x04,
// Stop.
kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0)},
This should result in an SPI transaction that takes seven clock cycles, which it does about half of the times. This is a screen shot from the oscilloscope for a 4-byte write:
FlexSPI Write at 10 MHz with continuous SPI clock
The following signals are captured:
| Channel | Description |
| 0 | SPI clock at 10 MHz |
| 1 | SPI chip select |
| 2 | DQS, inactive in write transaction |
| 3-7 | Five least significant bits of the eight SPI data lines |
This is the effect of triggering a FlexSPI write at address 0x08 with a 4-byte data value 0xFFFFFFFF. The signals are as expected:
| SPI clock frame(s) | Value on MOSI lines | Comment |
| 0 | 0x01 | Created by kFLEXSPI_Command_SDR LUT entry with operand 0x01 |
| 1-2 | 0x0008 | Two address bytes 0x0008 created by kFLEXSPI_Command_RADDR_SDR LUT entry with operand 16 |
| 3-6 | 0xFFFFFFFF | Five least significant bits of writing 4-byte value 0xFFFFFFFF with kFLEXSPI_Command_WRITE_SDR LUT entry |
But only roughly half the write transactions look like this. More often the transaction looks like this:

Here we have the following:
| SPI clock frame(s) | Value on MOSI lines | Comment |
| 0 | 0x01 | Correct command 0x01 |
| 1-2 | 0x0008 | Correct address 0x0008 |
| 3 | 0x0C | Incorrect frame that must not be present |
| 4-7 | 0xFFFFFFFF | Correct 4-byte data value 0xFFFFFFFF |
Note that it is reproducible that always the value 0x0C is inserted. I did not see any other value in my tests.
We checked the errata for the IMX8MN6 chip in the NXP document IMX8MN_0N14Y "Mask Set Errata for Mask 0N14Y", and there we found only the following erratum:
ERR050537: FlexSPI: Read timing sequence mismatches with several existing SPI NOR devices in dual, quad, and octal modes
...
In multiple IO modes such as dual, quad, and octal modes, the FlexSPI controller inserts one additional clock cycle following the address (or command modifier) phase in order to prevent contention on bidirectional IO pins.
This does not seem to apply to our situation as we have the problem with a write transaction, but nevertheless we checked whether an additional dummy cycle between the address and the data frames improves the situation. The new LUT for the write transaction looks like this:
{// Write command is first byte with LSB = 1
FLEXSPI_LUT_SEQ(
// Command "write" is one byte with LSB = 1.
kFLEXSPI_Command_SDR, kFLEXSPI_8PAD, 0x01,
// The row address is written in octal mode, 2 bytes = 16 bits.
kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_8PAD, 16),
FLEXSPI_LUT_SEQ(
// Dummy cycle as workaround attempt for problem with FlexSPI engine.
kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_8PAD, 1,
// Write the data in octal mode, the operand is irrelevant.
kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_8PAD, 0x04),
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0)},
This improves the reliability but it does not fix the problem. When running continuous tests the same errors happen on average two or three times after a few ten-thousands of write transactions.
This was with an SPI clock of 10 MHz. We want to reach an SPI clock frequency of 100 MHz. But already with a frequency to 20 MHz the behavior is catastrophic. With the higher clock frequency almost all write transactions are broken, and there are even more extra frames inserted. This is a screen shot from the oscilloscope with an SPI clock frequency of 20 MHz:

With the same LUT table as before the write transaction that should take exactly eight cycles now takes 14 cycles. Now we have this (this screen shot was taken with a different address and data value in the write transaction):
| SPI clock frame(s) | Value on MOSI lines | Comment |
| 0 | 0x01 | Correct command 0x01 |
| 1-2 | | two arbitrary address bytes |
| 3 | | dummy cycle |
| 4-9 | 0x0C | six extra 0x0C bytes |
| 10-13 | | four arbitrary data bytes |
This is the FlexSPI deviceconfig structure that we are using:
flexspi_device_config_t deviceconfig = {
.flexspiRootClk = 10000000, // 10 MHz (D)
.flashSize = 1, // 1 kB
.CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle,
.CSInterval = 2,
.CSHoldTime = 0,
.CSSetupTime = 0,
.dataValidTime = 0,
.columnspace = 0,
.enableWordAddress = 0,
.AWRSeqIndex = NOR_CMD_LUT_SEQ_IDX_WRITE,
.AWRSeqNumber = 1,
.ARDSeqIndex = NOR_CMD_LUT_SEQ_IDX_READ,
.ARDSeqNumber = 1,
.AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle,
.AHBWriteWaitInterval = 0,
};
And this is the FlexSPI initialization code:
flexspi_config_t config;
FLEXSPI_GetDefaultConfig(&config);
config.enableSckFreeRunning = true;
config.ahbConfig.enableAHBPrefetch = false;
config.ahbConfig.enableAHBBufferable = false;
config.ahbConfig.enableReadAddressOpt = false;
config.ahbConfig.enableAHBCachable = false;
config.rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackInternally;
config.enableCombination = true;
FLEXSPI_Init(base, &config);
What could be causing this unreliable behavior of the FlexSPI peripheral? According to the data sheet FlexSPI should work with SPI clocks up to 66 MHz in SDR mode with internal dummy read strobe and with SPI clocks up to 166 MHz with Flash-provided read strobe.