Post Go back to editing

UART - DMA Descriptor Mode Ping Pong Buffer

Category: Software
Product Number: ADSP-21565

Hi,

I work with the ADSP21565 and I want to implement a UART communication based on DMA with descriptor list mode with ping pong buffering (2 buffers for RX and 2 for TX).

I can't find any example for it, all I can find is an example with a single buffer.

Is there any example? as I don't think changing the DMA_NUM_DESC macro to 2 is enough.

Thanks,

Sagi.

Edit Notes

.
[edited by: SagiS at 2:50 PM (GMT -4) on 20 Oct 2025]
  • Hi Sagi,

    Did you get a chance to look into the UART example available in the ADSP-21569 BSP? This example demonstrates transfer of data in DMA mode between different UART's. Please enable the "LISTDESCRIPTOR_DMA_MODE" and check whether this example helps.

    Please download and install the ADSP-2156x Board support package can be downloaded from the below mentioned link.
    download.analog.com/.../ADI_EV-2156x_EZ-KIT-Rel3.0.0.exe

    Once installed, the UART DMA example can be available in the below installation path.
    [Installation directory]:\Analog Devices\EV-2156x_EZ-KIT-Rel3.0.0\EV-2156x_EZ-KIT\Examples\drivers\uart

    Regards,
    Nandini C

  • Hi Nandini,

    I tried to work with the example you've mentioned while trying to receive continues stream of packets from the PC.

    I get only 2 packets (UART RX event in the callback is called only twice).

    This is how I config the UART:

    #define DMA_NUM_DESC 2u
    #define DMA_MSIZE_IN_BYTES 1u

    #pragma section("seg_l2_dmda_bw")
    ADI_CACHE_ALIGN uint8_t SrcData[DMA_NUM_DESC][ADI_CACHE_ROUND_UP_SIZE(UART_DEBUG_BUFFER_LINE_SIZE, uint8_t)];
    #pragma section("seg_l2_dmda_bw")
    ADI_CACHE_ALIGN uint8_t DestData[DMA_NUM_DESC][ADI_CACHE_ROUND_UP_SIZE(UART_DEBUG_BUFFER_LINE_SIZE, uint8_t)];
    #pragma section("seg_l2_dmda_bw")
    ADI_CACHE_ALIGN ADI_PDMA_DESC_LIST Uart_Src_List[DMA_NUM_DESC];
    #pragma section("seg_l2_dmda_bw")
    ADI_CACHE_ALIGN ADI_PDMA_DESC_LIST Uart_Dest_List[DMA_NUM_DESC];

    int32_t Init_UART()
    {
    ADI_UART_RESULT eResult;

    /* Open UART */
    eResult = adi_uart_Open(ADI_UART_1, ADI_UART_DIR_BIDIRECTION, UARTDev0, ADI_UART_BIDIR_MEMORY_SIZE, &hDev0);

    /* Configure UART baud rate */
    eResult = adi_uart_ConfigBaudRate(hDev0, UART_Edb0, UART_BAUD_RATE_Divisor);

    /* Register UART Callback function for DMA mode */
    eResult = adi_uart_RegisterCallback(hDev0, Callback, NULL);

    /* Prepare descriptors for memory copy using List mode */
    PrepareDescriptors();

    eResult = adi_uart_DMARead(hDev0, Uart_Dest_List, DMA_NUM_DESC, ADI_PDMA_DESCRIPTOR_LIST);

    return eResult;
    }

    static void PrepareDescriptors (void)
    {
    /* Loop variable */
    uint32_t i;

    /* Populate List descriptor instances for UART DMA transfer */
    for (i = 0u; i < DMA_NUM_DESC; i++)
    {
    /* Buffer Start Address */
    Uart_Src_List[i].pStartAddr = &SrcData[i][0];
    /* DMA Config - only specify memory transfer size */
    Uart_Src_List[i].XCount = (UART_DEBUG_BUFFER_LINE_SIZE/DMA_MSIZE_IN_BYTES);
    Uart_Src_List[i].XModify = DMA_MSIZE_IN_BYTES;
    Uart_Src_List[i].Config = ENUM_DMA_CFG_XCNT_INT;

    /* Buffer Start Address */
    Uart_Dest_List[i].pStartAddr = &DestData[i][0];
    /* DMA Config - only specify memory transfer size */
    Uart_Dest_List[i].XCount = (UART_DEBUG_BUFFER_LINE_SIZE/DMA_MSIZE_IN_BYTES);
    Uart_Dest_List[i].XModify = DMA_MSIZE_IN_BYTES;
    Uart_Dest_List[i].Config = ENUM_DMA_CFG_XCNT_INT;

    /* if it is an end of the list */
    if (i >= (DMA_NUM_DESC-1u))
    {
    Uart_Src_List[i].pNxtDscp = NULL;
    Uart_Dest_List[i].pNxtDscp = NULL;
    }
    /* if it is not an end of the list */
    else
    {
    Uart_Src_List[i].pNxtDscp = &Uart_Src_List[i+1];
    Uart_Dest_List[i].pNxtDscp = &Uart_Dest_List[i+1];
    }

    }
    }

    Why is it happening? how can I get a continues stream of packets from the PC via UART DMA?

    Thanks,

    Sagi

  • Hi Sagi,

    You are configured the number of descriptors as 2 and in the "Uart_Dest_List" descriptor provided as NULL for the next descriptor. So, it receives only 2 packets.

    To receive continues stream of packets, you have to create four descriptors, 2 for source and 2 for destination like ping pong mechanism. This buffering mechanism allows to access one buffer while the DMA is filling/sending out another in the pair. This can be taken care by the “flag” variable to decide which buffer will be accessed at an instant.

    Please refer the “Audio_Passthrough” examples available in the BSP package, which utilizes this technique to receive the data from one buffer from ADC for processing, while it is transmitting the other data already processed through another buffer to the DAC.

    The example code can be found in the path given below:
    <installation path>\EV-2156x_EZ-KIT-Rel3.0.0\EV-2156x_EZ-KIT\Examples\drivers\adc

    Please use the DMA descriptor configuration from this example as a reference and modify your code accordingly.

    Regards,
    Nandini C