USART DMA FIFO error and multi level interrupt problem-STM32F4-discovery
Hello everybody,
I try to use USART2 with DMA, but I have two problems. Now the code just sends back the received word. The memory is word based so I use the DMA controller packing/unpacking feature. My first problem is everytime when a transfer occures the FEIF6 bit of the DMA1 HISR register is set. I have tried send only one bytes when the memory was byte based as well, but this flag have been set as well. By the way, the device sends the data back perfectly I just do not understand why this bit is set.
As you can see the memory is word based, so one communication cycle includes four UART transfer. A timer guards that this cycle can't stuck in. My second problem is if the timer generates an interrupt the execution never jumps to DMA1_Strem5_IRQHandler from the timer interrupt body, although it has a higher priority and the TCIF flag have been set. It seem the multi-level interrupt doesn't work properly.
I would be very gratefull if someone could help me! These issues make me crazy...
#define PERIPH_BUFF_SIZE 1
typedef
uint32_t PeripheralBufferType;
PeripheralBufferType Periph_InputData[PERIPH_BUFF_SIZE];
PeripheralBufferType Periph_OutputData[PERIPH_BUFF_SIZE];
#define SafeUartTransfer() while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);\
USART_ClearFlag(USART2,USART_FLAG_TC);\
DMA_Cmd(DMA1_Stream6,ENABLE);
bool
transferInProgress=
false
;
bool
USART_DMA_frame_error=
false
;
void
TIM2_IRQHandler()
{
if
(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
{
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
if
(transferInProgress)
{
USART_DMA_frame_error=
true
;
DMA_Cmd(DMA1_Stream5,DISABLE);
DMA_Cmd(DMA1_Stream5,ENABLE);
while
(USART_DMA_frame_error);
transferInProgress=
false
;
++USART_DMA_frame_error_cnt;
STM_EVAL_LEDToggle(LED6);
}
else
if
(DMA_GetCurrDataCounter(DMA1_Stream5)!=PERIPH_BUFF_SIZE*
sizeof
(PeripheralBufferType))
transferInProgress=
true
;
}
}
void
DMA1_Stream5_IRQHandler()
{
if
(DMA_GetITStatus(DMA1_Stream5,DMA_IT_TCIF5))
{
transferInProgress=
false
;
DMA_ClearITPendingBit(DMA1_Stream5,DMA_IT_TCIF5);
DMA_ClearITPendingBit(DMA1_Stream5,DMA_IT_HTIF5);
if
(!USART_DMA_frame_error)
{
InputAction();
for
(
int
j=0;j<PERIPH_BUFF_SIZE;++j)
{
Periph_OutputData[j]=Periph_InputData[j];
}
STM_EVAL_LEDToggle (LED5);
DMA_Cmd(DMA1_Stream5,ENABLE);
SafeUartTransfer();
}
else
USART_DMA_frame_error=
false
;
}
}
void
DMA1_Stream6_IRQHandler()
{
if
(DMA_GetITStatus(DMA1_Stream6,DMA_IT_TCIF6))
{
DMA_ClearITPendingBit(DMA1_Stream6,DMA_IT_TCIF6);
DMA_ClearITPendingBit(DMA1_Stream6,DMA_IT_HTIF6);
if
(DMA_GetFlagStatus(DMA1_Stream6,DMA_IT_FEIF6)==SET)
STM_EVAL_LEDOn(LED6);
else
STM_EVAL_LEDOff(LED6);
DMA_ClearITPendingBit(DMA1_Stream6,DMA_IT_FEIF6);
}
}
void
USART2GPIOInit()
{
GPIO_InitTypeDef InitStructure;
//enable peripherial clock
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2);
InitStructure.GPIO_Mode=GPIO_Mode_AF;
InitStructure.GPIO_OType=GPIO_OType_PP;
InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
InitStructure.GPIO_Speed=GPIO_Speed_25MHz;
InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3;
GPIO_Init(GPIOA,&InitStructure);
}
void
USART2Init()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
USART_InitTypeDef InitStructure;
InitStructure.USART_BaudRate=115200;
InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
InitStructure.USART_Mode=USART_Mode_Rx | USART_Mode_Tx;
InitStructure.USART_Parity=USART_Parity_No;
InitStructure.USART_StopBits=USART_StopBits_1;
InitStructure.USART_WordLength=USART_WordLength_8b;
USART_Init(USART2,&InitStructure);
}
void
USART2DMAAndIRQInitRx()
{
DMA_InitTypeDef DMAInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);
DMA_DeInit(DMA1_Stream5 );
while
(DMA_GetCmdStatus(DMA1_Stream5 ) != DISABLE);
DMAInitStructure.DMA_BufferSize=PERIPH_BUFF_SIZE*
sizeof
(PeripheralBufferType);
//because it depends on the pripheral data size
DMAInitStructure.DMA_Channel=DMA_Channel_4;
DMAInitStructure.DMA_DIR= DMA_DIR_PeripheralToMemory;
DMAInitStructure.DMA_FIFOMode=DMA_FIFOMode_Enable;
DMAInitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_1QuarterFull;
DMAInitStructure.DMA_Memory0BaseAddr=(uint32_t) &Periph_InputData;
DMAInitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;
DMAInitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Word;
DMAInitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
DMAInitStructure.DMA_Mode=DMA_Mode_Normal;
DMAInitStructure.DMA_PeripheralBaseAddr=(uint32_t)&USART2->DR;
DMAInitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
DMAInitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
DMAInitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
DMAInitStructure.DMA_Priority=DMA_Priority_Medium;
DMA_Init(DMA1_Stream5,&DMAInitStructure);
DMA_ITConfig (DMA1_Stream5, DMA_IT_TC, ENABLE);
// Transfer complete interrupt mask
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init (&NVIC_InitStructure);
USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);
DMA_ClearFlag(DMA1_Stream5, DMA_FLAG_TCIF5 );
DMA_Cmd(DMA1_Stream5,ENABLE);
}
void
USART2DMAAndIRQInitTx()
{
DMA_InitTypeDef DMAInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
DMA_DeInit(DMA1_Stream6 );
while
(DMA_GetCmdStatus(DMA1_Stream6 ) != DISABLE);
DMAInitStructure.DMA_BufferSize=PERIPH_BUFF_SIZE*
sizeof
(PeripheralBufferType);
DMAInitStructure.DMA_Channel=DMA_Channel_4;
DMAInitStructure.DMA_DIR= DMA_DIR_MemoryToPeripheral;
DMAInitStructure.DMA_FIFOMode=DMA_FIFOMode_Enable;
DMAInitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_1QuarterFull;
DMAInitStructure.DMA_Memory0BaseAddr=(uint32_t) &Periph_OutputData;
DMAInitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;
DMAInitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Word;
DMAInitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
DMAInitStructure.DMA_Mode=DMA_Mode_Normal;
DMAInitStructure.DMA_PeripheralBaseAddr=(uint32_t)&USART2->DR;
DMAInitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
DMAInitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
DMAInitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
DMAInitStructure.DMA_Priority=DMA_Priority_Medium;
DMA_Init(DMA1_Stream6,&DMAInitStructure);
DMA_ITConfig (DMA1_Stream6, DMA_IT_TC, ENABLE);
// Transfer complete interrupt mask
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init (&NVIC_InitStructure);
USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE);
DMA_ClearFlag(DMA1_Stream6, DMA_FLAG_TCIF6 );
}
/**
* @brief Initiates timer 2 * @param None
* @retval None
*/
void
TMR2Init()
{
TIM_TimeBaseInitTypeDef def;
NVIC_InitTypeDef NVIC_InitStructure;
SystemCoreClockUpdate();
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
def.TIM_ClockDivision=0;
def.TIM_CounterMode=TIM_CounterMode_Down;
def.TIM_Period=SystemCoreClock/2-1;
def.TIM_RepetitionCounter=0;
def.TIM_Prescaler=0;
TIM_TimeBaseInit(TIM2,&def);
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2,ENABLE);
}
void
main()
{
NVIC_SetPriorityGrouping(NVIC_PriorityGroup_3);
TMR2Init();
USART2GPIOInit();
USART2Init();
USART2DMAAndIRQInitRx();
USART2DMAAndIRQInitTx();
USART_Cmd(USART2,ENABLE);
while
(1);
}
#usart-fifo-dma-interrupt