2016-01-07 05:02 AM
Hello all,
I obsarvate an problem with the DMA in STM32F2. I am using the STM322xG-Eval Board for the development. The firmware streams data from SRAM to I²S by DMA. I also use in the same firmware FreeRTOS. After a couple of time (sometimes after few Minutes and sometimes after over an hour) the transmission stops. I see in the DMA registers that the NDTR register is zero but the TCIF flag is not set and so the interrupt service routine is not called. Does anyone has an idea what this behaviour could cause? This is the DMA and I²S configuration:
DMA Config
{
/* Set the parameters to be configured */
DMA_InitStructure.DMA_Channel = AUDIO_MAL_DMA_CHANNEL;
DMA_InitStructure.DMA_PeripheralBaseAddr = CODEC_I2S_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0; /* This field will be configured in play function */
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = (uint32_t)0xFFFE; /* This field will be configured in play function */
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = AUDIO_MAL_DMA_PERIPH_DATA_SIZE;
DMA_InitStructure.DMA_MemoryDataSize = AUDIO_MAL_DMA_MEM_DATA_SIZE;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure);
DMA_ITConfig(AUDIO_MAL_DMA_STREAM, DMA_IT_TC, ENABLE);
DMA_ITConfig(AUDIO_MAL_DMA_STREAM, DMA_IT_HT, ENABLE);
DMA_ITConfig(AUDIO_MAL_DMA_STREAM, DMA_IT_TE | DMA_IT_FE | DMA_IT_DME, ENABLE);
SPI_I2S_DMACmd(CODEC_I2S, SPI_I2S_DMAReq_Tx, ENABLE);
/* I2S DMA IRQ Channel configuration */
NVIC_InitStructure.NVIC_IRQChannel = AUDIO_MAL_DMA_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = EVAL_AUDIO_IRQ_PREPRIO;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = EVAL_AUDIO_IRQ_SUBRIO;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
I²S config
{
I2S_InitTypeDef I2S_InitStructure;
/* Enable the CODEC_I2S peripheral clock */
RCC_APB1PeriphClockCmd(CODEC_I2S_CLK, ENABLE);
/* CODEC_I2S peripheral configuration */
SPI_I2S_DeInit(CODEC_I2S);
I2S_InitStructure.I2S_AudioFreq = AudioFreq;
I2S_InitStructure.I2S_Standard = I2S_STANDARD;
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(CODEC_I2S, &I2S_InitStructure);
}
Regards, Markus
#stm32f-dma-i²s
2016-01-07 10:51 AM
Check all the DMA interrupt flags in the service routine. TCIF isn't the only flag that stops DMA. You may have a DMA error.
2016-01-07 12:51 PM
Hello Jack,
thank you for your answer. As you can see in the first pic in my previous post, there is only the HTIF flag set. The ISR Routine isn't called if the failure occurs. I also check in the ISR if a failure interrupt flag is set. But there is no flag set. here is the code in the ISR where i check for error flags:/* FIFO Error interrupt */
if (DMA_GetFlagStatus(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TE) != RESET)
{
TRACE_INFO(''Transfer error Interrupt
'');
/* Clear the Interrupt flag */
DMA_ClearFlag(AUDIO_MAL_DMA_STREAM,
AUDIO_MAL_DMA_FLAG_TE | AUDIO_MAL_DMA_FLAG_FE | \
AUDIO_MAL_DMA_FLAG_DME);
NVIC_ClearPendingIRQ(AUDIO_MAL_DMA_IRQ);
}
else if (DMA_GetFlagStatus(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_FE) != RESET)
{
TRACE_INFO(''FIFO overrun/under-run error
'');
/* Clear the Interrupt flag */
DMA_ClearFlag(AUDIO_MAL_DMA_STREAM,
AUDIO_MAL_DMA_FLAG_TE | AUDIO_MAL_DMA_FLAG_FE | \
AUDIO_MAL_DMA_FLAG_DME);
NVIC_ClearPendingIRQ(AUDIO_MAL_DMA_IRQ);
}
else if (DMA_GetFlagStatus(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_DME) != RESET)
{
/* Manage the error generated on DMA FIFO */
EVAL_AUDIO_Error_CallBack((uint32_t*)&WritePtrAddr);
/* Clear the Interrupt flag */
DMA_ClearFlag(AUDIO_MAL_DMA_STREAM,
AUDIO_MAL_DMA_FLAG_TE | AUDIO_MAL_DMA_FLAG_FE | \
AUDIO_MAL_DMA_FLAG_DME);
}
At the moment I have an workaround.
I check in a seperate task if the NDTR Register is zero.
If so, then reinit the stream.
This works fine.
But this is not the answer what cause this failure.
Regards,
Markus