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.

Can DMA be used to send a waveform to the ePWM?

Other Parts Discussed in Thread: CONTROLSUITE

Can I use DMA to read data from a lookup table and output to the ePWM?

I need only one word to tranfer at a time.

So far I have only been able to have 1 word to transfer and have to use the DMA ISR to change the source address so it increments through my lookup table. This seems to defeat the purpose of DMA. I was hoping I could transfer 1 word per event but auto increment through my lookup table without CPU intervention. Can this be done?

Thanks

  • did you look at the ePWM_dma example in the Header Files / controlSUITE?

    C:\ti\controlSUITE\device_support\f2833x\v132\DSP2833x_examples_ccsv4\epwm_dma

     

  • Chris,

          Thanks for the example. I looked at it and the other DMA examples. They were invaluable to me to get DMA working. However, this example does exactly what I was trying to explain above. It bursts 1 word. There has to be another trigger to start the next DMA burst. Why wouldn't you just use the ePWM interrupt to write the next byte. In the time it takes you to setup the DMA to do another burst of 1 word, you can just write the next word manually in the ePWM ISR.

    I am hoping I am missing something.

    My issue is that I have two ePWM interrupts and they delay each other causing jitter. I was hoping DMA would solve this problem for me but I am not yet seeing how. If it could write all the words from my lookup table, 1 at a time and retrigger without CPU intervention, then that would be great!

    Having said all that...

    If I set it up that the DMA channel to burst the 1 word when the ePWM triggers it, and not necessarily when the ePWM interrupt is handled, I may get rid of the jitter. I will try that.

    Thanks

     

  • Maxpower,

    It would help to understand in more detail what you are trying to do with the PWMs.  I hear that you want to control (2) ePWM modules and you want to minimize the jitter between them.

    Why do you have (2) ePWM interrupts? 

    Is the goal really to have a look-up table of duty cycles to load into the ePWM?  Or is the look-up table an attempt to resolve the jitter issue?

    Please provide more details on what you are trying to achieve.

    On a side-note, the DMA certainly can auto increment through memory without ISRs.  There are Burst and Transfer Step registers that can increment or decrement by 16-bits.  Each transfer is initiated by a trigger source.  Each transfer can have multiple bursts.  At the end of all the transfers you can then interrupt the CPU.

    Though the DMA support of the ePWM is great for time-of-flight applications where fast ePWM updates are needed, I am not sure that is the issue for your case. 

    Thanks, Jeff

  • Hi Jeff!

    To give you more info:

    I am controlling a motor and using a resolver for motor position. The method I am using to read the resolver is based on a TI appnote that requires the excitation frequency run exactly 1/8 the time of the motor frequency.

    If the motor is running at 20KHz (ISR freq) then the excitation has to run at 2.5KHz. In order to get this frequency for the excitation signal from the 20KHz motor control ISR, the PWM lookup table has to be only 8 points long. This doesn't generate a smooth sine wave. This may or may not be an issue but I am assuming for the moment it is and am trying to get a smooth 2.5KHz sine wave excitation signal with more points in my lookup table.

    My first attempt was to have a separate ISR for the excitation signal and motor control PWMs. However, since there are now two ePWM ISRs running, there is too much jitter on the excitation waveform and this causes the motor control to no longer work. The angles calculated by my resolver code is way too noisy.

    I then thought I could generate the waveform on the ePWM using DMA but only one lookup value can be written to the ePWM from the DMA module at a time. That is, I can only burst 1 word per transfer. I get an interrupt after each burst of 1 word. Having two high frequency ISR is proving to cause problems. I know I can burst more than 1 word per transfer but that doesn't solve the problem. I hope I am just misunderstanding something.

    I thought about using one short period timer interrupt (ie no PWM interrupts) to generate a smooth excitation signal (that part works) but the motor control routines plus my resolver routines take more time then allotted by the timer period. I am not even close, so optimizing the code is not going to work in this case. lol

    Thanks for the help!

  • Hi Maxpower,

    Thanks for the added details.

    If you were to use ePWM1 for the motor PWMs and ePWM2 for the resolver PWM, you could then use ePWM3 as the trigger source for the DMA to update ePWM2 duty cycle.

    This will allow you to specify the update with the ePWM3 SOC trigger at whatever rate you want to get a smooth excitation signal.  You would adjust the look-up size to match.

    The DMA would not need to ever generate an ISR.  It would increment through the lookup table writing 1 value on every trigger.  For the source addresses, the Burst Step would be 1 and the Burst Size would be 1.  The Transfer Step would be 0 and the Transfer Size would be the size of the look-up table.

    For every ePWM3 SOC trigger the DMA would do (1) transfer.  Since the burst size is 1, it transfers 1 value for every ePWM3 trigger.  If you want more data points, for the 2.5Khz sine wave, just increase the ePWM3 trigger rate.  The complete process would be repeated at the end of the look-up table which would also be the end of the transfer.  You can have an interrupt at this point or use the DMA's wrap function to reset the start address.

    The key point from your description is to avoid getting an interrupt on every burst.  The way to do that is to specify a transfer size that matches your look-up table size.

    I hope this helps, Jeff

  • Jeff,

        Thanks! I didn't get a chance today to try it. I will be at a Motor Control seminar tomorrow with TI :) . Hopefully I can give this a try on Friday.

    Not that it matters with your example but I am using PWMs 1, 2 & 3 for motor drive and 4 for resolver excitation. I will use PWM 5 to trigger DMA. But why can't I just use 4? Why do you, in your example, use a 3rd PWM to trigger DMA?

    So if I understand you correctly, by setting burst to size = 1, step = 1 and transfer step = 0, size = size of lookup, it will walk through my table, outputting one word at a time and automatically wrap? What do I set the wrap register(s) to?

    Thanks again for all the help!

     

  • I am soooo close!

    I have setup DMA on an extra PWM to do what you described. I tested it by writing to a memory location and watching it change. It changes quickly, obviously, so I create a buffer to dump that memory location in and DMA is working as planned. So the next step, I simply took that memory location and copied it into the PWM CMP register and I get the output on the PWM I want. The last step is to use the PWM CMP register address as the destination. This is where it fails.

    DMA will not update the CMP register directly. It will update a memory location that I can copy into the CMP register though.

    What am I doing wrong?

    Here is my code:

     DMAInitialize();

    // Configure DMA Channel
     DMADest = &EPwm4Regs.CMPA.half.CMPA;
    // DMADest = &dbuff[0];
     DMASource = &excitation[0];
     DMACH1AddrConfig(DMADest,DMASource);
     DMACH1BurstConfig(0,1,0);
     DMACH1TransferConfig(7,1,0);
     DMACH1WrapConfig(8,0xFFF8,0,0);
     DMACH1ModeConfig(DMA_ePWM5SOCB,PERINT_ENABLE,ONESHOT_DISABLE,CONT_ENABLE,SYNC_DISABLE,SYNC_SRC,OVRFLOW_DISABLE,SIXTEEN_BIT,CHINT_END,CHINT_ENABLE);
    StartDMACH1();

    Under what condition will DMA not write to the hardware directly?

    Thanks

  • I thought I had the answer. I saw this line in the DMA/PWM example:

    SysCtrlRegs.MAPCNF.bit.MAPEPWM = 1;      // Remap ePWMs for DMA access

    Unfortunately, adding this line does not make it work. However, I can no longer write to the PWM register manually through the watch window. So this line is doing something.

    Any ideas?

  • It is working now!

    After adding the line:

    SysCtrlRegs.MAPCNF.bit.MAPEPWM = 1; 

    Which remaps t he ePWM registers, I had to modify the linker map to put the ePWMs in Peripheral Frame 3.  This makes sense but I don't understand why the example code doesn't have them mapped that way.

    Thanks for the help!

  • Having same issue.

    What changes did you make to the linker map?  ... Specifically what addresses?

    Thanks

  • The above command changes where the pwm registers are mapped but you need to change the linker command file so that the rest of the program knows where they are mapped.

    Periperhal frame 1

    /*   EPWM1       : origin = 0x006800, length = 0x000022     /* Enhanced PWM 1 registers */
    /*   EPWM2       : origin = 0x006840, length = 0x000022     /* Enhanced PWM 2 registers */
    /*   EPWM3       : origin = 0x006880, length = 0x000022     /* Enhanced PWM 3 registers */
    /*   EPWM4       : origin = 0x0068C0, length = 0x000022     /* Enhanced PWM 4 registers */
    /*   EPWM5       : origin = 0x006900, length = 0x000022     /* Enhanced PWM 5 registers */
    /*   EPWM6       : origin = 0x006940, length = 0x000022     /* Enhanced PWM 6 registers */

    Periperhal frame 3

       EPWM1       : origin = 0x005800, length = 0x000022     /* Enhanced PWM 1 registers */
       EPWM2       : origin = 0x005840, length = 0x000022     /* Enhanced PWM 2 registers */
       EPWM3       : origin = 0x005880, length = 0x000022     /* Enhanced PWM 3 registers */
       EPWM4       : origin = 0x0058C0, length = 0x000022     /* Enhanced PWM 4 registers */
       EPWM5       : origin = 0x005900, length = 0x000022     /* Enhanced PWM 5 registers */
       EPWM6       : origin = 0x005940, length = 0x000022     /* Enhanced PWM 6 registers */

    I hope this helps.

  • Thanks much.

    I'm using a 2806x and was experiencing the same symptoms so I thought the solution might be the same as for the 2833x.  As I discovered, on the 2806x changing the mapping bit in SysCtrlRegs works without requiring remapping in the linker cmd file.

  • I had this problem as well and finally found the answer is another less obvious post. For future reference:

    Comment this out in the page 1 section of DSP2833x_Headers_nonBIOS.cmd:

    /*   EPWM1       : origin = 0x006800, length = 0x000022     /* Enhanced PWM 1 registers */
    /*   EPWM2       : origin = 0x006840, length = 0x000022     /* Enhanced PWM 2 registers */
    /*   EPWM3       : origin = 0x006880, length = 0x000022     /* Enhanced PWM 3 registers */
    /*   EPWM4       : origin = 0x0068C0, length = 0x000022     /* Enhanced PWM 4 registers */
    /*   EPWM5       : origin = 0x006900, length = 0x000022     /* Enhanced PWM 5 registers */
    /*   EPWM6       : origin = 0x006940, length = 0x000022     /* Enhanced PWM 6 registers */

    Then add this in:

    Periperhal frame 3

       EPWM1       : origin = 0x005800, length = 0x000022     /* Enhanced PWM 1 registers */
       EPWM2       : origin = 0x005840, length = 0x000022     /* Enhanced PWM 2 registers */
       EPWM3       : origin = 0x005880, length = 0x000022     /* Enhanced PWM 3 registers */
       EPWM4       : origin = 0x0058C0, length = 0x000022     /* Enhanced PWM 4 registers */
       EPWM5       : origin = 0x005900, length = 0x000022     /* Enhanced PWM 5 registers */
       EPWM6       : origin = 0x005940, length = 0x000022     /* Enhanced PWM 6 registers */