cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F743 QUADSPI Remains busy forever after read (CMSIS, no HAL!)

krezo107
Associate

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:

Spoiler
MODIFY_REG(RCC->D1CCIPR, RCC_D1CCIPR_QSPISEL, (0b01) << RCC_D1CCIPR_QSPISEL_Pos); // PLL1Q as clock source
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:

 

 

Spoiler

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:

Spoiler
uint8_t qspi_read1(uint32_t addr) {
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;
}

 

3 REPLIES 3
Pavel A.
Evangelist II

In indirect mode the processor should not stall because of accessing any QSPI register. Do you use MPU as recommended, to avoid the "speculative execution" and whatever cache related complications?

something must be received anyway - this is SPI, after all.

Yes, but you also wait for certain bits in the SR. The status bits reflect the device POV. It is possible that MCU does a number of clock pulses, but the device does not see all these pulses and waits for more.

From the reference manual, DR register info:

In indirect read mode, reading this register gives (via the FIFO) the data which was received
from the flash memory. If the FIFO does not have as many bytes as requested by the read
operation and if BUSY=1, the read operation is stalled until enough data is present or until
the transfer is complete, whichever happens first.

So, if there is no info in the FIFO (which IS the case), processor can stall.

Next, as you can see from my code, yes, the processor stalls if I try to read at any moment the DR register, even if I add a delay, but, as you can see from my code, I am waiting while the BUSY flag is set and checking if there is something in the FIFO. There is not, SR == 34 (BUSY + TC, but FIFO is empty). Fifo flag threshold is at minimum.

What do you mean by "the device does not see all these pulses"? This code should work even if no IC is present, since uC is always the master in QSPI connection.

KDJEM.1
ST Employee

Hello @krezo107 and welcome to the Community 🙂,

Are you using the QUADSPI interface in indirect read mode when only data phase is activated?

If yes, note that it is mentioned in the errata sheet ES0392 that the QUADSPI cannot be used in indirect read mode when only data phase. In this case, the QUADSPI peripheral hangs and the BUSY flag of the QUADSPI_SR register remains high. An abort must be performed to reset the BUSY flag and exit the hanging state. 

The workaround is insert a dummy phase with at least two dummy cycles.

Thank you.

Kaouthar

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.