This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C129ENCPDT: DMA interrupt - How to determine how many packets were received? (burst or single trasmission?)

Part Number: TM4C129ENCPDT

Hello, I'm running the TIVA dma_example (ping pong uart receive) and I want to know how many bytes were transfered when I receive the DMA interrupt. I need to know if it's a single or burst transfer, in order to process the DMA data buffers A and B.

In the TIVA dma code example interrupt handler:

//*****************************************************************************
//
// The interrupt handler for UART1. This interrupt will occur when a DMA
// transfer is complete using the UART1 uDMA channel. It will also be
// triggered if the peripheral signals an error. This interrupt handler will
// switch between receive ping-pong buffers A and B. It will also restart a TX
// uDMA transfer if the prior transfer is complete. This will keep the UART
// running continuously (looping TX data back to RX).
//
//*****************************************************************************
void
UART1IntHandler(void)
{
uint32_t ui32Status;
uint32_t ui32Mode;

//
// Read the interrupt status of the UART.
//
ui32Status = ROM_UARTIntStatus(UART1_BASE, 1);

//
// Clear any pending status, even though there should be none since no UART
// interrupts were enabled. If UART error interrupts were enabled, then
// those interrupts could occur here and should be handled. Since uDMA is
// used for both the RX and TX, then neither of those interrupts should be
// enabled.
//
ROM_UARTIntClear(UART1_BASE, ui32Status);

//
// Check the DMA control table to see if the ping-pong "A" transfer is
// complete. The "A" transfer uses receive buffer "A", and the primary
// control structure.
//
ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_UART1RX | UDMA_PRI_SELECT);

//
// If the primary control structure indicates stop, that means the "A"
// receive buffer is done. The uDMA controller should still be receiving
// data into the "B" buffer.
//
if(ui32Mode == UDMA_MODE_STOP)
{
//
// Increment a counter to indicate data was received into buffer A. In
// a real application this would be used to signal the main thread that
// data was received so the main thread can process the data.
//
g_ui32RxBufACount++;

// I don't know if the data is single or burst...

//
// Set up the next transfer for the "A" buffer, using the primary
// control structure. When the ongoing receive into the "B" buffer is
// done, the uDMA controller will switch back to this one. This
// example re-uses buffer A, but a more sophisticated application could
// use a rotating set of buffers to increase the amount of time that
// the main thread has to process the data in the buffer before it is
// reused.
//
ROM_uDMAChannelTransferSet(UDMA_CHANNEL_UART1RX | UDMA_PRI_SELECT,
UDMA_MODE_PINGPONG,
(void *)(UART1_BASE + UART_O_DR),
g_ui8RxBufA, sizeof(g_ui8RxBufA));
}

//
// Check the DMA control table to see if the ping-pong "B" transfer is
// complete. The "B" transfer uses receive buffer "B", and the alternate
// control structure.
//
ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_UART1RX | UDMA_ALT_SELECT);

//
// If the alternate control structure indicates stop, that means the "B"
// receive buffer is done. The uDMA controller should still be receiving
// data into the "A" buffer.
//
if(ui32Mode == UDMA_MODE_STOP)
{
//
// Increment a counter to indicate data was received into buffer A. In
// a real application this would be used to signal the main thread that
// data was received so the main thread can process the data.
//
g_ui32RxBufBCount++;

//
// Set up the next transfer for the "B" buffer, using the alternate
// control structure. When the ongoing receive into the "A" buffer is
// done, the uDMA controller will switch back to this one. This
// example re-uses buffer B, but a more sophisticated application could
// use a rotating set of buffers to increase the amount of time that
// the main thread has to process the data in the buffer before it is
// reused.
//
ROM_uDMAChannelTransferSet(UDMA_CHANNEL_UART1RX | UDMA_ALT_SELECT,
UDMA_MODE_PINGPONG,
(void *)(UART1_BASE + UART_O_DR),
g_ui8RxBufB, sizeof(g_ui8RxBufB));
}

//
// If the UART1 DMA TX channel is disabled, that means the TX DMA transfer
// is done.
//
if(!ROM_uDMAChannelIsEnabled(UDMA_CHANNEL_UART1TX))
{
//
// Start another DMA transfer to UART1 TX.
//
ROM_uDMAChannelTransferSet(UDMA_CHANNEL_UART1TX | UDMA_PRI_SELECT,
UDMA_MODE_BASIC, g_ui8TxBuf,
(void *)(UART1_BASE + UART_O_DR),
sizeof(g_ui8TxBuf));

//
// The uDMA TX channel must be re-enabled.
//
ROM_uDMAChannelEnable(UDMA_CHANNEL_UART1TX);
}
}

On the datasheet:

Request Types
The μDMA controller responds to two types of requests from a peripheral: single or burst. Each
peripheral may support either or both types of requests. A single request means that the peripheral
is ready to transfer one item, while a burst request means that the peripheral is ready to transfer
multiple items.
The μDMA controller responds differently depending on whether the peripheral is making a single
request or a burst request. If both are asserted, and the μDMA channel has been set up for a burst
transfer, then the burst request takes precedence.

Datasheet page 708:

Note: In this example, it is not important if the peripheral makes a single request or a burst request. - but for me it's important!
Because the peripheral has a FIFO that triggers at a level of 8, the arbitration size is set to
8. If the peripheral does make a burst request, then 8 bytes are transferred, which is what
the FIFO can accommodate. If the peripheral makes a single request (if there is any data
in the FIFO), then one byte is transferred at a time. If it is important to the application that
transfers only be made in bursts, then the Channel Useburst SET[8] bit should be set in
the DMA Channel Useburst Set (DMAUSEBURSTSET) register.

I thought about pooling the XFERSIZE (transfer size) register, but it seems that it contains the outstanding items necessary to complete the DMA cycle (should be zero when the interrupt triggers). So it doesn't help me.

Thank you in advance.

  • Hi Matheus,
    If you look at the example inside the InitUART1Transfer() the FIFO level threshold is set to 4 meaning that when the RXFIFO contains 4 bytes of data it will send a DMA request to the DMA module. Responding to the DMA request, the DMA will read the 4 bytes of data in the RXFIFO. When the transfer is complete the UART module will send a RXDMA interrupt to the CPU.

    //
    // Set both the TX and RX trigger thresholds to 4. This will be used by
    // the uDMA controller to signal when more data should be transferred. The
    // uDMA TX and RX channels will be configured so that it can transfer 4
    // bytes in a burst when the UART is ready to transfer more data.
    //
    ROM_UARTFIFOLevelSet(UART1_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);
  • Hi Charles, when the uart fifo receive only one byte, it also generates a dma request (and a dma interrupt after this one byte transfer). When I receive this interrupt, I need a way to know if the uart request was a single transfer dma request (one byte transfer) or a burst transfer dma request (4 bytes as you said in your reply).
  • Hi Matheus,

      In the case of the example, when you receive an interrupt then it must mean that the DMA has transferred 4 bytes of data and it must have responded to a burst request. You need to make sure the DMA arbitration size is configured to the same number as the UART FIFO level. Let's say you are expecting to receive 80 bytes of data into UART FIFO. You can setup FIFO trigger level to be 1/4 of the FIFO meaning whenever there are 4 or more bytes of data in the FIFO it will generate a burst request. In the DMA you have also setup the channel with a arbitration size of 4. Responding to a burst request it will always read 4 bytes out of the UART RXFIFO. I don't think the UART will ever assert a single request in this case since you have configured the UART in FIFO mode. It will take the UART 20 times to generate DMA request to the DMA module to complete the 80 bytes of transfer. You must not have a non matching arbitration size with respect to the UART FIFO trigger level. For example, if you have a total of 81 bytes to transfer. In this case, there will be one byte remaining in FIFO after 80 bytes are transferred. I think there are two possible outcomes. One is that the UART will not generate a DMA request since you are in FIFO mode and your trigger level is 4 bytes. The UART FIFO will wait for 3 more bytes to arrive before sending a DMA request. This is the most likely scenario in my opinion. The second scenario is that the UART sends a single request for this one-byte data. I really doubt this will happen. If the request is sent to the DMA and IF you still have the DMA configured with the arbitration size of 4 bytes then the DMA is going to read 4 bytes from the FIFO which will produce a underrun situation unless you have earlier reconfigured the DMA with a one byte arbitration size. 

  • Hi,

    Datasheet page 1295:

    DMA Operation
    The UART provides an interface to the μDMA controller with separate channels for transmit and
    receive. The DMA operation of the UART is enabled through the UART DMA Control
    (UARTDMACTL) register. When DMA operation is enabled, the UART asserts a DMA request on
    the receive or transmit channel when the associated FIFO can transfer data. For the receive channel,
    a single transfer request is asserted whenever any data is in the receive FIFO. A burst transfer
    request is asserted whenever the amount of data in the receive FIFO is at or above the FIFO trigger
    level configured in the UARTIFLS register.

    According to this section the UART sends a dma request for a single byte too. I need to know if the dma request was a single or burst one, in order to process data.

  • Hi,
    That can only happen when you are in non FIFO mode. If in FIFO mode and if the UART generates single transfer request whenever there is any data is in the receive FIFO, then it makes the FIFO level select (i.e. 1/8, 1/4, 1/2, etc) useless, isn't? The reason is that you will always have at least one data in the FIFO whenever you receive one data from the UART RX pin. The DMA will never work with any arbitration size unless it is configured to arbitration size of 1 or otherwise the DMA is going to read more than what is available int he UART RXFIFO.