AnsweredAssumed Answered

DMA_CERQ - response time to actually stop the DMA channel (clear bit in DMA_ERQ)?

Question asked by Jarkko Silvasti on Oct 22, 2015
Latest reply on Nov 13, 2015 by Earl Orlando Ramirez Sanchez

Is there or actually how much there is/can be delay between giving the DMA disable request and that channel has been actually stopped?

 

I have basically following code to tackle the uart errors during DMA transfer (see my other post Kinetis (K10) UART DMA rx error handling ).

- key point is to stop DMA&uart until the uart error has been completely solved


void Uart_error_irq( void )

{

  UART_C2_REQ( uart0 ) &= ~(UART_C2_RE_MASK);

  DMA_CERQ = DMA_CERQ_CERQ(uart_rx_dma_ch);

 

  status = UART_S1_REQ( uart0 );

  (void)UART_D_REG( uart0 );

  UART_C_FIFO_REG( uart0 ) |= (UART_CFIFO_RXFLUSH_MASK);

  print_uart_error( status );

 

  notifytask(); // posts error event to task

}

 

task()

{

   event = wait_events();

   if( event & uart_error)

   {

      error_event_handler();

   }

}

 

void error_event_handler( void )

{
  if( DMA_ERQ & uart_rx_dma_ch )
  {

    // DMA still running

    notifytask(); // kick task again to avoid busy loops // added afterwards

    u32DmaStillRunningCountDebug++;

  }

  else

  {

    SetBufferReadingIndex();

    UART_C_FIFO_REG( uart0 ) |= (UART_CFIFO_RXFLUSH_MASK); // just in case

    DMA_SERQ = DMA_SERQ_SERQ( uart_rx_dma_ch );
    if( DMA_ERR & uart_rx_dma_ch )

    {

      Error();

    }
    UART_C2_REQ( uart0 ) |= UART_C2_RE_MASK;

  }

}

 

I test the system by calling by Uart_error_irq() periodically from my software (1sec in this case) to simulate the error (this is the only reasonable way to test that my error handling code works & the transferred protocol over uart tolerates such errors).

- I noticed that sometimes u32DmaStillRunningCountDebug increases

 

Then I looked a little bit further and noticed that DMA_CERQ-command is not always "immediately" visible in DMA_ERQ, so I added the task-re-kicker rather than while( DMA_ERQ & uart_rx_dma_ch )-busy wait loop and now it looks to work ok.

- CPU manual does not mention that there is any delays, based on my tests the delay exists only if there is active uart-transmission ongoing...

 

If the DMA is serving the uart request I assume that it cannot be immediately stopped? If that is true then the DMA_CERQ delay should not depend of used baudrate because DMA is not connected to uart shift-register so some kind of busy-wait loop could added because the delay "should be" small? What is the worst case delay between DMA_CERQ & DMA_ERQ visibility?

 

 

I don't also understand why CPU manual says that BITER-value must match CITER-value or configuration error is reported? Based on my experience that is not true. If you use DMA_CERQ to stop the DMA-channel, you do not need to do any CITER settings to continue with DMA_SERQ. After DMA_SERQ I  also use DMA_ERR-register to check if there is error present in channel and none is present even though the CITER seldom equals BITER because I have 400 byte long buffer.

 

So both methods in the function look to work equally (and yes, I am sure that in #else the CITER != BITER)

SetBufferReadingIndex()

{

#ifdef FULL_DMA_INIT

  DMA_DADDR( uart_rx_dma_ch ) = buffer;

  DMA_CITER_ELINKNO( uart_rx_dma_ch ) = DMA_BITER_ELINKNO( uart_rx_dma_ch );
  prevciter = DMA_CITER_ELINKNO( uart_rx_dma_ch );

  BufReadIndex = 0U; 

#else

  prevciter = DMA_CITER_ELINKNO( uart_rx_dma_ch );

  BufReadIndex = DMA_DADDR( uart_rx_dma_ch ) - (uint32)buffer;#endif

}

 

 

Is there somewhere available a proper description that how the DMA actually works because looks like that CPU manual has errors and also hides information... This is really time consuming trying to figure out cpu-functionality by trial and error!!! Maybe I have now figured out enough of the DMA functionality because code looks now ok and pretty bullet proof so maybe I don't need that information any more but someone else would need...

Outcomes