AnsweredAssumed Answered

USART DMA FIFO error and multi level interrupt problem-STM32F4-discovery

Question asked by vitez.laszlo on Oct 5, 2013
Latest reply on Oct 8, 2013 by Clive One

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...



001.#define PERIPH_BUFF_SIZE 1
002.typedef uint32_t PeripheralBufferType;
003.PeripheralBufferType Periph_InputData[PERIPH_BUFF_SIZE];
004.PeripheralBufferType Periph_OutputData[PERIPH_BUFF_SIZE];
005.#define SafeUartTransfer() while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);\
006.USART_ClearFlag(USART2,USART_FLAG_TC);\
007.DMA_Cmd(DMA1_Stream6,ENABLE);
008.bool transferInProgress=false;
009.bool USART_DMA_frame_error=false;
010.void TIM2_IRQHandler()
011.{
012.if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
013.{
014.TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
015.if(transferInProgress)
016.{
017.USART_DMA_frame_error=true;
018.DMA_Cmd(DMA1_Stream5,DISABLE);
019.DMA_Cmd(DMA1_Stream5,ENABLE);
020.while(USART_DMA_frame_error);
021.transferInProgress=false;
022.++USART_DMA_frame_error_cnt;
023.STM_EVAL_LEDToggle(LED6);
024.}
025.else if(DMA_GetCurrDataCounter(DMA1_Stream5)!=PERIPH_BUFF_SIZE*sizeof(PeripheralBufferType))
026.transferInProgress=true;
027.}
028.
029.}
030.
031.void DMA1_Stream5_IRQHandler()
032.{
033.if(DMA_GetITStatus(DMA1_Stream5,DMA_IT_TCIF5))
034.{
035.transferInProgress=false;
036.DMA_ClearITPendingBit(DMA1_Stream5,DMA_IT_TCIF5);
037.DMA_ClearITPendingBit(DMA1_Stream5,DMA_IT_HTIF5);
038.if(!USART_DMA_frame_error)
039.{
040.InputAction();
041.for(int j=0;j<PERIPH_BUFF_SIZE;++j)
042.{
043.Periph_OutputData[j]=Periph_InputData[j];
044.}
045.STM_EVAL_LEDToggle (LED5);
046.DMA_Cmd(DMA1_Stream5,ENABLE);
047.SafeUartTransfer();
048.}
049.else
050.USART_DMA_frame_error=false;
051.}
052.}
053.void DMA1_Stream6_IRQHandler()
054.{
055.if(DMA_GetITStatus(DMA1_Stream6,DMA_IT_TCIF6))
056.{
057.DMA_ClearITPendingBit(DMA1_Stream6,DMA_IT_TCIF6);
058.DMA_ClearITPendingBit(DMA1_Stream6,DMA_IT_HTIF6);
059.if(DMA_GetFlagStatus(DMA1_Stream6,DMA_IT_FEIF6)==SET)
060.STM_EVAL_LEDOn(LED6);
061.else
062.STM_EVAL_LEDOff(LED6);
063.DMA_ClearITPendingBit(DMA1_Stream6,DMA_IT_FEIF6);
064.}
065.}
066.
067.void USART2GPIOInit()
068.{
069.GPIO_InitTypeDef InitStructure;
070.//enable peripherial clock
071.RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
072.
073.GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2);
074.GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2);
075.
076.
077.InitStructure.GPIO_Mode=GPIO_Mode_AF;
078.InitStructure.GPIO_OType=GPIO_OType_PP;
079.InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
080.InitStructure.GPIO_Speed=GPIO_Speed_25MHz;
081.InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3;
082.GPIO_Init(GPIOA,&InitStructure);
083.}
084.void USART2Init()
085.{
086.RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
087.
088.USART_InitTypeDef InitStructure;
089.
090.
091.InitStructure.USART_BaudRate=115200;
092.InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
093.InitStructure.USART_Mode=USART_Mode_Rx | USART_Mode_Tx;
094.InitStructure.USART_Parity=USART_Parity_No;
095.InitStructure.USART_StopBits=USART_StopBits_1;
096.InitStructure.USART_WordLength=USART_WordLength_8b;
097.
098.USART_Init(USART2,&InitStructure);
099.}
100.
101.void USART2DMAAndIRQInitRx()
102.{
103.DMA_InitTypeDef DMAInitStructure;
104.NVIC_InitTypeDef NVIC_InitStructure;
105.
106.RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);
107.
108.DMA_DeInit(DMA1_Stream5 );
109.while (DMA_GetCmdStatus(DMA1_Stream5 ) != DISABLE);
110.
111.DMAInitStructure.DMA_BufferSize=PERIPH_BUFF_SIZE*sizeof(PeripheralBufferType);//because it depends on the pripheral data size
112.DMAInitStructure.DMA_Channel=DMA_Channel_4;
113.DMAInitStructure.DMA_DIR= DMA_DIR_PeripheralToMemory;
114.DMAInitStructure.DMA_FIFOMode=DMA_FIFOMode_Enable;
115.DMAInitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_1QuarterFull;
116.DMAInitStructure.DMA_Memory0BaseAddr=(uint32_t) &Periph_InputData;
117.DMAInitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;
118.DMAInitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Word;
119.DMAInitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
120.DMAInitStructure.DMA_Mode=DMA_Mode_Normal;
121.DMAInitStructure.DMA_PeripheralBaseAddr=(uint32_t)&USART2->DR;
122.DMAInitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
123.DMAInitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
124.DMAInitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
125.DMAInitStructure.DMA_Priority=DMA_Priority_Medium;
126.
127.DMA_Init(DMA1_Stream5,&DMAInitStructure);
128.
129.
130.DMA_ITConfig (DMA1_Stream5, DMA_IT_TC, ENABLE); // Transfer complete interrupt mask
131.
132.NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream5_IRQn;
133.NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
134.NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
135.NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
136.NVIC_Init (&NVIC_InitStructure);
137.
138.USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);
139.
140.DMA_ClearFlag(DMA1_Stream5, DMA_FLAG_TCIF5 );
141.DMA_Cmd(DMA1_Stream5,ENABLE);
142.}
143.void USART2DMAAndIRQInitTx()
144.{
145.DMA_InitTypeDef DMAInitStructure;
146.NVIC_InitTypeDef NVIC_InitStructure;
147.
148.DMA_DeInit(DMA1_Stream6 );
149.
150.while (DMA_GetCmdStatus(DMA1_Stream6 ) != DISABLE);
151.
152.DMAInitStructure.DMA_BufferSize=PERIPH_BUFF_SIZE*sizeof(PeripheralBufferType);
153.DMAInitStructure.DMA_Channel=DMA_Channel_4;
154.DMAInitStructure.DMA_DIR= DMA_DIR_MemoryToPeripheral;
155.DMAInitStructure.DMA_FIFOMode=DMA_FIFOMode_Enable;
156.DMAInitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_1QuarterFull;
157.DMAInitStructure.DMA_Memory0BaseAddr=(uint32_t) &Periph_OutputData;
158.DMAInitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;
159.DMAInitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Word;
160.DMAInitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
161.DMAInitStructure.DMA_Mode=DMA_Mode_Normal;
162.DMAInitStructure.DMA_PeripheralBaseAddr=(uint32_t)&USART2->DR;
163.DMAInitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
164.DMAInitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
165.DMAInitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
166.DMAInitStructure.DMA_Priority=DMA_Priority_Medium;
167.
168.DMA_Init(DMA1_Stream6,&DMAInitStructure);
169.DMA_ITConfig (DMA1_Stream6, DMA_IT_TC, ENABLE); // Transfer complete interrupt mask
170.
171.NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream6_IRQn;
172.NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
173.NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
174.NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
175.NVIC_Init (&NVIC_InitStructure);
176.
177.USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE);
178.
179.DMA_ClearFlag(DMA1_Stream6, DMA_FLAG_TCIF6 );
180.
181.}
182.
183./**
184.* @brief Initiates timer 2 * @param None
185.* @retval None
186.*/
187.void TMR2Init()
188.{
189.TIM_TimeBaseInitTypeDef def;
190.NVIC_InitTypeDef NVIC_InitStructure;
191.
192.SystemCoreClockUpdate();
193.RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
194.
195.def.TIM_ClockDivision=0;
196.def.TIM_CounterMode=TIM_CounterMode_Down;
197.def.TIM_Period=SystemCoreClock/2-1;
198.def.TIM_RepetitionCounter=0;
199.def.TIM_Prescaler=0;
200.TIM_TimeBaseInit(TIM2,&def);
201.
202.
203.TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
204.TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
205.
206.NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
207.NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
208.NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
209.NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
210.NVIC_Init(&NVIC_InitStructure);
211.
212.TIM_Cmd(TIM2,ENABLE);
213.
214.}
215.
216.void main()
217.{
218.NVIC_SetPriorityGrouping(NVIC_PriorityGroup_3);
219.TMR2Init();
220.USART2GPIOInit();
221.USART2Init();
222.USART2DMAAndIRQInitRx();
223.USART2DMAAndIRQInitTx();
224.USART_Cmd(USART2,ENABLE);
225.while(1);
226.
227.}

Outcomes