This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430F5438A DMA ping pong

Other Parts Discussed in Thread: MSP430F5438A

 

Hello!

 

I'd like to implement a kind of ping pong mode in the MSP430F5438A.
The reason for this is the fact that I need to do signal processing on a continuous data stream using ADC12+DMA.

I found no method to create a kind of ping pong / double buffering. There seems to be no "DMA Half finished interrupt", no chained DMA transfers, no special ping poing mode. The only possibility at all that I've found is to configure DMA in repeated single transfer mode but this would lead to very high timing constraints (very low interrupt latency of less than 1/samplingrate needed).

I would appreciate any hint.

 

Best regards,

 

Kai

  • Kai Gossner said:
    no chained DMA transfers

    Oh, there is. If one DMA sequence/single transfer is finished, it can trigger the next DMA channel.
    Yet I'm not sure whether using the 'DMA finished' signal as a DMA trigger will prevent it from being used as an IRQ trigger as well.

    And there is (at least on the 5438 with its 3-channel DMA) no ping-pong mode, only a ping-pong-peng mode, as DMA0 can trigger DMA1, but DMA1 can only trigger DMA2 and DMA2 triggers DMA0. But the first in the chain needs to be triggered by the ADC anyway.

    But what is the problem? You can trigger a DMA sequence by the ADCIFG and 64 MCLK cycles later (16 channels*4 MCLK cycles per DMA transfer) the data is copied, the DMA will trigger an IRQ and you han handle the stuff. Until the ADC has finished sampling the next sequence.
    But if you are unable to handle processing the data before the next set is ready, no DMA will help you. More than you can handle stays more than you can handle. Double-buffering makes things only worse. It only helps if you cannot handle the whole data before the first value of the sequence is overwritten again with a new result.
    And then, one DMA channel does the trick. The 16 differen ADC12MEM locations are doing sort of a sixteenuple-buffering for you already.

  • Jens-Michael Gross said:

    no chained DMA transfers

    Oh, there is. If one DMA sequence/single transfer is finished, it can trigger the next DMA channel.
    Yet I'm not sure whether using the 'DMA finished' signal as a DMA trigger will prevent it from being used as an IRQ trigger as well.

    And there is (at least on the 5438 with its 3-channel DMA) no ping-pong mode, only a ping-pong-peng mode, as DMA0 can trigger DMA1, but DMA1 can only trigger DMA2 and DMA2 triggers DMA0. But the first in the chain needs to be triggered by the ADC anyway.

    [/quote]

     

    OK:

    DMA0 is triggered and working synchrnous to ADC12IFG
    DMA1 is triggered by DMA0
    DMA2 is triggered by DMA1
    ...

    But you can only define one trigger. When using single transfer mode for ADC12 you need a trigger that is generated each time a sample is ready to be read. When defining for example for DMA1 DMA0 as trigger or for DMA2 DMA1... how does it know that it should work synchronous to ADC12IFG?

    Maybe I just misunderstand the concept... but I think you assume that i sample multiple channels.

     

    Jens-Michael Gross said:

    But what is the problem? You can trigger a DMA sequence by the ADCIFG and 64 MCLK cycles later (16 channels*4 MCLK cycles per DMA transfer) the data is copied, the DMA will trigger an IRQ and you han handle the stuff. Until the ADC has finished sampling the next sequence.
    But if you are unable to handle processing the data before the next set is ready, no DMA will help you. More than you can handle stays more than you can handle.

    My ADC is working synchronous to a timer. I don't sample multiple channels but only one. I would not be happy if already after 16 *4MCLK cycles later the DMA transfer would be finished...

    I sample only a single channel with a samplerate of 20 kHz.. I want to sample a continuous stream without any gaps.

     

    Jens-Michael Gross said:

    Double-buffering makes things only worse. It only helps if you cannot handle the whole data before the first value of the sequence is overwritten again with a new result.
    And then, one DMA channel does the trick. The 16 different ADC12MEM locations are doing sort of a sixteenuple-buffering for you already.

    In certain constellations you are of course right but I have to save power in my application. Ping Pong is absolutely not useless and can often not be avoided. I know the concepts and have used them very often. And as you write yourself:
    "It only helps if you cannot handle the whole data before the first value of the sequence is overwritten again with a new result". PingPong buffering relaxes realtime conditions extremely. Interrupt/wakeup/... latencies don't need to be in the order of a few ns/us to be able to handle certain tasks.

     

  • Kai Gossner said:
    Maybe I just misunderstand the concept... but I think you assume that i sample multiple channels.

    Yes. And you still can. There's no need to sample different channels on different ADC12MEM locations. You can set a sequence of sampling 16 times the same channel. And set up the ADC so it triggers the S&H based on the timer (therefore hardware-snychronizing each sampling to the timer). After a row of 16 channels has been sampled, the DMA is triggered and copies 16 values to the destination, triggers an IRQ and you have another 16 samples time to process the last 16 ones. It won't give you a continuous stream of data with equal gaps between but rather a burst of 16 samples, yet the samples itself are equidistant. They just arrive in a burst.

    Sampling the same channel to different MEM locations is only 1 ADCOSC cycle slower than sampling to the same ADC12MEM all the time. And since you already trigger the conversion by a timer, it makes no difference.

     

    Kai Gossner said:
    I have to save power
    Then the conversion sequence is even better: it reduces the overhead for waking up form LPM and calling the ISR to 1/16, while the time required for handling the data is the same whether you process 16* 1 sample each or 1*16 samples together. :)

  • Jens-Michael Gross said:

    It won't give you a continuous stream of data with equal gaps between but rather a burst of 16 samples, yet the samples itself are equidistant. They just arrive in a burst.

    But that's the point: I NEED equidistant samples also over multiple "blocks". Loosing samples in between is not an option.

     

    Jens-Michael Gross said:

    Sampling the same channel to different MEM locations is only 1 ADCOSC cycle slower than sampling to the same ADC12MEM all the time. And since you already trigger the conversion by a timer, it makes no difference.

     

    I have to save power

    Then the conversion sequence is even better: it reduces the overhead for waking up form LPM and calling the ISR to 1/16, while the time required for handling the data is the same whether you process 16* 1 sample each or 1*16 samples together. :)

    [/quote]

    OK, this should work, but 16 samples is a joke :-)

    Especially because my algorithm has to process data with block sizes of 128 samples. So I wake up (128/16-1) = 7 times and do effectively nothing.

    To resume: "real" Ping pong buffering is only possible with buffer sizes of up to 16 words. Correct? With real I mean ping pong buffering with relaxed realtime conditions, i.e. it is not needed to react fast on an interrupt to execute a new DMA transfer in software or similar actions.

    Other uCs don't have this nice 16 AD conversion memory locations but are able to execute DMA transfers on ADCs and generate an interrupt when DMA transfer size is zero or half of the initial value. Then you are able to wake up at a slower rate and you have a real ping pong buffer without any software overhead.

     

  • Kai Gossner said:
    I NEED equidistant samples

    Now you misunderstood me. These sample would be equidistant, yet delivered in packs of 16 by the DMA. But between the 16th and the 17th sample (when taken) would be the same distance than between any other.

    Kai Gossner said:
    OK, this should work, but 16 samples is a joke :-)

    Better than nothing. The other option, using a DMA for copying each single sample up to, say, 256 would require to immediately setting up the DMA again for the next set when the transfer has been finished.

    Another approach: since you are working synchronized to the timer, you can wake up at any moment, exactly knowing that now half of the samples have been captured. You don't really need a halfway DMA interrupt. With a littel bit of simple integer math, you can set up the next DMA channel to kick in, so they overlap by 50%, or maybe by 1 sample, depending on your setup.
    Your software can check at any time, how many samples have been transferred already.

    I agree that I'd like to have more and better DMA, more triggers and more complex trigger logic, yet it is better than nothing.

    Anyway, 20kHz isn't that much (the ADC can do 300kHz). You have to wakeup every 16*50us = 800us then to store away 16 samples into the larger processing buffer. And if using two buffers here, you have an eternity to do the processing.

    Of course, every bit processing time does cost some energy, yet you cannot have everything: unlimited processing power at no energy usage. The optimum is somewhere in between.

  •  

    One question: Is it possible to select as destination adress for a DMA channel a register, like for example DMA1CTL?

    If this is the case a ping pong buffering without any SW overhead and with sample sizes > 16 should be possible.

     

  • According to the the 54xx errata sheet, DMA cannot write to DMA registers (DMA6 erratum). Any other register is fine.
    The 54xxA errata list does not have this erratum anymore. Maybe this has been fixed, maybe it just has been forgotten.

    What did you have in mind?

  • Hi Jens!

    You wrote that here:

    Jens-Michael Gross said:

    Maybe I just misunderstand the concept... but I think you assume that i sample multiple channels.

    Yes. And you still can. There's no need to sample different channels on different ADC12MEM locations. You can set a sequence of sampling 16 times the same channel. And set up the ADC so it triggers the S&H based on the timer (therefore hardware-snychronizing each sampling to the timer). After a row of 16 channels has been sampled, the DMA is triggered and copies 16 values to the destination, triggers an IRQ and you have another 16 samples time to process the last 16 ones. It won't give you a continuous stream of data with equal gaps between but rather a burst of 16 samples, yet the samples itself are equidistant. They just arrive in a burst.

    [/quote]

     

    According to the manual there is a DMA Trigger called ADC12IFGx. This ADC12IFGx triggers on ANY of the interrupts flags ADC12IFG0 - 15. Theese interrupts flags are set when the corresponding ADC12MEMx register was set.

    That means a DMA transfer will be triggered each time a sample is written to any of the ADC1MEM registers.
    I'd like to execute a Burst DMA transfer AFTER 16 samples have been sampled. and not a single transfer after each sample.

    From your comment above I undestand that this should be possible. ("After a row of 16 channels has been sampled, the DMA is triggered and copies 16 values to the destination").

    But how?

     

    Best regards,

    Kai

  •  

    1.) setup ADC12 to convert a single channel repeatedly, synchronous to a timer (sampling clock generator)

    2.) setup DMA0 to single transfer mode with a transfers size of 128 samples. Trigger = ADC12IFGx

    3.) setup DMA1 to single transfer to copy a complete set of new register contents from somewhere in memory to the whole set of DMA registers. Trigger = DMA0. This function also triggers an interrupt. The RAM shadow of the DMA registers are configured in a way that DMA0 is started again and the destination adress of the transfers always points to the other sampling buffer.

     

    The interrupt function processes the sample buffer and changes the ram-shadow of the DMA registers to the "Pong" buffer (or "Ping" in next sequence).

    OK, I wrote 0 software overhead but the "additional" software overhead is just a single write to a ram adress to change the next DMA destination adress.

     

    But: Instead of using ADC12 with a single channel I would like to use it in the mode you described, e.g. triggering DMA in burst mode after 16 conversions have been done. Can you have a look at the previous mail?

     

  • Kai Gossner said:

    But: Instead of using ADC12 with a single channel I would like to use it in the mode you described, e.g. triggering DMA in burst mode after 16 conversions have been done. Can you have a look at the previous mail?

     

    WAIT, i found a small note in chapter 19.2.10:

    "The DMA is triggered [...] after the completion of a sequence of channel conversions in sequence-of-channels conversion mode.

    It is not written exactly what "completion" means in this relation, especially in repeated sequence-of-channels mode, but I assume that this is when the "End of conversion" flag is set for a certain conversion result configuration register, right?

     

  • Kai Gossner said:
    This ADC12IFGx triggers on ANY of the interrupts flags ADC12IFG0 - 15

    Yes, any, but not all and always. :) If a sequence mode is selected, it will trigger on the channel that has the end-of-sequence bit set.
    In single-conversion mode, any of the channels (as there is only one at a time) will trigger it.

    I'm not really happy with the limited selection of DMA triggers, yet at least there has been some thought upone the few that are available.

    From the users guide, chapter 17.2.10: "The DMA is triggered after the conversion in single-channel conversion mode or after the completion of a sequence of channel conversions in sequence-of-channels conversion mode"

    Kai Gossner said:
    setup DMA1 to single transfer to copy a complete set of new register contents from somewhere in memory to the whole set of DMA registers. Trigger = DMA0.

    Well, teh errata sheet of the A-series does not list the erratum abotu being unable to writ ethe DMA registers per DMA anymore, so it could work. The non-A series is unable to do it.

    With the sequence mode, it would rather be

    DMA0: copy sequence
    DMA1 restart DMA0 (increment the destination start address) for some times (until enough has been collected)
    DMA2, reporgram/reset the whole and trigger ISR

    But maybe just copying the sequence is DMA enough. :)

    I'd really love to have more triggers, including two triggers for the DMA: one to start a DMA sequence, another one to preceed inside the sequence. And some more DMA channels :)
    Having different 'chunk' and 'total size' settings for the data to be transfered would be nice too, so you can say, copy 16 bytes on each trigger, but 256 in total (sequence of sequences) before returning to the original source and/or destination start addresses. And a 'trigger IRQ at count x' would be nice too.

**Attention** This is a public forum