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.

3-Phase D/A updates using uDMA

I am using a TM4C1294XL Launchpad board connected to a 12-bit serial D/A device (DAC124SO85) to generate 3-phase excitation signals for a small instrumentation motor. D/A data source comes from a memory buffer of several K-bytes built in groups of three 16-bit words, where each word contains the exact SSI data being sent to the D/A including the D/A channel number, update mode, and LUT data. I have it working using uDMA in basic mode transferring three 16-bit words at a time via a timer trigger. The problem is that the DMA interrupts the processor after every group of three words and I would rather not burden the processor this way. I am not seeing how to have the uDMA transfer only 3-words of data for every timer trigger, stop, and only interrupt after the complete buffer data is sent. In other words, I see only a buffer size for uDMA in burst mode, not a buffer size AND transfer count to move data from memory to a peripheral. Did I overlook something?

I need to move this over to a ping-pong approach, scatter-gather, or something else allowing me to interrupt the processor at a more reasonable rate. What is the best way to do this? Should set up three separate uDMA channels in single request mode? Can I modify the control table to transfer 3-words then stop? I can figure out the details is someone can point me in the best general direction as I do not have a lot of time to get this done. Any guidance would be greatly appreciated.

  • Hello Dave

    How larger is the buffer being sent from the external D/A device to TM4C1294. Note that the maximum transfer size is 1024 elements for any control task. This will allow up to 1024 half words transferred to the SSI (considering that the nearest size for 12 bit D/A is 16 bits). Hence the application will be interrupted at 1023/3 = 341 transfer (since 1024 is not a multiple of 3).

    Regards
    Amit
  • Hi Amit,

    Thank you for responding. The more resolution I can get out of this the better. I am updating all three phases with each DMA cycle at a constant 1ms rate and rebuilding the data buffer to change motor speed. The excitation resolution changes inversely proportional to motor speed this way, which is desireable. Doing this requires constant 1KHz interrupts. That is not an unreasonable rate, especially since the rate is periodic and repeatable, but I was hoping there was a way to run through a large buffer before I had to service the interrupt. As it is, in basic burst mode, I am seeing little or no performance advantage to using the uDMA over transferring the data via ISR except for the near total elimination of jitter and relative phase error. It is worth doing for that, but in terms of processor overhead it is nearly a wash.

    One thing I was wondering about since my first post is using the uDMA in single transfer ping-pong mode to send 1024 D/A channel points. The D/A will not update any analog outputs until the third channel is written so there is no consequence to updating each channel separately over time. I could increase the transfer rate to 1ms/3, transferring one D/A channel at a time instead of all three, and let the timer trigger the uDMA until it decrements the transfer count to zero. Am I understanding the single transfer mode correctly, or would I still have to service the uDMA after each transfer? Thanks for your help.

  • It does not look like the timer can assert a single transfer request, so I guess I have to service the higher rate interrupts. Please let me know if you think of any other way to allow uDMA to send isochronous data without having the processor get involved with every transfer. My application is fairly slow to be of much concern, but It would be different for faster transfers such as audio -> D/A. Maybe I am missing something. Thanks again for your help.
  • Hello Dave

    The DMA transfer is an efficient method when large amount of data have to be transferred. That is when the code will see the advantage. On a related note there is I2C Application note on TM4C web page, which has a diagram that shows how DMA can help reduce the number of interrupts when sending large amount of data v/s CPU doing the same in ISR.

    Coming back to the point here, since I am not sure on the overall mechanism for this specific DMA, you could in fact change over to SW triggered DMA doing 3 transfers every 1 ms in a Timer Interrupt Handler.

    Regards
    Amit
  • Hello Amit,
    I agree with the comments about large amounts of data, and I am using those means for sending data between memory and peripherals on other projects. My concern is when data must be transferred from memory to a peripheral in a critically timed manner. For example if you have a WAV file in a memory buffer, I do not see any means of sending that data to a D/A at the periodic and repeatable rate specified in the WAV header. I can send it in lumps and chunks, but I see no mechanism for throttling the rate. If I were sending 24-bit X 2 audio at 44KHz I would be much more concerned about this. I feel like I must be overlooking something because this is a common application for DMA that can take a tremendous burden off of the processor. I will look again when I can come up for air after getting this project completed.

    I have my motor running very smoothly now with the uDMA, and with the processor servicing every three-word transfer. My project is being used in a instrument for electron microscopy and it is extremely sensitive to jitter. Using the uDMA obliterates the jitter so I do not have to worry about variations in interrupt latency. Otherwise I would simply write three words to the SSI FIFO in the timer interrupt and not use uDMA at all for this particular transfer.

    Side note:
    I am having fun with this part and I appreciate that TI offers the launchpad products. I had this project soldered together on a breadboard and running in about 1-week because I was able to easily rewire I/O pins and other such things. My head would explode if I went to PCB layout without checking everything first, but now I can finish it up with a lot more confidence.

    Regards,
    Dave
  • Dave 1024 said:
    I can send it in lumps and chunks, but I see no mechanism for throttling the rate.

    From a quick read of the uDMA controller section in the datasheet a timer can generate a "Burst Request" trigger to the uDMA controller, where a Burst Request causes a transfer of "Arbitration Size" item transfers.

    i.e. think can can configure a regular timer to trigger the uDMA transfer 1 to 1024 items (allowed range of Arbitration Size).

    [I haven't tried to implement DMA in this way]

  • Hello Chester,

    That is only possible when Burst Request is generated by the peripheral that the Burst Request setting of the DMA can work with. But yes it is a good try,

    Regards
    Amit
  • Amit Ashara said:
    only possible when Burst Request is generated by the peripheral

    Hi Amit,

    Great to have you so active - constantly monitoring even these (smallest) of details.

    For those unfamiliar w/"Burst requests generated by peripherals" might you provide bit more detail?   Would you be good enough to comment upon "how, when and by what means" those (MCU I assume) peripherals make such, "Burst Request."   (1000 pardons should such be "well explained" w/in MCU manual - staff here finds that "not" the case...)

  • The DMA Operation section of the TM4C129 datasheet for the General-Purpose Timers says the following:

    16.3.6 DMA Operation

    The timers each have a dedicated μDMA channel and can provide a request signal to the μDMA controller. Pulse requests are generated by a timer via its own dma_req signal. A dma_done signal is provided from the μDMA to each timer to indicate transfer completion and trigger a μDMA done interrupt (DMAnRIS) in the GPTM Raw Interrupt Status Register (GPTMRIS) register. The request is a burst type and occurs whenever a timer raw interrupt condition occurs. The arbitration size of the μDMA transfer should be set to the amount of data that should be transferred whenever a timer event occurs.

    For example, to transfer 256 items, 8 items at a time every 10 ms, configure a timer to generate a periodic timeout at 10 ms. Configure the μDMA transfer for a total of 256 items, with a burst size of 8 items. Each time the timer times out, the μDMA controller transfers 8 items, until all 256 items have been transferred. Refer to “Micro Direct Memory Access (μDMA)” on page 690 for more details about programming the μDMA controller.

    I think this is the setup the original poster is looking for.

  • @Chester,

    Thank you - that's good stuff - yet it suggests that (only) a Timer may generate this "Burst Request" - and not an "individual peripheral" which I believe was Amit's contention...

    In light of this finding - now relating back to poster's original desire (interrupt only upon the "completed transfer") is it true that, "Only when the 256 items (per this specific example) have been transferred will the key/critical µDMA interrupt occur?"   Believe that was of key concern to this poster...

  • Hello Chester

    That is correct. I was reading the data sheet as well and reached the same place (saw your post first though)

    Regards
    Amit
  • May we ask if, "Some, none, most or all" of this µDMA Burst Transfer capability extends to the 123 family? And - is it true that only Timer triggered transfers may invoke this Burst Transfer?
  • Hello cb1,

    Yes, it should.

    Regards
    Amit
  • Hi Amit,

    We assume you're referring to TM4C123 having similar µDMA Burst Transfer capability as the 129. Is that correct?

    And - w/out the Timer in play - may an MCU Peripheral "signal or call" for such a Burst Transfer? Thank you.
  • Hello cb1,

    Yes. The uDMA module has the burst feature the same on both devices. The manner in which peripheral is integrated changed from 123 to 129. But I do think it is the correct text from the data sheet.

    W/o the timer in play the peripheral may be able to signal the same, and it needs to be checked on a per peripheral basis. Some peripherals may not have the DMA capability (like I2C on TM4C123).

    Regards
    Amit
  • cb1- said:
    yet it suggests that (only) a Timer may generate this "Burst Request" - and not an "individual peripheral"

    Datasheet Table 9-1. μDMA Channel Assignments summarizes which peripherals can generate a Burst Request, and yes peripherals other than just a Timer can generate a burst request.

    cb1- said:
    "Only when the 256 items (per this specific example) have been transferred will the key/critical µDMA interrupt occur?"

    When the DMA transfer is complete (all 256 items in this example) is complete the µDMA controller sends a dma_done signal to the peripheral, which in this example can generate a GPTM Timer x DMA Done Interrupt.

    Use of µDMA ping-pong mode should allow continuous timer-triggered DMA transfers to be be configured, where the software only has to process an interrupt after each transfer (of a number of items) is complete.

  • Thank you for so clear & complete a response. My firm does not use 129 - our hope is that (most) of the above carries thru to the earlier 123 family.

    As the poster has & uses the 129 - and such data appears to have come from that MCUs manual - read/review (may) have been too fast/furious...
  • Thank you all for your responses. The documentation clearly suggests the device can do small isochronous transfers from a large block of data with a single "done" interrupt. That is exactly what I am looking for. My project is working beautifully right now with fast interrupts, but I will throw some code together to use the "done" interrupt a little later so I can add a percentage point to my 90-percent CPU idle time :o)

    I was confused because I did not see specifically where to separate the burst size from the block size and I assumed they were one of the same. I saw no contradicting evidence in driverlib either, but I probably overlooked that as well.

    Thanks again, and I will let you know when I have code successfully running.

    Regards,
    Dave