AnsweredAssumed Answered

STM32 , DMA Transfer Complete Interrupt never triggers

Question asked by garcia_de_marina.hec on Aug 28, 2011
Latest reply on Aug 28, 2011 by garcia_de_marina.hec
Hello guys, 

I spent all the afternoon trying to just trigger an interrupt. The example is easy, I have FreeRTOS 7.0.1 running with a periodic task which writes a sequence towards USART2 employing the DMA1 (channel7).

The transfer is successful as I can read it in the PC Serial Port, but the interrupt informing the transfer completed never occurs. The code is the next:

main.c:

#define DMA_Channel_USART2_RX    DMA1_Channel6
#define DMA_Channel_USART2_TX    DMA1_Channel7
#define DMA_FLAG_USART2_TC_RX    DMA1_FLAG_TC6
#define DMA_FLAG_USART2_TC_TX    DMA1_FLAG_TC7

void send_USART_dma(const uint8_t *buff, uint8_t size)
{
   DMA_InitTypeDef DMA_InitStructure;

   /* shared DMA configuration values */
   DMA_InitStructure.DMA_PeripheralBaseAddr = &(USART2->DR);
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
   DMA_InitStructure.DMA_MemoryBaseAddr = buff;
   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

   DMA_DeInit(DMA_Channel_USART2_TX);
   DMA_Init(DMA_Channel_USART2_TX, &DMA_InitStructure);
   DMA_ITConfig(DMA1_Channel7, DMA1_IT_TC7, ENABLE);


   DMA_Cmd(DMA_Channel_USART2_TX, ENABLE);
   USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);
   //while (DMA_GetFlagStatus(DMA_FLAG_USART2_TC_TX) == RESET) { ; } <- Here I want the interrupt instead an active waiting
   
}

void initUSARTs(void)
{
   GPIO_InitTypeDef GPIO_InitStructure;
   USART_InitTypeDef USART_InitStructure;
   
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

   /* Configure USART Tx as alternate function push-pull */
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(GPIOA, &GPIO_InitStructure);
 

   /* Configure USART Rx as input floating */
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
   GPIO_Init(GPIOA, &GPIO_InitStructure);


   USART_InitStructure.USART_BaudRate = 115200;
   USART_InitStructure.USART_WordLength = USART_WordLength_8b;
   USART_InitStructure.USART_StopBits = USART_StopBits_1;
   USART_InitStructure.USART_Parity = USART_Parity_No;
   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
   USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

   USART_Init(USART2, &USART_InitStructure);
   USART_Cmd(USART2, ENABLE);
}

void blinkingLed(void *pvParameters)
{
   portTickType xLastWakeTime = xTaskGetTickCount();

   unsigned led_on = 0;

   for(;
   {
      led_on = ~led_on;
      if(led_on)
         GPIOC->BSRR |= 0x00001000;
      else
         GPIOC->BRR |= 0x00001000;
      
      vTaskDelayUntil(&xLastWakeTime, (500 / portTICK_RATE_MS));
   }
}

void countdown(void *pvParameters)
{
   portTickType xLastWakeTime = xTaskGetTickCount();
   
   uint8_t count[] = {0x44, 0xFF, 0x55};
   uint32_t entero32 = 0x11223344;
   
   for(;
   {
         send_USART_dma(&entero32, 4);
             vTaskDelayUntil(&xLastWakeTime, (1000 / portTICK_RATE_MS));
   }   

}

void iDMA1_Channel7_IRQHandler(void)
{
   DMA_ClearITPendingBit( DMA1_IT_TC7);
   DMA_Cmd(DMA_Channel_USART2_TX, DISABLE);
   USART_SendData(USART2, 0x99);
}

int main(int argc, char *argv[]) {

   initLEDs();
   initUSARTs();

   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

   NVIC_InitTypeDef NVIC_InitStructure;
   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
   NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
   //NVIC_EnableIRQ(DMA1_Channel7_IRQn); <- I guess this is done in NVIC_Init

   // Creating tasks
   xTaskCreate(blinkingLed, "Task 1", 240, NULL, 1, NULL);
   xTaskCreate(countdown, "Task 2", 240, NULL, 1, NULL);
   
   vTaskStartScheduler();
   return 0;



Some info to avoid pasting more trivial code, the Handler is well attach to the interruptVector and I could run a Timer interrupt with the same steps as in this code.

Do you what is happening?
Thanks in advance.

Outcomes