cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 , DMA Transfer Complete Interrupt never triggers

noeth3r
Associate
Posted on August 28, 2011 at 22:37

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.

1 REPLY 1
noeth3r
Associate
Posted on August 28, 2011 at 23:14

solved ...

 DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);

instead DMA1_IT_TC7 in second parameter.