2012-06-04 02:15 AM
Hi all,
I'm using the STM Discovery EVM to make some sample program. I'm using IAR as compiler and CMSIS 2.1 In this example I simple set a timer with 50ms period and start DMA transfert on USART 3 The transfer is correctly done on the serial port (I see the transmitted sting using Hyperterminal on PC), but I have a problem on the DMA IRQ Handler routine, Infact when I check the TCIF flag I found that the DMA transfert is not complete (while the transfert is already done on serial port). Furthermore I check for any DMA tranfert error and I found that there are no error. Where I wrong? Here The revelant part of the code: First the define for DMA /* Definition for DMAx resources **********************************************/ #define USARTx_DR_ADDRESS ((uint32_t)USART3 + 0x04) #define USARTx_DMA DMA1 #define USARTx_DMAx_CLK RCC_AHB1Periph_DMA1 #define USARTx_TX_DMA_CHANNEL DMA_Channel_4 #define USARTx_TX_DMA_STREAM DMA1_Stream3 #define USARTx_TX_DMA_FLAG_FEIF DMA_FLAG_FEIF3 #define USARTx_TX_DMA_FLAG_DMEIF DMA_FLAG_DMEIF3 #define USARTx_TX_DMA_FLAG_TEIF DMA_FLAG_TEIF3 #define USARTx_TX_DMA_FLAG_HTIF DMA_FLAG_HTIF3 #define USARTx_TX_DMA_FLAG_TCIF DMA_FLAG_TCIF3 #define USARTx_RX_DMA_CHANNEL DMA_Channel_4 #define USARTx_RX_DMA_STREAM DMA1_Stream1 #define USARTx_RX_DMA_FLAG_FEIF DMA_FLAG_FEIF1 #define USARTx_RX_DMA_FLAG_DMEIF DMA_FLAG_DMEIF1 #define USARTx_RX_DMA_FLAG_TEIF DMA_FLAG_TEIF1 #define USARTx_RX_DMA_FLAG_HTIF DMA_FLAG_HTIF1 #define USARTx_RX_DMA_FLAG_TCIF DMA_FLAG_TCIF1 #define USARTx_DMA_TX_IRQn DMA1_Stream3_IRQn #define USARTx_DMA_RX_IRQn DMA1_Stream1_IRQn #define USARTx_DMA_TX_IRQHandler DMA1_Stream3_IRQHandler #define USARTx_DMA_RX_IRQHandler DMA1_Stream1_IRQHandler here the TX Buffer String uint8_t TxBuffer[]= ''^**********************************************************************\r\n\ Prova di invio di caratteri alla seriale per vedere se ne perde qualcuno\r\n\ Cosi vediamo come si comporta il uP e il PC sperando che entrambi ce la facciano\r\n\ **********************************************************************@''; Then the Timer IRQ Handler routine: void TIM3_IRQHandler(void) { if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_CC1); /* LED4 toggling with frequency = 4.57 Hz */ STM_EVAL_LEDToggle(LED4); capture = TIM_GetCapture1(TIM3); TIM_SetCompare1(TIM3, capture + CCR1_Val); if (!DMASet) SetDMA(); STM_EVAL_LEDToggle(LED4); } } Here MY routine for DMA settings void SetDMA(void) { DMASet = 1; DMA_DeInit(USARTx_TX_DMA_STREAM); DMA_InitStructureTX.DMA_PeripheralBaseAddr = USARTx_DR_ADDRESS; DMA_InitStructureTX.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructureTX.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructureTX.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructureTX.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructureTX.DMA_Mode = DMA_Mode_Normal; DMA_InitStructureTX.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructureTX.DMA_FIFOMode = DMA_FIFOMode_Enable; DMA_InitStructureTX.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructureTX.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructureTX.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_InitStructureTX.DMA_Channel = USARTx_TX_DMA_CHANNEL; DMA_InitStructureTX.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructureTX.DMA_Memory0BaseAddr = (uint32_t)TxBuffer; // DMA_InitStructureTX.DMA_BufferSize = 300; DMA_InitStructureTX.DMA_BufferSize = 300; // DMA_InitStructureTX.DMA_BufferSize = (uint16_t)BUFFERSIZE; DMA_Init(USARTx_TX_DMA_STREAM, &DMA_InitStructureTX); /* Enable DMA1_Stream3 Transfer complete interrupt */ DMA_ITConfig(USARTx_TX_DMA_STREAM, DMA_IT_TC, ENABLE); // /* Enable DMA1_Stream3 */ // DMA_Cmd(USARTx_TX_DMA_STREAM, ENABLE); // /* Enable DMA USART Tx Stream */ DMA_Cmd(USARTx_TX_DMA_STREAM, ENABLE); } At the end the DMA IRQ Handler routine void DMA1_Stream3_IRQHandler(void) { // STM_EVAL_LEDToggle(LED6); if(DMA_GetITStatus(USARTx_TX_DMA_STREAM, USARTx_TX_DMA_FLAG_TCIF)) { DMA_ClearITPendingBit(DMA1_Stream3, DMA_IT_TCIF3); // /* Clear all DMA Streams flags */ //// DMA_ClearFlag(USARTx_TX_DMA_STREAM, USARTx_TX_DMA_FLAG_HTIF | USARTx_TX_DMA_FLAG_TCIF); // DMA_ClearFlag(USARTx_TX_DMA_STREAM, USARTx_TX_DMA_FLAG_TCIF); // // /* Disable the DMA Stream */ // DMA_Cmd(USARTx_TX_DMA_STREAM, DISABLE); // // /* Disable the USART Tx DMA request */ // USART_DMACmd(USARTx, USART_DMAReq_Tx, DISABLE); STM_EVAL_LEDToggle(LED6); } if (DMA_GetITStatus(USARTx_TX_DMA_STREAM, USARTx_TX_DMA_FLAG_TEIF)) STM_EVAL_LEDToggle(LED6); if (DMA_GetITStatus(USARTx_TX_DMA_STREAM, USARTx_TX_DMA_FLAG_HTIF)) STM_EVAL_LEDToggle(LED6); if (DMA_GetITStatus(USARTx_TX_DMA_STREAM, USARTx_TX_DMA_FLAG_FEIF)) STM_EVAL_LEDToggle(LED6); }2012-06-04 08:22 AM
Where I wrong?
USARTx_TX_DMA_FLAG_TCIF = DMA_FLAG_TCIF1 if(DMA_GetITStatus(USARTx_TX_DMA_STREAM, USARTx_TX_DMA_FLAG_TCIF)) But DMA_GetITStatus expects DMA_IT_TCIF12012-06-04 11:45 PM
Hi Clive,
but I had define USART TX as Channel 4 stream 3 #define USARTx_TX_DMA_CHANNEL DMA_Channel_4 #define USARTx_TX_DMA_STREAM DMA1_Stream3 so I define the TCIF flag as ''stream 3'' #define USARTx_TX_DMA_FLAG_TCIF DMA_FLAG_TCIF3 while the stream 1 of channel 4 is assigned to USART 3 RX channel (that is not used in this example) This assignement is according to the ST reference manual pg 164. Furthermore I enable (or I suppose that I do it) only the TX Tranfert complete IRQ /* Enable DMA1_Stream3 Transfer complete interrupt */ DMA_ITConfig(USARTx_TX_DMA_STREAM, DMA_IT_TC, ENABLE); So why you say that the DMA_GetITStatus expect TCIF1? Thanks Luca2012-06-05 12:26 AM
Hi again Clive,
Maybe I understand what you meaning, I used USARTxTX_DMA_FLAG_TCIF when I called DMA_GetITStatus, so I obtain wrong results. If I want to use DMA_GetITStatus, I had to use DMA_IT_TCIFx. if(DMA_GetITStatus(USARTx_TX_DMA_STREAM, DMA_IT_TCIF3) != (uint32_t)RESET) while If I want to use USARTx_TX_DMA_FLAG_TCIF I have to use DMA_GetFlagStatus // if(DMA_GetFlagStatus(USARTx_TX_DMA_STREAM, USARTx_TX_DMA_FLAG_TCIF) != (uint32_t)RESET) Now seems that the program working. Thanks Luca2016-11-16 12:32 AM
Hi
I had a problem similar to the one you described here. And now when i have solved it I thought it would be good to add a comment here to help others having similar problems. I have a STM32F746 mcu running Free RTOS that should send audio to a audio codec using I2S and DMA. But I had some problems getting the interrupts signaling the DMA transfer complete and DMA transfer half complete to work. It turned out that while following the examples from STM I had set the priority for the interrupts to 0, which was not permitted by Free RTOS (who permits a priority in the range of 5 down to 15. HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 5, 0); I had also a NULL-pointer exception which was hard to find. Since I had not found a good example where DMA and I2S was used together I had missed to link the DMA handler and the I2S handler. __HAL_LINKDMA (i2sHandle, hdmatx, DmaHandle); And of course I had to implement the interrupt function to handle the DMA stream interrupt. void DMA1_Stream4_IRQHandler (void) { HAL_DMA_IRQHandler (i2sHandle.hdmatx); }