2022-04-11 04: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.
The alignment was done with a margin. Tried before 4 - no result
Solved! Go to Solution.
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
2022-04-11 05: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
2022-04-11 08: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
But you can see in the debugger that after enabling DMA, the error flag is still set.
The transmission is working.
Also tried:
- also an error.
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
2022-04-11 11:26 AM
Thank you very much!