cancel
Showing results for 
Search instead for 
Did you mean: 

QSPI becomes endless busy after programming 1 page of external memory

mkovalevski
Associate

Hi everyone!

My goal is to program big-sized data into external memory (MICRON). But I have very annoying problem. I can program only 1 page of ext. memory (256 bytes), I use DMA (mem to periph) to read data from buffer and send it to QSPI data register. After sending 256 bytes QSPI busy flag never resets, transfer comlete flag = 1, FIFO threshold flag = 1 and DMA sets FEIF (FIFO error flag).

Here is an example of programming script:

#define __ADDR_MASK ((__QSPI_FLASH_SIZE<<1)-1) // 26 bits adr size
void QSPI_programPage(uint32_t adr, uint32_t nb, uint16_t ptr){
	DMA2_Stream7->M0AR = data_buffer + ptr;
	QSPI_WriteEnable();
	QUADSPI->CR |= QUADSPI_CR_DMAEN; // en DMA
	QUADSPI->DLR = nb; // num of bytes to be transfered (256 bytes)
 
	MODIFY_REG(QUADSPI->CCR, 
QUADSPI_CCR_INSTRUCTION | QUADSPI_CCR_DMODE | QUADSPI_CCR_ADMODE | QUADSPI_CCR_FMODE,
MT25Q_4BYTE_PROGRAM_PAGE<<QUADSPI_CCR_INSTRUCTION_Pos | QUADSPI_CCR_IMODE_0 | QUADSPI_CCR_DMODE_0 | QUADSPI_CCR_ADMODE_0 | QUADSPI_CCR_ADSIZE);
	QUADSPI->AR = adr & __ADDR_MASK;
	/* Write to QSPI data register */
	DMA2_Stream7->CR &=~ (DMA_SxCR_EN);
	DMA2_Stream7->NDTR = nb;
	DMA2_Stream7->CR |= (DMA_SxCR_EN);
	/* data sends */
	while (QUADSPI->SR & QUADSPI_SR_BUSY);
	/* Wait for the 'write in progress' bit to clear */
	qspi_reg_wait(0x01, 0x00);
//	DMA2_Stream7->CR &=~ (DMA_SxCR_EN);
}

Then address increments by 256 bytes and it is repeats.

I woud be very grateful, if you have some thoughts about it.

STM32F746

2 REPLIES 2

Lot to unpack here.

What's the actual instruction? Can't see the defines here.

Are you sure CCR gets set properly to the value you expect, decode what's in there. Don't seem to be masking IMODE properly

You should probably disable the DMA on entry, prior to setting M0AR

What's the address? Is it in suitable memory? Is it aligned? Are the transfer widths correct?

Why's it Error?

Is the data buffer really only 64KB, why not pass in the actual buffer address?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Thank you for the answer.

Actual instruction is MT25Q_4BYTE_PROGRAM_PAGE = 0x12, and CCR gets set as I expect, I configured extended SPI mode: IMODE = 0, DMODE = 0, ADMODE = 0 (all data goes by 1 line). IMODE always set as 0.

I tried to disable DMA before setting M0AR, but it didn't help. Also, not all data programmed into ext flash, when I disabled DMA.

Address is 0 and every time calling this function adr is aligned. Data width in periph and memory is 1 byte.

"Is the data buffer really only 64KB, why not pass in the actual buffer address?" Memory can be programmed only by pages (256 bytes), and I read data from USB MS by 4096 bytes, that's why I need to increment dma pointer to another data. If I pass just buffer address and set NDTR as 4096, only first 256 bytes of memory will be programmed.