AnsweredAssumed Answered

MQX: DMA Scatter/Gather

Question asked by acremonini on May 22, 2014
Latest reply on Jun 10, 2017 by Cory Frey

Hello,

we're working on a project on MQX 4.1 that uses DMA to acquire data from an ADC, periodically (every ~5µs) triggered by the PDB. We are using a k60 tower module.

We setup the DMA using the framework's functions as shown:

  

 

 

dma_channel_claim(&ADC_DMA_RX_channel, 0);      //associates DMA channel pointer with channel 0

dma_channel_setup(ADC_DMA_RX_channel, 2, DMA_CHANNEL_FLAG_LOOP_MODE); //the channel has two TCDs running in loop mode

dma_callback_reg(ADC_DMA_RX_channel,(DMA_EOT_CALLBACK)(my_CallBack),NULL); //association of the callback

dma_request_source(ADC_DMA_RX_channel, 40); //Association with ADC0 requests

 

dma_tcd_reg2mem(&adc_dma_tcd, &ADC0_RA, 2, testDMA,480); //creation of the TCD that moves data from ADCO_RA to an array

dma_transfer_submit(ADC_DMA_RX_channel, &adc_dma_tcd, my_tcd_seq_pointer); //the new TCD is the first one in the channel

dma_tcd_reg2mem(&adc_dma_tcd2, &ADC0_RA, 2, testDMA2,480);//creation of the TCD that moves data from ADCO_RA to a different array

dma_transfer_submit(ADC_DMA_RX_channel, &adc_dma_tcd2, my_tcd_seq_pointer); //the new TCD is the second one in the channel

 

dma_request_enable(ADC_DMA_RX_channel); //start of DMA requests

 

Our aim is to swing the transfer of data between the first array and the second one, so we can use the data in one array while we are filling the second one with DMA.

While the transfer of data seems to work properly, we're having some issues with the ISR: sometimes the callback receives tcds_done=2 and a tcd_seq increased by two in comparison with the previous call of the function, but we expect to have a callback for each completion of a TCD. Moving a GPIO up and down during the callback and checking the timing with the oscilloscope we verified that there's a callback at the end of every cycle as expected.

 

We tried to debug the code and we noticed that at the beginning of the ISR the code latches the content of the TCD registers and the DONE flag in CSR is '0' when an error occurs (the code uses that flag to calculate tcd_seq and tcds_done), while when the cycle runs smoothly DONE is '1'.

Moreover, we noticed that normally the DONE flag is '1', to indicate the last transfer is completed, but the DLASTSGA is already the new TCD's one. How can this be possible? We expected that the DONE flag and the DLASTSGA register belong to the same TCD.

The most strange thing we noticed is that the problem seems correlated to the ADC's frequency: if we slow down the triggering of PDB (we tried with 17µs) the problem disappears.

 

Do someone have an idea to help us?

Outcomes