STM32F4 DMA FIFO + SPI_TX = FIFO error, but work
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-04-11 4:03 AM
Good afternoon! I am trying to establish the transmission of data via SPI to the display with DMA. The transmission is working, the display is completely painted over, but the FIFO error flag is set in the DMA registers.
MCU: STM32F401CEU6
alignas(32) uint16_t buff[80 * 160];
// SPI init
SPI2->CR1 |= (0b000 << SPI_CR1_BR_Pos) |
SPI_CR1_MSTR |
SPI_CR1_SSI | SPI_CR1_SSM;
SPI2->CR2 |= SPI_CR2_TXDMAEN;
SPI2->CR1 |= SPI_CR1_SPE;
// DMA init
DMA1_Stream4->CR |= (0b01 << DMA_SxCR_DIR_Pos) |
(0 << DMA_SxCR_CHSEL_Pos) |
(0b11 << DMA_SxCR_MBURST_Pos) |
DMA_SxCR_MINC;
DMA1_Stream4->PAR = (uint32_t)&SPI2->DR;
DMA1_Stream4->M0AR = (uint32_t)getBuffer();
DMA1_Stream4->FCR &= ~DMA_SxFCR_FTH;
DMA1_Stream4->FCR |= DMA_SxFCR_DMDIS;
__DMB();
DMA1_Stream4->FCR |= (0b11 << DMA_SxFCR_FTH_Pos);
void ST7735s::stopScreenUpdate()
{
DMA1_Stream4->CR &= ~DMA_SxCR_EN;
while (DMA2_Stream4->CR & DMA_SxCR_EN)
;
CS_Up();
}
void ST7735s::startScreenUpdate()
{
stopScreenUpdate();
sendCommand(ST77XX_RAMWR);
CS_Down();
DC_Up();
DMA1->HIFCR = DMA_HIFCR_CFEIF4 | DMA_HIFCR_CHTIF4 | DMA_HIFCR_CTCIF4 | DMA_HIFCR_CTEIF4 | DMA_HIFCR_CDMEIF4;
DMA1_Stream4->NDTR = WIDTH * HEIGHT * 2;
DMA1_Stream4->CR |= DMA_SxCR_EN;
}
After transmission, the FIFO buffer operation error flag in DMA is set. The flag has to be reset manually + it's not normal somehow.
- 80 pixels * 160 pixels * 2 bytes = 25,600 bytes. In total, if I understood the logic correctly, with a packet size of 16 chunks, with a chunk size = MSIZE = 1 byte, everything should work, because the configuration is allowed + 25,600 bytes exactly divided into transactions of 16 bytes.
- I tried to change NDTR - divided by 16, but it didn't help, because it is necessary to specify exactly the number of bytes transmitted. With division by 16, only 1/16 of the display is filled.
- There is no overwriting (ovverun) either - all pixels take their places
- There are no SPI errors (Except overrun, since I only use sending)
The alignment was done with a margin. Tried before 4 - no result
Solved! Go to Solution.
- Labels:
-
DMA
-
SPI
-
STM32F4 Series
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-04-11 10:31 AM
It's not about SPI_CR1.SPE, but about SPI_CR2.TXDMAEN, i.e. gate of signal (which here is equal to SPI_SR.TXE), which goes to DMA. It's set before DMA has chance to fill up its FIFO, that's why it throws the FIFO error.
I recommended to use 32-bit memory-side transfer not because of any error, but because it's more efficient.
JW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-04-11 5:28 AM
See AN4031, chapter 4.3 Software sequence to enable DMA.
Also, it's better to use word-wide transfers on the memory side, (MSIZE=0b11) rather than bursts of byte transfers. The FIFO is there to unpack.
JW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-04-11 8:11 AM
void ST7735s::startScreenUpdate()
{
stopScreenUpdate();
sendCommand(ST77XX_RAMWR);
CS_Down();
DC_Up();
SPI2->CR1 &= ~SPI_CR1_SPE;
DMA1->HIFCR = DMA_HIFCR_CFEIF4 | DMA_HIFCR_CHTIF4 | DMA_HIFCR_CTCIF4 | DMA_HIFCR_CTEIF4 | DMA_HIFCR_CDMEIF4;
DMA1_Stream4->NDTR = WIDTH * HEIGHT * 2;
DMA1_Stream4->CR |= DMA_SxCR_EN;
__NOP();
/*
NDTR = 25'599 // (-1)
FS[2:0] = 0b011 // 3/4
FEIF5 = 1 // error
*/
SPI2->CR1 |= SPI_CR1_SPE;
}
Modified the function: now before launching
- disabling SPI
- enabling DMA
- enabling SPI
But you can see in the debugger that after enabling DMA, the error flag is still set.
The transmission is working.
Also tried:
- MSIZE[1:0] = 0b10 (32 bit)
- MBURST[1:0] = 0b01 (incremental burst of 4 beats)
- also an error.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-04-11 10:31 AM
It's not about SPI_CR1.SPE, but about SPI_CR2.TXDMAEN, i.e. gate of signal (which here is equal to SPI_SR.TXE), which goes to DMA. It's set before DMA has chance to fill up its FIFO, that's why it throws the FIFO error.
I recommended to use 32-bit memory-side transfer not because of any error, but because it's more efficient.
JW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2022-04-11 11:26 AM
Thank you very much!
