AnsweredAssumed Answered

STM32F407 DMA2 Repeated Disable and Enable Fails

Question asked by Josh Yu on Apr 12, 2018
Latest reply on Apr 13, 2018 by AvaTar

Hi,

 

I'm using STM32F407 in my project and I use DMA2 on USART1 RX/TX. Since my TX packet length changes almost every time, I'd have to disable DMA, reconfigure it to the correct data length, and enable DMA. I'm doing this at least 100Hz if not more. And I don't know if it's because of that, the DMA would fail to enable after random periods of time. I write 1 to the EN bit in the control register and poll it to make sure it actually becomes 1, but it never does. I'm not sure what the problem is, since it always works for a few minutes then stops working. Another interesting point is that the DMA2 RX doesn't stop working at all. If anyone has any pointers I highly appreciate it. Thanks!

 

Here's my USART1 TX and DMA reconfigure code: (by the way, the printf statements printed out the same values when the DMA is working and when it's not)

 

void USART1_DMA2_Send_Array(u8 * data_to_send_addr, u16 send_length)
{
     static int i = 0;
     // Make sure that the UART TX DMA is disabled (which should already be disabled by hardware if
     // the previous transfer is completed)

     uint16_t remaining = DMA_GetCurrDataCounter(DMA2_Stream7);
     if (remaining != 0) {
          printf("Remaining DMA transfer = %u", remaining);
     }

     i = 0;
     DMA_Cmd(DMA2_Stream7,DISABLE);
     while(DMA_GetCmdStatus(DMA2_Stream7) != DISABLE) {
          DMA_Cmd(DMA2_Stream7,DISABLE);
          printf("Disabling DMA... %d\n", i);
          i++;
          if (i > 1000) {
               System_Failure();
          }
     }

     DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_TCIF7|DMA_FLAG_HTIF7|DMA_FLAG_TEIF7|DMA_FLAG_DMEIF7|DMA_FLAG_FEIF7);
     USART_ClearFlag(USART1, USART_FLAG_TC);

     DMA_InitTypeDef  DMA_InitStructure;

    // common configuration
    DMA_StructInit(&DMA_InitStructure);
    DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_FIFOMode                 = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_1QuarterFull;
    DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;
    DMA_InitStructure.DMA_Priority           = DMA_Priority_High;

    // Configure TX DMA: DMA2_Stream7 Channel 4
    DMA_InitStructure.DMA_Channel            = DMA_Channel_4;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(USART1->DR);
    DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;
    DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_DIR                = DMA_DIR_MemoryToPeripheral;
    DMA_InitStructure.DMA_BufferSize         = send_length;
    DMA_InitStructure.DMA_Memory0BaseAddr    = (u32)data_to_send_addr;
    DMA_Init(DMA2_Stream7,&DMA_InitStructure);

//     DMA_SetCurrDataCounter(DMA2_Stream7, send_length);
//    printf("Enabling DMA... %d\n", i);
//     printf("Buffer size = %u\n", send_length);
//     printf("USART1->SR = 0x%x\n", USART1->SR);
//     printf("USART1->CR1 = 0x%x\n", USART1->CR1);
//     printf("USART1->CR3 = 0x%x\n", USART1->CR3);
//     printf("DMA2->HISR = 0x%x\n", DMA2->HISR);
//     printf("DMA2->S7CR = 0x%x\n\n", DMA2_Stream7->CR);

    // started to transmit
    i = 0;
    DMA_Cmd(DMA2_Stream7,ENABLE);
    while(DMA_GetCmdStatus(DMA2_Stream7) != ENABLE) {
         DMA_Cmd(DMA2_Stream7,ENABLE);
//          printf("Enabling DMA... %d\n", i);
//          printf("Buffer size = %u\n", send_length);
//          printf("USART1->SR = 0x%x\n", USART1->SR);
//          printf("USART1->CR1 = 0x%x\n", USART1->CR1);
//          printf("USART1->CR3 = 0x%x\n", USART1->CR3);
//          printf("DMA2->HISR = 0x%x\n", DMA2->HISR);
//          printf("DMA2->S7CR = 0x%x\n", DMA2_Stream7->CR);
          i++;
          vTaskDelay(pdMS_TO_TICKS(1));
          if (i > 1000) {
               System_Failure();
          }
    }
}

Outcomes