STM32F743 QUADSPI Remains busy forever after read (CMSIS, no HAL!)
I am trying to access the APS6404 PSRAM with QuadSPI on STM32H743. For some reason, indirect-writes are fine; but as soon as I try an inderect-read (one-line, typical SPI essentially) the communication stalls. By stalling I mean the SR register is always "Busy" (== 32), but there is no data in FIFO, reading DR stalls the processor (since there's no data in the FIFO, the memory read operation stalls).
I don't think it's a problem with the IC, since something must be received anyway - this is SPI, after all. There's nothing really complex in my code, just setting the CCR register appropriately and AR register then. I've also tried adding dummy bits, but that does not help at all. What am I doing wrong?
My initialization code is as follows:
RCC->AHB3ENR |= RCC_AHB3ENR_QSPIEN;
QUADSPI->CR = (1 << QUADSPI_CR_PRESCALER_Pos) | (0 << QUADSPI_CR_FSEL_Pos) | (0 << QUADSPI_CR_DFM_Pos) | (0 << QUADSPI_CR_SSHIFT_Pos);
QUADSPI->DCR = (22 << QUADSPI_DCR_FSIZE_Pos) | (7 << QUADSPI_DCR_CSHT_Pos) | (0 << QUADSPI_DCR_CKMODE_Pos); // 8MB, max hold time, CLK Low when NCS=1
QUADSPI->CR |= QUADSPI_CR_EN;
QUADSPI->DLR = 0;
Write code:
void qspi_write1(uint32_t addr, uint8_t b) {
QUADSPI->CR |= QUADSPI_CR_ABORT; QUADSPI->FCR |= 0b11011;
QUADSPI->DLR = 0;
QUADSPI->DR = b;
QUADSPI->CCR = (0 << QUADSPI_CCR_DDRM_Pos) | (0 << QUADSPI_CCR_SIOO_Pos) | (0b00 << QUADSPI_CCR_FMODE_Pos)
| (0b01 << QUADSPI_CCR_DMODE_Pos) | (0b00 << QUADSPI_CCR_DCYC_Pos) | (0b00 << QUADSPI_CCR_ABMODE_Pos)
| (0b10 << QUADSPI_CCR_ADSIZE_Pos) | (0b01 << QUADSPI_CCR_ADMODE_Pos) | (0b01 << QUADSPI_CCR_IMODE_Pos)
| (0x02 << QUADSPI_CCR_INSTRUCTION_Pos);
QUADSPI->AR = addr;
WAITNBIT(QUADSPI->SR, QUADSPI_SR_BUSY);
}
Read code:
QUADSPI->CR |= QUADSPI_CR_ABORT; QUADSPI->FCR |= 0b11011;
QUADSPI->DLR = 0;
QUADSPI->CCR = (0 << QUADSPI_CCR_DDRM_Pos) | (0 << QUADSPI_CCR_SIOO_Pos) | (0b01 << QUADSPI_CCR_FMODE_Pos)
| (0b01 << QUADSPI_CCR_DMODE_Pos) | (0x06 << QUADSPI_CCR_DCYC_Pos) | (0b00 << QUADSPI_CCR_ABMODE_Pos)
| (0b10 << QUADSPI_CCR_ADSIZE_Pos) | (0b01 << QUADSPI_CCR_ADMODE_Pos) | (0b01 << QUADSPI_CCR_IMODE_Pos)
| (0x03 << QUADSPI_CCR_INSTRUCTION_Pos);
__DSB();
QUADSPI->AR = addr;
uint32_t sr;
uint8_t data = 0;
do {
sr = QUADSPI->SR;
if(sr & QUADSPI_SR_FTF) {
data = QUADSPI->DR;
}
} while (sr & QUADSPI_SR_BUSY);
return data;
}
