MSPM0G3507: Setting Up ADC DMA - Interrupts ?

Part Number: MSPM0G3507
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

Hello.

Trying to DMA from ADC to SPI...I want to DMA 64 conversions one go at a time....does not seem to start.

I have setup below..see snip.

Yet again (from previous thread) I am confused by the interrupt term for DMA...

The DMA trigger is the first conversion into MEM0.."MEM0 result loaded interrupt".....but I do not want an interrupt to occur !?

Thanks

Phil

  • Similar to the other thread, the "interrupt" registers are best viewed as a routing mechanism. Here again, the DMA_TRIG set has a subset of the bits.

    I'm supposing you want to sample a single channel (at least) 64 times, and have the DMA capture them into an array. So you want

    1) transfer mode "Single",

    2) "Fixed->Block",

    3) length (for both) Word (32-bit),

    4) source:non-increment, destination:increment,

    5) transfer size 64 (items).

    6) "DMA Samples Count" applies to FIFO usage, so set it to =1 [Ref TRM Sec 12.2.12.3].

    Sysconfig won't declare your result array (the "Block" above), so you'll need to call DL_DMA_setDestAddr(DMA,2, &sample_array[0]); in your code.

    It seems as though you should have got one sample, though; how is "Sampling Mode ->Trigger Source" set?

  • Hi thanks for reply....

    I want to transfer from ADC to SPI via DMA...

    So I have set everything up via sysconfig and in addition also also have:

    DL_DMA_setDestAddr(DMA,DMA_CH2_CHAN_ID, (uint32_t) (&SPI_0_INST->TXDATA));
    The ADC is triggered by an external event of a GPIO...looks OK.
    I am a little confused on widths here:
    1. I think the ADC width is two bytes
    2. SPI width is sixteen bits
    Not sure if mapping from ADC to SPI is working for DMA.
    --
    Phil
  • The ADC (MEMRES) registers are 32-bit, even though only 16 bits are defined; reading them as 32 bits keeps the address increments right (I suppose you could use STRIDE_2 instead).

    I'm pretty sure you can fetch (source) a 32-bit word and store (destination) it as a 16-bit halfword (truncated to low-half).

    I can't think of a reason DMA ADC[MEMRES]->SPI[TXDATA] wouldn't succeed, assuming you've worked out the timing.

  • Thanks...still can't get DMA to start..my plan is to DMA to SPI but for now trying to an array....

    I setup the DMA in sys cfg...see snip.

    The odd thing is that DMA source address is zero (see register)...do I have to explicitly set this in code ?

    If so...for ADC0..what is the address of memres0 ?? (I can't find it)

    DL_DMA_setDestAddr(DMA,DMA_CH1_CHAN_ID, (uint32_t) buffer);
    DL_DMA_setSrcAddr(DMA, DMA_CH1_CHAN_ID, (uint32_t) ????);
  • Try:

    > DL_DMA_setSrcAddr(DMA, DMA_CH1_CHAN_ID, DL_ADC12_getMemResultAddress(ADC0, DL_ADC12_MEM_IDX_0));

  • Thanks...still can't get DMA to start....some more detail:

    I am triggering the ADC conversion from an external event.

    And the idea is that DMA will then happen when memres0 is written.

    Any conflict doing both of these ???

  • I don't know of any conflict. Are you fairly certain the ADC is running? Do you see MEMRES0 change?

  • Hello, thanks.

    If I turn off the DMA and enable an ADC interrupt, I can see a counter increment:

    void ADC12_0_INST_IRQHandler(void)
    {
    adc_count++;
    }
    This can, of course, only happen if my trigger is functioning...(from a GPIO event).
    BUT count only ever gets to one, despite having sixty four triggers..
    I have set the ADC as in snip below.
    For trigger mode (marked in pink)...does it matter what I use since I only have a single memres ?
    Thanks
    Phil
  • It sounds like you haven't set the "Enable Repeat Mode" check-box. The trigger mode matters for Repeated+Single and you want the "Valid Trigger will step.." option you chose [Ref TRM Sec 12.2.10].

  • Hello, thanks yes that fixed it.

    The DMA is working but is terminating early  - doing sixteen transactions as opposed to sixty four..

    I have the ADC DMA on CH1:

    What is the difference between these two ?

    DL_DMA_enableChannel(DMA, DMA_CH1_CHAN_ID);
    DL_ADC12_enableDMA(ADC12_0_INST);
    Do I need both ?
    Regards
    Phil
  • DL_ADC12_enableDMA() allows the ADC12 to issue DMA requests (to the DMA channel) [CTL2:DMAEN]. 

    DL_DMA_enableChannel() allows the DMA channel to run, i.e. to accept DMA requests [DMACTL:DMAEN].

    How do you tell there were only 16 transactions? [DMASZ vs scope trace from POCI?]

    Are you still running the DMA from the ADC12 [MEMRES] directly to the SPI [TXDATA], or are you using an intermediate buffer? If it's the former, FIFO overruns seem possible if you don't get the timing just right.

  • Understood thanks.

    If I look on a logic analyser I can see that (I toggle a pin on each DMA)

    while((DL_DMA_isChannelEnabled(DMA,DMA_CH1_CHAN_ID)==true))
    ;
    waits for seven DMAs and then exits.
    My understanding is that in this mode, once the DMAs have finished the channel is disabled...below is ADC0 DMA (memres0) to SPI TX
  • In addition...if I set the size and then set breakpoint the DMA_DMASZ is not set ????

  • In fact can't seem to enable it either ??? Going nuts..

  • Set the transfer size before enabling the channel. 

    1) Enabling a channel with DMASZ==0 causes it to complete immediately. (I think that's what you're observing above.)

    2) I suspect DMASZ (as well as the others) is read-only while the channel is enabled. [The other day I tried to find this stated in the TRM, but didn't. This is based on the similarity with the MSP430 DMA.]

    How are you toggling a pin on each transfer? I still wonder whether you're overrunning the (SPI) FIFO.

  • Thanks...I may give up on the DMA ADC to SPI directly...too many problems for me.

    I wanted speed but may have to do DMA ADC to buffer then DMA buffer to SPI..

  • Depending on where the DMA trigger originates, the flow control either comes from

    a) The Tx FIFO (space available) or

    b) The ADC (data is ready)

    but not both.

    At some point the Master ends up in the position of micro-managing the flow control remotely through the GPIO trigger and paced SPI (request) frames. With an intermediate (speed-matching) buffer it can just wiggle the GPIO 64 times then read the results in a burst.

    I (personally) would pay the 128B just so I wouldn't have to worry about it.

  • Thanks again...picture below is trying to explain what I am trying to do....

    CCK is replicated from MOSI by events (pos edge and neg edge) to drive part of my system (I can't use physical mux for various reasons).

  • When the DMA stops, is DMASZ==0? This would distinguish whether it's the DMA or the ADC (or other) that's stalling.

    It looks like you've computed the (ADC vs MOSI) timing, and it "should" work. One experiment would be to slow down the SPI (SCK), to see if you're cutting it too close [I've seen systems where an ADC acts up if it's triggered while it's busy].

  • Hi Phil,

    In fact can't seem to enable it either ??? Going nuts..

    DMA has temporary register for its channel configuration when enable repeat mode:

    And, SPI only has four FIFO entry, using MOSI to trigger ADC might cause the SPI FIFO overflow and lose data randomly.

    To check whether DMA done, maybe you can check ADC interrupt register .RIS, and see whether DMA done is asserted.

    B.R.

    Sal