2013-08-07 12:21 PM
I'm confused about the FIFO error flag (FEIF) when I set up DMA for direct mode transfers. As I understand it, in direct mode the FIFO is disabled. But for some reason, if I enable the FE interrupt in the DMA_SxFCR register then shortly after I enable DMA I see the FIFO error flag get set. Any ideas why? Is this flag a don't care in direct mode?
To give you an idea of the application, I store a bunch of data in a SPI flash that I send to a codec over I2S. The I2S transfer happens using DMA. The code I'm using to set everything up is below./* Initialize I2S GPIOs - follow procedure in stm32f4xx_spi.c
* I2S_SCLK - Port B, Pin 10 (pin13)
* I2S_WS - Port B, Pin 12
* I2S_SDO - Port C, Pin 3 (Port B, Pin 15)
* I2S_SDI - (Port B, Pin 14)
* I2S_MCLK - Port C, Pin 6
*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_SPI2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_SPI2);
/* Initialize the I2S Peripheral */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
SPI_I2S_DeInit(SPI2);
I2S_InitStructure.I2S_AudioFreq = SAMPLING_RATE;
I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;
I2S_Init(SPI2, &I2S_InitStructure);
RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S);
RCC_PLLI2SCmd(ENABLE);
while(!RCC_GetFlagStatus(RCC_FLAG_PLLI2SRDY));
/* Configure DMA for I2S transactions */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
DMA_Cmd(DMA1_Stream4, DISABLE);
DMA_DeInit(DMA1_Stream4);
/* Set the parameters to be configured */
DMA_InitStructure_Tx.DMA_Channel = DMA_Channel_0;
DMA_InitStructure_Tx.DMA_PeripheralBaseAddr = 0x4000380C;
DMA_InitStructure_Tx.DMA_Memory0BaseAddr = (uint32_t)0;
DMA_InitStructure_Tx.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure_Tx.DMA_BufferSize = (uint32_t)0xFFFF;
DMA_InitStructure_Tx.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure_Tx.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure_Tx.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure_Tx.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure_Tx.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure_Tx.DMA_Priority = DMA_Priority_High;
DMA_InitStructure_Tx.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure_Tx.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
DMA_InitStructure_Tx.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure_Tx.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream4, &DMA_InitStructure_Tx);
/* Enable the DMA interrupts */
DMA_ITConfig(DMA1_Stream4, DMA_IT_TC | DMA_IT_TE | DMA_IT_FE | DMA_IT_DME, ENABLE);
/* I2S DMA IRQ Channel configuration */
NVIC_EnableIRQ(DMA1_Stream4_IRQn);
/* Enable the I2S DMA request */
SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);
Then later to actually enable DMA I have the following:
/* Set the memory address and size for DMA transfer
* NOTE: Stream must be disabled to change these parameters! */
DMA_InitStructure_Tx.DMA_Memory0BaseAddr = dma_addr0;
DMA_InitStructure_Tx.DMA_BufferSize = dma_size;
DMA_DoubleBufferModeConfig(DMA1_Stream4, dma_addr1, 0);
DMA_DoubleBufferModeCmd(DMA1_Stream4, ENABLE);
DMA_Init(DMA1_Stream4, &DMA_InitStructure_Tx);
// PRINT OUT REGISTERS & TOGGLE GPIO
/* Enable DMA Stream and I2S Peripheral */
DMA_Cmd(DMA1_Stream4, ENABLE);
if ((SPI2->I2SCFGR & 0x0400) == 0) {
I2S_Cmd(SPI2, ENABLE);
}
I print out all the DMA/I2S registers right before I enable them and everything looks the way it should:
DMA Regs
LISR: 0x00000000
HISR: 0x00000000
LIFCR: 0x00000000
HIFCR: 0x00000000
CR: 0x00062D56
NDTR: 0x00000200
PAR: 0x4000380C
M0AR: 0x20001464
M1AR: 0x20001864
FCR: 0x000000A0
I2S Regs
CR2: 0x00000002
SR: 0x00000002
DR: 0x00000000
I2SCFGR: 0x00000A00
I2SPR: 0x00000204
#dma-fe-error
2013-09-12 03:13 AM
Hi Andrew,
In your case, try to disable all interrupts and keep only the needed one(s). Then you have to check in the ISR that the flag you use is enabled. -Mayla-To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2014-06-20 02:57 PM
Mayla,
Your advice, of course, is good... you only want to enable interrupts that you can/want to use.I would observe, however, that the Cube firmware takes much of that choice away from the developer. In particular, if you look at stm32f4xx_hal_dma.c near line 400, you will see that DMA_IT_FE is always enabled, whether FIFOMODE was enabled or not.My application shows the same sort of problems as described in the original post here... an endless stream of FE interrupts, even though FIFOMODE is not even enabled.The HAL code needs to be corrected to do something like: if (hdma->Init.FIFOMode == DMA_FIFOMODE_ENABLE){
__HAL_DMA_ENABLE_IT(hdma, DMA_IT_FE);}
Looking a bit beyond that simple HAL bugfix, though, one has to ask: why is the DMA controller sending this endless stream of FE interrupts when you've explicitly told it that you don't want FIFOMODE? This sounds like a bug in the DMA controller itself.2014-06-20 03:23 PM
The FE error you see is a signal that the FIFO has dropped below the threshold. Why this occurs in direct mode doesn't make a lot of sense. Look at the DMA_SxFCR register, fields FS and FTH. If FS is below the FTH setting then FE can be ignored.
Jack Peacock2014-06-23 07:20 AM
Jack,
That's the sort of thing I did in my first pass at a fix to my code. Spurious interrupts take resources, though. It's the HAL code that should be amended. Obviously, I've done that in my version, but the distribution version should also be corrected.2014-06-24 06:45 AM
In direct mode you disable FE interrupt and enable DME so it's not really a spurious interrupt. The FE bit is set but can safely be ignored in direct mode.
Jack Peacock2016-04-21 02:35 PM
After spending the last two days (and nights) trying to figure out why my SPI DMA transfers were only delivering up to five bytes, I finally stumbled upon the right keywords to find this thread.
''Surely ST would have corrected their Cube code generator by now, since it's almost been a year since this was reported (and acknowledged)...'', I said to myself. However the problem still exists for F7 generated code using version 1.3.1 (current as of today). I even looked at the example in the package for the F746-DISCO that showed SPI DMA full duplex communications. Note to everyone who tries to use this model to communicate with a device that actually uses a chip select (conveniently not used in this example) - if you rely on their wTransferComplete flag to set NSS high, you will sometimes see CS go high early, cutting off the last byte. If you ALSO wait for the HAL_SPI_GetState(&hspi) to return HAL_SPI_STATE_READY, you will still sometimes issue your NSS high before the data is clocked out (verified on scope with protocol analyzer). At least I am no longer having my spi streams cut off early after making sure the FIFO error interrupt didn't get enabled. I not have yet another section of code that needs to be modified every time I update my cube configuration and regenerate code. Lots of fun. Now if I can only figure out what to monitor before taking my NSS high...2024-02-29 06:39 AM
Dear ST-Support,
are you kidding me???
This bug was reported in 2013 and I found the thread because it is still present in the most recent HAL version (STM32F7xx_HAL_Driver v1.17.1).
That's 11 years!
And isaac23 even gave you a fix.
I hope you'll finally fix it, now that I brought it up again, but as history shows it, will most likely be ignored...