cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 QUADSPI Status Polling in 444 Mode

MWalk.3
Associate II

I'm noticing some odd behaviour in the QUADSPI peripheral on the STM32H743. When I use the automatic status polling feature in quad mode it appears that the 1st query works as configured, but subsequent queries are strangely incomplete.

What I mean by this is, no matter how many bytes I ask transferred, on the second query I only see 3 clock cycles, and the chip select never deasserts. Subsequent queries, at the polling interval, then use 4 clock cycles each. I also noticed that even if I have APMS set, when I get the match interrupt, the queries continue until I set ABORT in CR.

If I revert back to 111 mode, then every query looks identical, chip select cycles, I see the correct number of clock cycles, and no manual abort is required.

It turns out that even though this behavior looks very strange, the flash QSPI chip I'm working with doesn't care, but it is worrysome that I'm missing something. Especially since it appears I start getting noise on the line as the master and perhiperal start getting confused on who should be driving things.

Any thoughts?

Some setup details:

400MHz sysclk, 200Mhz HPRE

Divide by 32 prescaler for the QUADSPI chip select, 32 cycle CS high time, in Mode 0.

And every important line from the setup routine I wrote:

uint32_t cr = ((cs_cfg.prescaler << QUADSPI_CR_PRESCALER_Pos) & QUADSPI_CR_PRESCALER_Msk);
cr |= QUADSPI_CR_APMS;
cr |= xfer_list_->cs << QUADSPI_CR_FSEL_Pos;
cr |= QUADSPI_CR_EN;
cr |= QUADSPI_CR_SMIE;
QUADSPI->CR = cr;
 
uint32_t dcr = 0x1FF << QUADSPI_DCR_FSIZE_Pos; // Disable length checking
dcr |= ((cs_cfg.cs_high_time << QUADSPI_DCR_CSHT_Pos) & QUADSPI_DCR_CSHT_Msk);
dcr |= cs_cfg.mode == Mode::Mode3 ? QUADSPI_DCR_CKMODE : 0;
QUADSPI->DCR = dcr;
 
QUADSPI->FCR = QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF | QUADSPI_FCR_CSMF | QUADSPI_FCR_CTOF;
 
QUADSPI->DLR = xfer_list_->data_len - 1;
 
QUADSPI->PSMKR = xfer_list_->status.mask;
QUADSPI->PSMAR = xfer_list_->status.match;
QUADSPI->PIR = 1024;
 
uint32_t ccr = 0;
ccr |= 0x2 << QUADSPI_CCR_FMODE_Pos;
ccr |= (xfer_list_->cmd_xfer_width + 1) << QUADSPI_CCR_IMODE_Pos;
ccr |= xfer_list_->cmd << QUADSPI_CCR_INSTRUCTION_Pos;
ccr |= (xfer_list_->data_xfer_width + 1) << QUADSPI_CCR_DMODE_Pos;
ccr |= xfer_list_->dummy_clocks_len << QUADSPI_CCR_DCYC_Pos;
QUADSPI->CCR = ccr;

Where my xfer_widths are setup so that 0 is a width of 1, and 2 is a width of 4.

And here's a scope capture, the Saleae Logic is running at 500MHz, and the bus is 6.25MHz so I should be seeing everything. Note how the first query transfers 5 bytes and then releases CS, the next transaction transfers the command and half a bytes of data, and then subsequenct transfers transfer the command and a byte of data. (I also adjusted the PIR to be 32 counts so that we could see multiple queries in one plot.)0693W000003QUQOQA4.png

1 REPLY 1
TGütl.1
Associate

Hello,

I have the same problem here. Also on the STM32H743 and in 444 mode.

For me, the 3 clocks appear when the first response to a polling request does not match. After that the 3 clocks come, and then the busy flag hangs, probably because the external chip gets messed up.

0693W00000FD7JuQAL.png 

Is there a solution or explanation for this behavior?