AnsweredAssumed Answered

DMA Callback is not beeing called

Question asked by jpb on Dec 14, 2009
Latest reply on Mar 2, 2010 by jpb

Hi,

 

I am using DMA to copy data between SPORT and local buffers. I am getting a problem, the DMA Callback (tdmInterfaceMDMACallback) is not beeing called after transfer.

I'm not expert with BF DMA configs, so it would be nice if someone could check my configurations below.

 

Regards,

João

 

Hardware: BF527

VDSP: 5.0 update 5

 

void TDMInterface::initMemoryDMABufferDescriptors()
{
    ADI_DMA_RESULT result;

 

    // Memory DMA Config Register default values
    ADI_DMA_CONFIG_REG defaultConfigReg;

 

    defaultConfigReg.b_WNR         = ADI_DMA_WNR_READ;              //1     Direction
    defaultConfigReg.b_WDSIZE     = ADI_DMA_WDSIZE_8BIT;          //2:3   Transfer word size
    defaultConfigReg.b_DMA2D     = ADI_DMA_DMA2D_LINEAR;          //4     DMA mode
    defaultConfigReg.b_RESTART     = ADI_DMA_RESTART_RETAIN;          //5     Retain FIFO
    defaultConfigReg.b_DI_SEL     = ADI_DMA_DI_SEL_OUTER_LOOP;      //6     Data interrupt timing select
    defaultConfigReg.b_DI_EN     = ADI_DMA_DI_EN_DISABLE;          //7     Data interrupt enabled
    defaultConfigReg.b_NDSIZE     = ADI_DMA_NDSIZE_LARGE;          //8:11  Flex descriptor size
    defaultConfigReg.b_FLOW     = ADI_DMA_FLOW_LARGE;            // Flow
    //.b_DMA_EN* ->  Data interrupt enabled (*only after SET_DATAFLOW to TRUE command be performed)

 

    // Temporary variable to receive Channel TDM Slot
    int currentChannelTDMSlot = 0;
    int channel = 0;

 

    // Setting default values for Large Buffers Descriptors
    for (channel; channel < numberOfChannels; channel++)
    {
        currentChannelTDMSlot = channelTDMSlot[channel];

 

        //===============================================================================
        // First correlated pair: TDM -> Channel transfers

 

        // Configuring SPORT Rx Buffer Descriptor
        sportRxBufferDescriptor[channel].pNext             = &(sportRxBufferDescriptor[channel+1]);      // next descriptor in the chain
        sportRxBufferDescriptor[channel].StartAddress    = &sport0RxBufferData[currentChannelTDMSlot]; // start address of the data (first Rx buffer)
        sportRxBufferDescriptor[channel].XCount            = DSP_NUMBER_OF_SAMPLES;                       // X (column) count
        sportRxBufferDescriptor[channel].XModify        = DSP_NUMBER_OF_CHANNELS;                      // X (column) stride
        sportRxBufferDescriptor[channel].YCount            = 1;                                          // Y (row) count (Doesn't matter for 1D transfers)
        sportRxBufferDescriptor[channel].YModify        = 1;                                              // Y (row) stride (Doesn't matter for 1D transfers)
        sportRxBufferDescriptor[channel].CallbackFlag   = 0;

 

        // Configuring SPORT Rx Buffer Descriptor: Config Register Structure
        sportRxBufferDescriptor[channel].Config = defaultConfigReg;

 

        // Configuring Channel TDM to IP Buffer Descriptor
        channelTDMToIPBufferDescriptor[channel].pNext             = &(channelTDMToIPBufferDescriptor[channel+1]); // next descriptor in the chain
        //.StartAddress -> start address of the data: it can only be set on run time, after local buffers be created
        channelTDMToIPBufferDescriptor[channel].XCount            = DSP_NUMBER_OF_SAMPLES;                           // X (column) count
        channelTDMToIPBufferDescriptor[channel].XModify            = 2;                                              // X (column) stride: 16 bits buffer cell size, but only 8 bits sample
        channelTDMToIPBufferDescriptor[channel].YCount            = 1;                                              // Y (row) count (Doesn't matter for 1D transfers)
        channelTDMToIPBufferDescriptor[channel].YModify            = 1;                                                  // Y (row) stride (Doesn't matter for 1D transfers)
        channelTDMToIPBufferDescriptor[channel].CallbackFlag       = 0;

 

        // Configuring Channel TDM to IP Buffer Descriptor: Config Register Structure
        channelTDMToIPBufferDescriptor[channel].Config = defaultConfigReg;
        channelTDMToIPBufferDescriptor[channel].Config.b_WNR = ADI_DMA_WNR_WRITE;
        channelTDMToIPBufferDescriptor[channel].Config.b_DI_EN = ADI_DMA_DI_EN_ENABLE;
        //===============================================================================

 


        //===============================================================================
        // Second correlated pair: Channel -> TDM transfers

 

        // Configuring Channel IP to TDM Buffer Descriptor
        channelIPToTDMBufferDescriptor[channel].pNext             = &(channelIPToTDMBufferDescriptor[channel+1]); // next descriptor in the chain
        channelIPToTDMBufferDescriptor[channel].StartAddress    = (void *)channelBufferAddress[channel];         // start address of the data (first Rx buffer)
        channelIPToTDMBufferDescriptor[channel].XCount            = DSP_NUMBER_OF_SAMPLES;                           // X (column) count
        channelIPToTDMBufferDescriptor[channel].XModify            = 2;                                              // X (column) stride: 16 bits buffer cell size, but only 8 bits sample
        channelIPToTDMBufferDescriptor[channel].YCount            = 1;                                              // Y (row) count (Doesn't matter for 1D transfers)
        channelIPToTDMBufferDescriptor[channel].YModify            = 1;                                                  // Y (row) stride (Doesn't matter for 1D transfers)
        channelIPToTDMBufferDescriptor[channel].CallbackFlag       = 0;

 

        // Configuring Channel TDM to IP Buffer Descriptor: Config Register Structure
        channelIPToTDMBufferDescriptor[channel].Config = defaultConfigReg;

 

        // Configuring SPORT Tx Buffer Descriptor
        sportTxBufferDescriptor[channel].pNext             = &(sportTxBufferDescriptor[channel+1]);      // next descriptor in the chain
        sportTxBufferDescriptor[channel].StartAddress    = &sport0TxBufferData[currentChannelTDMSlot]; // start address of the data (first Tx buffer)
        sportTxBufferDescriptor[channel].XCount            = DSP_NUMBER_OF_SAMPLES;                       // X (column) count
        sportTxBufferDescriptor[channel].XModify        = DSP_NUMBER_OF_CHANNELS;                      // X (column) stride
        sportTxBufferDescriptor[channel].YCount            = 1;                                          // Y (row) count (Doesn't matter for 1D transfers)
        sportTxBufferDescriptor[channel].YModify        = 1;                                              // Y (row) stride (Doesn't matter for 1D transfers)
        sportTxBufferDescriptor[channel].CallbackFlag   = 0;

 

        // Configuring SPORT Rx Buffer Descriptor: Config Register Structure
        sportTxBufferDescriptor[channel].Config = defaultConfigReg;
        sportTxBufferDescriptor[channel].Config.b_WNR = ADI_DMA_WNR_WRITE;
        sportTxBufferDescriptor[channel].Config.b_DI_EN = ADI_DMA_DI_EN_ENABLE;
        //===============================================================================
    }

 

    // Correcting last channel descriptors pNext parameter
    sportRxBufferDescriptor[channel - 1].pNext           = &(channelIPToTDMBufferDescriptor[0]); // Continue reading from ChannelIPToTDM Buffers
    channelTDMToIPBufferDescriptor[channel - 1].pNext = &(sportTxBufferDescriptor[0]);           // Continue writing to SPORT Tx Buffers

 

    channelIPToTDMBufferDescriptor[channel - 1].pNext = (ADI_DMA_DESCRIPTOR_LARGE *)NULL; // All buffers read
    sportTxBufferDescriptor[channel - 1].pNext           = (ADI_DMA_DESCRIPTOR_LARGE *)NULL; // All buffers write

 

    // Opening Memory DMA
    result = adi_dma_Open(dspManager->getDMAHandle(), ADI_DMA_MDMA_S1, (void *)0, &srcMemoryDMAHandle, ADI_DMA_MODE_DESCRIPTOR_LARGE, NULL, tdmInterfaceMDMACallback);
    if ( result != ADI_DMA_RESULT_SUCCESS) return; // TODO: Must log an error

 

    result = adi_dma_Open(dspManager->getDMAHandle(), ADI_DMA_MDMA_D1, (void *)0, &destMemoryDMAHandle, ADI_DMA_MODE_DESCRIPTOR_LARGE, NULL, tdmInterfaceMDMACallback);
    if ( result != ADI_DMA_RESULT_SUCCESS) return; // TODO: Must log an error
}

 

 

void TDMInterface::processBuffers()
{
    ADI_DMA_RESULT result

 

 

    // Creating Buffer of Samples received from TDM Network, to transmit them to the channels applications
    short * channelSamplesFromTDMBuffer;
    channelSamplesFromTDMBuffer = (short*) (new short[ numberOfChannels * DSP_NUMBER_OF_SAMPLES ]);

 

    // Loop to update DMA Descriptors start address
    for (int channelId = 0; channelId < numberOfChannels; channelId++)
    {
        // Updating DMA Descriptors start address according to current SPORT buffer filled: SPORT and Channels reception buffers
        sportRxBufferDescriptor[channelId].StartAddress = &sport0RxBufferData[channelTDMSlot[channelId] + sportBufferFilled*DSP_SPORT_BUFFER_MEMORY_SIZE/2];
        channelTDMToIPBufferDescriptor[channelId].StartAddress = (void *)channelSamplesFromTDMBuffer[channelId * DSP_NUMBER_OF_SAMPLES];

 

        // Updating DMA Descriptors start address according to current SPORT buffer filled: SPORT transmission buffers
        // channelIPToTDMBufferDescriptor doesn't need to be update because Channel IP to TDM Tx Buffer is a
        // static, and unique, buffer: it start address doesn't change on Run Time
        sportTxBufferDescriptor[channelId].StartAddress = &sport0TxBufferData[channelTDMSlot[channelId] + sportBufferFilled*DSP_SPORT_BUFFER_MEMORY_SIZE/2];

 

    }

 

  //=============================================================================================================
    // Starting Memory DMA operation

 

    // Queuing Descriptors
    result = adi_dma_Queue(srcMemoryDMAHandle, (ADI_DMA_DESCRIPTOR_HANDLE)&sportRxBufferDescriptor[0]);
    if ( result != ADI_DMA_RESULT_SUCCESS) return; // TODO: Must log an error

 

    result = adi_dma_Queue(destMemoryDMAHandle, (ADI_DMA_DESCRIPTOR_HANDLE)&channelTDMToIPBufferDescriptor[0]);
    if ( result != ADI_DMA_RESULT_SUCCESS) return; // TODO: Must log an error

 

    // Starting the DMA transfer (source side first)
    result = adi_dma_Control(srcMemoryDMAHandle, ADI_DMA_CMD_SET_DATAFLOW, (void *)TRUE);
    if ( result != ADI_DMA_RESULT_SUCCESS) return; // TODO: Must log an error

 

    // Starting the DMA transfer (destination side)
    result = adi_dma_Control(destMemoryDMAHandle, ADI_DMA_CMD_SET_DATAFLOW, (void *)TRUE);
    if ( result != ADI_DMA_RESULT_SUCCESS) return; // TODO: Must log an error
    //=============================================================================================================

 

    // Here TDM Interface wait Memory DMA concludes samples transfer
    BFWaitEvent(EVENT_TDM_INTERFACE_MEMORY_DMA_TRANSFER_COMPLETE);

}

Outcomes