KL26 DMA

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

KL26 DMA

706 Views
Richie_B
Contributor I

Hi,

I'm using a FRDM-KL26Z dev board with MCUXpresso IDE and SDK.  I'm trying to figure out how to set up the DMA to work with the ADC to continuously transfer samples into a pair of RAM buffers in standard "ping-pong" fashion.  (This is where DMA fills one buffer with ADC results whilst software processes data from the other buffer.  When the next buffer is filled, the software processes data in that second buffer and the DMA proceeds to over-write the first buffer with new ADC results.)

I have managed to get the DMA controller to fill one buffer (BUFFER_A) automatically with ADC results and then generate a transfer complete interrupt when the byte count reaches zero.  However, I cannot manage to make this event automatically start either the same or another DMA channel to begin filling the next buffer (BUFFER_B) with further ADC results.

I can do this manually in the DMA transfer complete interrupt service routines, and have had this working.  However, I think that it should be possible to implement this continuous ping-pong DMA of ADC results into two buffers in hardware, without software intervention.  The reason for this is that I have concerns that the DMA transfer complete interrupt service routine may not always get to execute quickly enough to re-configure or start a new DMA transfer before the ADC performs another sample.  Such a situation could result in loss of measurement data when the ADC sample-rate is high and/or the CPU instruction execution rate is low.

I believe that this common process of ping-pong DMA buffering should be possible by DMA channel linking to ensure that there is no data loss.  I have experimented with setting DMA channel 0 to chain to DMA channel 1 in an attempt to make the end of the DMA transfer of results into BUFFER_A trigger a new DMA transfer of new results into BUFFER_B.  However my attempts have so far been unsuccessful, and are best summarised by the posts of my colleague Gavin Lowes in this thread:

Solved: Re: KL26Z PIT, ADC, Two Channel DMA Ping-Pong Buff... - NXP Community

If DMA channel 1 is not enabled in advance, then the channel linking does nothing.  And when channel 1 is enabled, it only does a single transfer of the last ADC result to BUFFER_B when the transfer to BUFFER_A finishes.

The advice given in the thread posted above to re-write the DMA transfer descriptor in the DMA transaction complete interrupt handler (callback) is one solution, but it does rely on timely execution of the Interrupt Service Routine which can't be guaranteed in all situations.

After much experimenting with all of the different DMA configuration settings, and reading the application note about asynchronous DMA transfers below...

Using Asynchronous DMA features of Kinetis L Series (nxp.com)

...I have come to the conclusion that the DMA controller just doesn't work in a way that allows me to do what I want it to achieve?  Can someone please let me know if this is indeed the case?

In fact I have yet to even manage to make it perform a continuous DMA transfer of data into a single circular buffer.  (Something that would be an acceptable compromise if the double buffer ping-pong arrangement is not realisable on this device.)  I can invoke the modulo addressing functionality fine, but cannot make the transfer be continuous.  Despite trying both options for the D_REQ bit in the control register the DMA channel always seems to stop when the byte count remaining reaches zero!  The behaviour I was expecting was that data would be transferred continuously into the buffer with a DMA complete interrupt being issued every time the modulo addressing wrapped for the destination pointer, but this does not seem to be the case.  Is there an errata regarding DMA operation on this device that I should be aware of?  ...or an application note providing more information about the application of the DMA controller in these devices to common tasks like ping-pong buffering?

Any help or suggestions are much appreciated.

Best regards and thanks in advance,

-Richie,

0 Kudos
3 Replies

675 Views
Pavel_Hernandez
NXP TechSupport
NXP TechSupport

Hello Richie_B,

I will work on your case, give me a chance to review your case, when I have more information I will contact you.

Best regards,
Pavel

0 Kudos

646 Views
Pavel_Hernandez
NXP TechSupport
NXP TechSupport

Hello,

As you see in the other thread this can be achieved with additional configuration. The mechanism to achieve this without using the CPU is to use EDMA, but the KL26 MCU does not have it. If you want to use that function, you can try to use the K64 EVK board. The SDK has many examples for pin-pong or ring buffer.

Best regards,
Pavel

0 Kudos

527 Views
Richie_B
Contributor I

Hi Pavel,

Thanks for getting back to me.  It is a bit disappointing that this ping-pong functionality can't be achieved entirely in DMA hardware on the KL16 and KL26, however, it is not entirely unexpected.  It is also the conclusion that I had come to myself.

Since my project is heavily committed to the KL16/KL26 platform I have chosen to implement the ping-pong buffer functionality in software as follows:  Two DMA descriptor structs are prepared in advance...  One is for a block transfer from the ADC result register into a RAM buffer "A" and the other descriptor is for a block transfer from the ADC results register into the other RAM buffer "B".  These two pre-prepared DMA descriptors are alternately loaded into the DMA controller by the "DMA complete" callback (interrupt handler) so that blocks of ADC results are written to the two RAM buffers alternately.

I can get away with this for my current application as the sample-rate is quite low, and the DMA complete callback function is able to update the DMA channel with the new descriptor before the ADC performs the next sample.

Regarding the other question in my original post...

Do you have any information about how to use the D_REQ bit in the DMA_DCRn register to allow continuous (non-ending) transfers?  My understanding from reading the datasheet is that normally the byte count register BCR would decrement towards zero as the DMA transfer progresses, and when the BCR reaches zero, the transfer is stopped by the ERQ bit being cleared automatically when D_REQ is set?  It is then my understanding that if the D_REQ bit is clear the ERQ bit should not be automatically cleared when the byte count register BCR reaches zero, and DMA transfers should remain enabled as long as peripheral requests are generated?

Can you confirm if my understanding is correct because I seem to be seeing behaviour where the DMA channel always stops when BCR reaches zero, regardless of the D_REQ bit setting?

I noticed that the DMA drivers in the FRDM-KL26Z SDK v2.2.0 don't have any function for modifying the D_REQ bit for "non-ending" transfers so wondered if there is an issue with this functionality on KL26?

Many thanks for your assistance.

Best regards,

-Richie,

0 Kudos