DMA transfer to DAC in ping pong mode

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

DMA transfer to DAC in ping pong mode

829 Views
vayyalu
Contributor I

Hello there,

I am currently working on an application in which i am using the DMA to drive my DAC to create an analog signal. At low frequencies i am able to use the single transfer DMA and a call back function to reload the DMA. At higher frequencies there is a problem with the callback as they introduce a certain delay while making the subsequent DMA transfers.

I tried to use the ping pong buffer and the DMA values are not refreshed as i expected. I am using the following code and not sure what i am doing wrong in setting up the ping pong scheme for DMA. The software runs on a LPC845. Any suggestions please.

dma_descriptor_t nextDesc[2];
dma_channel_config_t dma_channel_config;
#define DAC_DATA_REG_ADDR 0x40014000
dma_handle_t DMA0_CH0_Handle;
#define DMA0_CH0_DMA_CHANNEL 22

void Start_DAC_1Khz_signal(void)
{
uint32_t numOftransferBytes = sizeof(g_waveform);

DMA_EnableChannel(DMA0_DMA_BASEADDR, DMA0_CH0_DMA_CHANNEL);

DMA_ALLOCATE_LINK_DESCRIPTORS(nextDesc,2);
DMA_SetupDescriptor(&nextDesc[0],
                       DMA_CHANNEL_XFER(1, 0, 0, 0, 4, kDMA_AddressInterleave4xWidth,                                                kDMA_AddressInterleave4xWidth, numOftransferBytes),
                (void *)g_waveform, (void *)DAC_DATA_REG_ADDR,&nextDesc[1]);

DMA_SetupDescriptor(&nextDesc[1],
                 DMA_CHANNEL_XFER(1, 0, 0, 0, 4, kDMA_AddressInterleave4xWidth,                                                 kDMA_AddressInterleave4xWidth, numOftransferBytes),
            (void *)g_waveform, (void *)DAC_DATA_REG_ADDR, &nextDesc[0]);
DMA_CreateHandle(&DMA0_CH0_Handle, DMA0_DMA_BASEADDR, DMA0_CH0_DMA_CHANNEL);
DMA_PrepareChannelTransfer(&dma_channel_config, (void *)g_waveform,                            

  (void *)DAC_DATA_REG_ADDR,
                     DMA_CHANNEL_XFER(1, 0, 0, 0, 4, kDMA_AddressInterleave4xWidth, kDMA_AddressInterleave4xWidth, numOftransferBytes),kDMA_MemoryToPeripheral,0,&nextDesc[0]);

DMA_SubmitChannelTransfer(&DMA0_CH0_Handle, &dma_channel_config);
DMA_StartTransfer(&DMA0_CH0_Handle);
}

const dac_config_t DAC0_config = {
.settlingTime = kDAC_SettlingTimeIs1us
};
#define DAC0_BUFFER_VALUE 1
#define DAC0_COUNTER_VALUE 234

static void DAC0_init(void) {
/* DAC0 initiation */
DAC_Init(DAC0_PERIPHERAL, &DAC0_config);
/* DAC0 double buffering enabled */
DAC_EnableDoubleBuffering(DAC0_PERIPHERAL, true);
/* DAC0 set buffer value */
DAC_SetBufferValue(DAC0_PERIPHERAL, DAC0_BUFFER_VALUE);
/* DAC0 set counter value */
DAC_SetCounterValue(DAC0_PERIPHERAL, DAC0_COUNTER_VALUE);
/* DAC0 DMA access enabled */
DAC_EnableDMA(DAC0_PERIPHERAL, true);
/* DAC0 enable counter */
DAC_EnableCounter(DAC0_PERIPHERAL, true);
}

int main()
{

DMA_Init(DMA0_DMA_BASEADDR);

/* Initialize components */

DAC0_init();
Start_DAC_1Khz_signal();
while(1){};

}

 

 

 

 

Labels (1)
0 Kudos
4 Replies

811 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

I think both the DAC and DMA code are correct.

In the SDK driver package, the DMA callback function is called in the DMA ISR, but the DMA ISR is too complicated and inefficient, which leads to the long delay of the DMA callback function.

I think you can try to modify the DMA ISR to shorten the delay.

Hope it can help you

BR

XiangJun Rong

 

 

0 Kudos

809 Views
vayyalu
Contributor I

I was under the impression that the DMA callback is required only if i do a single transfer and with ping pong buffer we can eliminate the DMA callback completely.

Please correct if my understanding is wrong.

 

0 Kudos

801 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

Obviously, whether the DMA callback function is required is totally dependent on your application. For your application, both descriptors do the same job to write the same buffer to DAC, I think the DMA call-back function is unnecessary.

BR

XiangJun Rong

 

0 Kudos

798 Views
vayyalu
Contributor I

Thanks.

Can you please review the fn. which sets up the ping pong buffer and see whether i have missed something in the setup?

Thanks again

0 Kudos