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.

MSPM0G3507: Falling Edge Event Triggered ADC Using Single Repeat Mode Only Capturing On First Edge

Part Number: MSPM0G3507
Other Parts Discussed in Thread: SYSCONFIG

Hello,

I am trying to trigger both ADC channels on the falling edge of a 3V3 500kHz digital signal with 51 pulses in each burst, but only a single sample is converted per burst.

The 500kHz signal is going into an input GPIO pin which publishes an event upon the falling edge to a channel subscribed to by the ADC channels.

Both ADC channels are configured to be in Single Repeat mode, Trigger mode set to "Valid trigger will step..." (TRIG=1), and have set DMA to copy the output result into an array upon "MEM0 result loaded" interrupt.
The DMA is configured in Repeat Single mode with DestAddress Increment.

When I make ADC1 publish an event upon "MEM0 result loaded" to a channel subscribed to by an output GPIO which toggles upon an event trigger I get the correct number of toggle events, suggesting the ADC is indeed sampling for each pulse, but I only get one converted value per burst of 50 pulses copied into the output array by DMA.

Am I misunderstanding how the event triggering works?
Any help would be appreciated!

Thanks,

Alex

  • Hi Alex,

    What have you set your DMA transfer size to? I believe that if you have this set to 1, the DMA destination address will always reset to 1 after each transfer, but if you have it set to 50 (or 51?) then it will only reset the destination address after you've made this many transfers.

  • Hi Dylan,

    Thanks for the fast response!

    Yes, the DMA transfer size is set to 51 (set in the syscfg file as well as manually using dl_dma.h setTransferSize).

  • Could you post a screenshot of the sysconfig settings you are using for the DMA and for the ADC? I would like to compare them to the settings I have used in my own similar implementation.

  • Absolutely, I've posted the full ADC1 sysconfig in the three screenshots below.
    Event channel 12 is the channel published to by the 500kHz signal input.

  • Hi Alex,

    Can you try changing your DMA address mode to "Fixed addr. to Block addr."?

    I tried implementing this on my own and was able to get it working, so it is certainly possible. There are some other differences between ours but I believe the above is the reason you are having trouble. You may also want to change your transfer mode to single, as repeat single should cause multiple single conversions to occur after a single trigger. I also kept destination address increment set to unchanged.

    Please give these a try and let me know how it works for you. If not, I could always show you my example code to look further.

  • Hi Dylan,

    Unfortunately that hasn't worked for me either, I'm still getting only a single value added to the array per burst.

    Regarding the transfer mode, my understanding was that 'Repeat Single' simply left the DMA channel enabled but awaiting further triggers, is this not right?


    Glad to hear that you have something similar working on your board, thanks for confirming!
    If you are happy to share your example I would be very keen to have a deeper dig into what I've set up incorrectly.

  • I'll post images of my DMA configuration below, as well as my code. It is based on the adc_max_freq_dma example that we offer in the SDK.

    As for the transfer mode: I just went to check and verify by putting the device in repeat single mode, and gave it only one trigger by toggling a GPIO. The ADC still sampled 1024 times (the array size I am using) with only one trigger.

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include "ti_msp_dl_config.h"
    #define ADC_SAMPLE_SIZE (1024)
    /* When FIFO is enabled 2 samples are compacted in a single word */
    #define ADC_FIFO_SAMPLES (ADC_SAMPLE_SIZE >> 1)
    uint16_t gADCSamples[ADC_SAMPLE_SIZE];
    volatile bool gCheckADC;
    int main(void)
    {
    SYSCFG_DL_init();
    /* Configure DMA source, destination and size */
    DL_DMA_setSrcAddr(DMA, DMA_CH0_CHAN_ID,
    (uint32_t) DL_ADC12_getFIFOAddress(ADC12_0_INST));
    DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t) &gADCSamples[0]);
    DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, ADC_FIFO_SAMPLES);
    DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Please let me know if you have more questions or issues viewing the images. The Sysconfig tabs that aren't shown are left at their default values after adding the peripheral.

  • Thanks for your help Dylan!
    I'll see if I can find the problem, if not I'll try to create a simple example which demonstrates the issue I am encountering and post the code here (there is quite a bit going on in my code at the moment, for example i have a large DMA block transfer going on at the same time).

    I am quite surprised at the DMA transferring all 1024 ADC samples when the ADC DMA is in "Repeat Single" transfer mode, the documentation suggests that each DMA transfer should require a trigger:

    Am I misinterpreting the above or are these out of date docs?



  • Ah, I think I know why your ADC is taking more than one sample.
    If you left the "Trigger mode" default in ADC repeat mode it will continue to take samples continuously rather than waiting for the GPIO event to take each sample.
    This was discussed on the "original question" linked to this one, the Trigger mode sets the "TRIG" bit in the MEMCTL register, with 1 meaning a trigger is required for each sample and 0 (the default) only requiring the initial trigger)

  • I see what you mean about the trigger mode in optional configuration. However if I do leave all other settings the same, then change the trigger mode to "Valid trigger will step to next...", then I am sampling correctly on the falling edge of the 500kHz square wave rather than continuously at maximum speed. However, using the other setting for trigger mode, I still fill my buffer with data, it just fills as fast as the ADC can perform conversions, rather than on each falling edge. This leads me to believe that the problem is in your DMA configuration. 

    Does the example I provided work for your application/ were you able to solve your issue? Or does this not work for what you were trying to accomplish?

    As for your point about the datasheet, I think that the definition of repeat single sounds almost the same as the definition for single transfer. Logically speaking, I would not expect repeat single to require many triggers to repeat the transfer. I plan to consult my team about the wording used here versus the actual intended usage.

  • Happy new year Dylan.

    I agree that the issue seems to be in my DMA configuration, or my lack of understanding of how multiple DMA channels operating simultaneously function.
    Last year, after testing your example code, I started creating a simplified version of my code isolating the necessary components to get the effect I am seeing.

    When I have completed this I'll post it here.

  • Below is the simplified code I mentioned in my last message.
    I also have a non-fifo version which has the same issue if this would be of interest.

    PA12 is the 500kHz signal output pin, which I connect to the input pin PA17 as it is configures to emit an event to ADC0.
    I also connect the 3V3 pin to the ADC0 pin PA27 so that upon the breakpoint in my code I can see how many transfers into my array have occurred after a burst of 500 positive pulses on PA12/17.

    Please let me know if you need any further details.

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include "ti/devices/msp/m0p/mspm0g350x.h"
    #include "ti/driverlib/dl_dma.h"
    #include "ti_msp_dl_config.h"
    #define ADC_SAMPLE_SIZE (500)
    #define ADC_FIFO_SAMPLES (ADC_SAMPLE_SIZE >> 1)
    // Array to store ADC conversion data
    uint16_t gSenseA_output[ADC_SAMPLE_SIZE] = {0};
    // Array to store an output signal to DMA
    uint32_t gSignal[5000] = {0};
    volatile bool gDMAOutInterruptTaken = false;
    volatile bool gDMASenseADone = false;
    int main(void)
    {
    SYSCFG_DL_init();
    /* Setup interrupts on device */
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /**
    * These arguments were used when this file was generated. They will be automatically applied on subsequent loads
    * via the GUI or CLI. Run CLI with '--help' for additional information on how to override these arguments.
    * @cliArgs --device "MSPM0G350X" --package "LQFP-64(PM)" --part "Default" --product "mspm0_sdk@1.20.01.06"
    * @versions {"tool":"1.18.0+3266"}
    */
    /**
    * Import the modules used in this configuration.
    */
    const ADC12 = scripting.addModule("/ti/driverlib/ADC12", {}, false);
    const ADC121 = ADC12.addInstance();
    const Board = scripting.addModule("/ti/driverlib/Board");
    const DMA = scripting.addModule("/ti/driverlib/DMA");
    const GPIO = scripting.addModule("/ti/driverlib/GPIO", {}, false);
    const GPIO1 = GPIO.addInstance();
    const SYSCTL = scripting.addModule("/ti/driverlib/SYSCTL");
    const VREF = scripting.addModule("/ti/driverlib/VREF");
    /**
    * Write custom configuration values to the imported modules.
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Hi Alex,

    Could you explain why you are outputting a 500kHz wave from PA12 to PA17 to generate the event, instead of using a timer to generate the event? Or just an external source? An external source would allow you to cut out more and pinpoint your problem more easily.

    Can you explain your goal with using DL_GPIO_enableDMAAccess and DL_GPIO_enableOutput? I believe these are intended to be used for parallel output of DMA data. It also looks like the enable output function sets all of the pins on that port as outputs, so it seems like PA17 is being set as an output even though you're intending to use it as an input.

    What is triggering the DMA channel that you are using to output the 500kHz signal?

  • 1) Why output the 500khz wave from PA12 to PA17

    This is for two reasons, firstly I believe my application requires this as it is a small part of a more complex timing diagram which is being controlled by DMA and I was concerned part of the issue might have been DMA priority, also it was a convenient way to get a burst of a known number of pulses so that I could confirm a conversion per rising edge.

    I'll do some further investigation with external sources, but I would be interested if you knew of any DMA prioritisation/concurrent DMA issues?

    2) Purpose of GPIO_enableDMAAccess and GPIO_enableOutput

    The former seemed necessary for me to DMA transfer to the output pins in my application, so I've used it here, the latter is belts and braces to ensure PA12 is set as an output.

    The docstring for these functions suggest that the second argument is a mask determining which pins are effected by the function, and I am passing only PA12.

    Am I incorrect in thinking that these functions should therefore only impact PA12?

    3) What is triggering the output signal DMA channel

    This is software triggered with DL_DMA_startTransfer prior to the while(1) loop and after the while(gDMAOutInterruptTaken == false) loop.

  • So you are trying to use the output of the GPIO to control the timing for other components as well? There are no other issues that come to mind that would cause this behavior. To account for DMA prioritization, you could try making sure that the ADC samples are transferred with a full channel, and the waveform with a basic channel, to make sure that the transfer of ADC data gets the highest priority.

    I misread your function, you are right that the second argument is a mask. This should only impact PA12 as you mentioned.

    Have you already verified that the waveform coming from PA12 is correct? Additionally, have you tried using this example with only one DMA channel, and generating the waveform with an external source to check whether something in your waveform generating implementation isn't causing this? Alternatively, you could try starting with the example that I posted above and adding your waveform generating functionality to it.

  • "So you are trying to use the output of the GPIO to control the timing for other components as well" exactly right, I need the ADC conversions to occurr at a time determined by a GPIO being set by a DMA.

    "Have you already verified that the waveform coming from PA12 is correct", yes it seems to be correct on my scope.

    Thanks for your suggestions and for confirming the usage of the GPIO SDK functions, I'll look into using an external source, changing the DMA channel priorities in the next few working days.

  • Hi Dylan,
    After speaking with a colleague I think we have found the issue, DMA channels seem not to be able to operate in parallel (ie. if one DMA is performing a large block transfer then other DMA channels have to wait for the transfer to complete before they respond to a trigger) and are planning on taking a different approach.

  • Thanks for the update Alex. I will mark this thread as closed. Feel free to create a new thread if you have more difficulties.