STM32 , DMA Transfer Complete Interrupt never triggers

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_BufferSize = size;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
	DMA_InitStructure.DMA_M2M = DMA_M2M_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_GL7 | 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
	//DMA_Cmd(DMA_Channel_USART2_TX, DISABLE);
}

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_GL7 | DMA1_IT_TC7);
	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);

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

solved …

DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);

instead DMA1_IT_TC7 in second parameter. Libs are really helpfull, but sometimes are really “harder” to debug xD