2025-02-11 01:07 AM - edited 2025-02-11 01:08 AM
When using DMA to do a SPI transmit, I found a strange behavior. The problem is, that the communication to the DAC works for a few seconds, depending on the used frequency. After the few seconds only 1 byte instead of 3 bytes are sent and the NSS Pin (Hardware regulated) stays low. You can even see these two data items to transfer in S1NDTR (NDT). I used the approximately same code with Software NSS without any problem.
I also get a DMA FIFO Error (FEIF) directly after starting the DMA stream, even when using DMA circular mode. Not every time but over 50% of the times when the communication is working I get the FEIF. When the communication is not working anymore, I do not get the FEIF anymore.
I found these factors influencing the error:
- Using DMA normal mode/ circular mode -> no difference
- Enabling DMA FIFO -> no difference
- Increase frequency of sending values to the DAC: communication breaks very fast
- Decrease frequency of sending values to the DAC: communication does not break
- Changing Priorities -> no difference
This is my SPI configuration:
/* SPI1 parameter configuration*/
SPI_InitStruct.TransferDirection = LL_SPI_SIMPLEX_TX;
SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;
SPI_InitStruct.NSS = LL_SPI_NSS_HARD_OUTPUT;
SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4;
SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
SPI_InitStruct.CRCPoly = 0x0;
LL_SPI_Init(SPI1, &SPI_InitStruct);
LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);
LL_SPI_DisableNSSPulseMgt(SPI1);
This is my corresponding DMA config:
167: Dma.SPI1_TX.1.Direction=DMA_MEMORY_TO_PERIPH
168: Dma.SPI1_TX.1.EventEnable=DISABLE
169: Dma.SPI1_TX.1.FIFOMode=DMA_FIFOMODE_DISABLE
170: Dma.SPI1_TX.1.Instance=DMA2_Stream1
171: Dma.SPI1_TX.1.MemDataAlignment=DMA_MDATAALIGN_BYTE
172: Dma.SPI1_TX.1.MemInc=DMA_MINC_ENABLE
173: Dma.SPI1_TX.1.Mode=DMA_CIRCULAR
174: Dma.SPI1_TX.1.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
175: Dma.SPI1_TX.1.PeriphInc=DMA_PINC_DISABLE
176: Dma.SPI1_TX.1.Polarity=HAL_DMAMUX_REQ_GEN_RISING
177: Dma.SPI1_TX.1.Priority=DMA_PRIORITY_HIGH
178: Dma.SPI1_TX.1.RequestNumber=1
179: Dma.SPI1_TX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,SignalID,Polarity,RequestNumber,SyncSignalID,SyncPolarity,SyncEnable,EventEnable,SyncRequestNumber
180: Dma.SPI1_TX.1.SignalID=NONE
181: Dma.SPI1_TX.1.SyncEnable=DISABLE
182: Dma.SPI1_TX.1.SyncPolarity=HAL_DMAMUX_SYNC_NO_EVENT
183: Dma.SPI1_TX.1.SyncRequestNumber=1
184: Dma.SPI1_TX.1.SyncSignalID=NONE
This is the code I am using for sending the values to the DAC (shortened it to just the important parts):
dma_buffer_dac1[0] = (COMMAND_SOFTWARE_RESET >> 16);
dma_buffer_dac1[1] = 0;
dma_buffer_dac1[2] = 0 ;
LL_SPI_StartMasterTransfer(DACX->spi); // sets CSTART bit of SPI
LL_DMA_EnableStream(DACX->xdma_tx); // sets EN bit of DMA
while (DACX1_DMA_TX_CHECK_TC_ACTIVE == 0) {} // wait until DMA transfer complete
//Reset transmission flags
LL_DMA_ClearFlag_TC1(DACX1_DMA);
LL_DMA_ClearFlag_HT1(DACX1_DMA);
LL_DMA_ClearFlag_FE1(DACX1_DMA);
while (!LL_SPI_IsActiveFlag_EOT(DACX1.spi){} // wait for SPI End of Transfer
LL_SPI_ClearFlag_EOT(DACX1.spi);
Can anyone help my why the communication breaks?
I am not sure if the FEIF is the problem here, but I am also interested why the FEIF error is showing up?
2025-02-11 06:02 AM
Here are the possibilities:
What else is going on in your program that is using the DMA, particular at same/higher priority levels?
What are the values of the DMA registers when the error occurs?