2022-11-25 07:38 AM
Win10, CubeIDE, Implementing QUADSPI in C purely on registers.
Have scope and logic analyzer.
STM32F746 Disco
Running MCU on default HSI 16MHz internal, QUADSPI runs at 1MHz for easy debugging and capture with cheapo logic analyzer.
Indirect write/indirect read work correctly and return expected number of bytes. Even with maxed out system clock (thoroughly tested - debugged it so much I can read waveform without decoder).
I've never used it in memory mapped mode before. So here is my code:
uint32_t readout_firstword;
QSPI_readMemoryBytesQuad(0x00000000, 4, (uint8_t*) (&readout_firstword));
uint32_t readout_secondword;
QSPI_readMemoryBytesQuad(0x00000004, 4, (uint8_t*) (&readout_secondword));
/* Activate memory-mapped mode */
QSPI_enabledMemoryMappedMode();
uint32_t readout_firstwordMemoryMapped = *(uint32_t*) (0x90000000);
The readout_firstwordMemoryMapped returns 0x000000fa, which is only 1 correct byte of the entire word (0xFACE8D00).
Curiously enough, the waveform contains the entire first word, the entire second word that I never asked, then it also contains a few dozen more clock cycles and it never releases chip select. It stays low forever.
This is the waveform that addressing memory in memory-mapped mode does:
So there is an instruction, there is address (0x000000), dummy bytes (6 now, but since it's 1MHz, it should - and clearly does - work, because otherwise I wouldn't get my first byte). Then comes the data - 8 bytes of it. And then clock runs for some time and chip select never releases. And the variable has only 1 byte, the other 7 bytes were discarded. So physically I receive 8 bytes plus never ending chip select, while variable has only 1 byte. Whereas the correct behavior would be to read only 4 bytes and release chip select there. I set data length register to 3 (4 bytes). Also, I tried timeout value 0xFFFF and 0x0000, it makes no difference at all, I believe it's not relevant to specifically this situation.
These are QUADSPI registers AFTER this memory mapped read:
This is how I enable memory mapped mode:
void QSPI_enabledMemoryMappedMode(void) {
QUADSPI->CR &= ~(0x01 << 0);
QUADSPI->DLR = 4U - 1U;
QUADSPI->CR = (QUADSPI->CR & ~(0x1F << 8)) | (0x03 << 8); //Set FIFO threshold to 4
QUADSPI->CCR = (QSPI_FMODE_MEMORY_MAPPED << 26) | (QSPI_QUAD << 24)
| (QSPI_QUAD << 8) | (QSPI_QUAD << 10) | (QSPI_ADSIZE_24 << 12)
| (MT25QL128ABA1EW9_COMMAND_QUAD_IO_FAST_READ << 0);
QUADSPI->LPTR = 0x0000;
QUADSPI->CR |= (0x01 << 0);
}
I would be grateful if someone pointed me in the right direction. I don't understand what I misconfigured, why my QUADSPI has 20 bytes in fifo after requesting 1 WORD, and why even tho I have my entire 32-bit word waveform, I get only the first byte of data into the actual variable.
I did look at HAL and other standard implementations. I didn't see any difference in terms of logic of actions. I didn't notice missing any step.