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_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(;![wink](img/smilies/wink.png)
{
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(;![wink](img/smilies/wink.png)
{
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.