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.

TMS320F28035: EPWM ISR STOPS Triggering randomly

Part Number: TMS320F28035

Hi,

So randomly after like few thousands of cycles EPWM ISR is not called.

So is there anything wrong I am doing with initialization of EPWM or setting something? It works almost so long so hard to find the problem.

Thanks,

Sagar

  • Hi Sagar,

    Can you give more details on this? What do you mean by "stop pulsing after 1000 pulses" & then "randomly after like few thousands of cycles EPWM ISR is not called"?

    Thanks
    Vasudha
  • Sagar,

    I think I understand what you are trying to do. If I'm right, you want to periodically disable PWM1 and you are doing this by setting the period register to zero and turning off the clock. Presumably after some time you restore the period register and re-start the clock.

    Firstly a comment: setting ETSEL to 0xB will trigger interrupts on period OR zero match events, not just zero matches as stated in the comment. Normally one would use this with up-down counter mode, but I do not know the value of "TBCTLVAL" so I cannot determine what mode the counter is operating in. I also cannot determine what TBPRD value you are using because I do not know "pulse_speed".

    In any case, I'm suspicious of your method of disabling interrupts by setting the period value to zero. It is conceivable that you force TBPRD to zero just before the count reaches it, so the match occurs during the EALLOW or the next instruction, in which case TBCTR has already passed the period match when you re-enable and no interrupt is taken. In that case the counter would continue to 0xFFFF and wrap. Possibly you would lose interrupts in that case. This is just my theory, you understand.

    It would be cleaner to leave TBPRD and CMPA alone and just disable the clock, or to trigger your interrupt from compare match and disable by moving CMPA beyond TCPRD - but make sure interrupts are disabled when you do that.

    This is just something to look at. Please do respond to Vasudha's questions so we have more to work on. Thanks.

    Regards,

    Richard
  • So I just found out that below in the ISR where EPwm1Regs.ETCLR.bit.INT = 1; helps to generate a next ISR trigger on the end of TBPRD . But after having ISR Trigger continuously for almost regularly for million of pulses(I ran the the code controlling Dc motor) for 7-8 hours, it misses the interrupt and then all my variable update done in ISR is messed. So I do want to understand if there is wrong in my way setting up the registers.

    THANKS,



    __interrupt void epwm1_isr(void)
    {

    EPwm1Regs.ETCLR.bit.INT = 1;
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    }
  • This part of your code is correct.

    Regards,

    Richard
  • Can you give more details on this? What do you mean by "stop pulsing after 1000 pulses" & then "randomly after like few thousands of cycles EPWM ISR is not called"?

    I mean give 1000 pulse PWM fora dc motor and disable clock and switch off PWM. And then I start PWM for 1000 pwm Pulse.

    For each end of PWM Pulse I have Epwm ISR interrupt generated. But after having the above pattern the Epwm ISR is not called while I still have the pulsing going on for some time.

    So this time I had my probe connected and I manually made EPwm1Regs.ETCLR.bit.INT = 1 in command window (even though I clear it in my epwm ISR) and then it started to trigger the ISR again.

    So i am not sure if I am doing incorrectly or something else.

    Thanks,

    Sagar Shah

  • I think the most likely explanation is an interrupt takes place just before you turn off the PWM clock and it doesn't get serviced. As I said, the technique of gating pulses by switching the peripheral clock on and off is not a great way to do this. You could try manipulating CMPA as I suggested earlier, or use the AQ to reconfigure the PWM action from pulse generation to forced low. Another approach would be to re-configure the GPIO pin between PWM and I/O.

    Regards,

    Richard
  • I did not understand the part where you manipulating CMPA or AQ ro reconfigure the PWM action? Could you explain it?

    Thanks,
    Sagar Shah
  • Sure. From your init code in the first post you have PWM1A configured like this:
    EPwm1Regs.AQCTLA.bit.ZRO =0x02; // output High at zero
    EPwm1Regs.AQCTLA.bit.PRD =0x00; // Unaffected.
    EPwm1Regs.AQCTLA.bit.CAU =0x01;// output low at CMPA

    So, to disable the PWM you could just write:
    EPwm1Regs.AQCTLA.bit.ZRO =0x01; // output low at zero

    ...and re-enable with:
    EPwm1Regs.AQCTLA.bit.ZRO =0x02; // output High at zero

    Regards,

    Richard
  • In my first post the system sends out 1000 pulse then waits for signal from other system(API) and then sends again 1000 pulse and waits for Api signal. So that is why I am disabling clock when i have not received signal from the API. SO you mean instead of having EPwm1Regs.CMPA.half.CMPA=0;
    EPwm1Regs.TBPRD=0;
    EALLOW;
    SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 0;
    EDIS;

    I should have So, to disable the PWM you could just write:
    EPwm1Regs.AQCTLA.bit.ZRO =0x01; // output low at zero ??

    Thanks
  • I don't see why you need to disable the clock when all you want to do is stop PWM pulses from being produced.  The issue you originally described is likely caused by some timing issue when you do that.  I have described how to accomplish the same thing without disabling the clock - you can keep the PWM running but re-configure it to output low always.  Yes.

    Regards,

    Richard

  • I'd like to add that there may be something about what you're trying to do which isn't clear to me. If your intention is to start the PWM at the precise instant when your other system responds then you could try disabling TBCLK with TBCTL.CTRMODE and resetting TBCTR. You're going to have to think through the details then try it out.

    If you can attach a timing diagram of what you need it could help. Thanks.

    Regards,

    Richard
  • Below is one full cycle of pulses i want after i receive start command from the API

  • Thanks. A couple of questions:
    1. Is it critical to have the pulses start exactly on receipt of some trigger? If so, is the trigger software or hardware?
    2. The pulses start from a low condition and terminate in a high condition. What resets the output back low for the start of the next sequence?
    Regards,
    Richard
  • ALSO I have Question regarding how to enable EPWM clock and other sequence after I complete a move of pulses as shown above.

    void Start(){ // after Recieving start from the API
    EALLOW;
    SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 1;
    EDIS;

    EPwm1Regs.TBCTL.bit.CLKDIV = 0x6;
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0x0;

    EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT
    EPwm1Regs.ETSEL.bit.INTSEL = 1;
    EPwm1Regs.ETCLR.bit.INT = 1;
    EPwm1Regs.TBPRD = CPU_CLK/(2*pulse_speed); // pulse_speed is a Uint16 (ranges from 400- 1500)
    EPwm1Regs.CMPA.half.CMPA = (EPwm1Regs.TBPRD +1)/2;

    }





    void STP(){ // After receiving stop from the API
    EPwm1Regs.CMPA.half.CMPA=0;
    EPwm1Regs.TBPRD=0;
    EALLOW;
    SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 0;
    EDIS;
    }


    So is the above sequence correct? Should I put EPwm1Regs.TBCTR=0; in the start or somewhere else?

  • 1) yes should it start on trigger. but few cycles latency is okay.
    2)Ignore the part where it remains in the high condition. It should go at low condition after stop command.(the scope image is not correct at the end of cycle).
  • I think the loss of PWM interrupts has something to do with the timing of when you enable and disable the clock relative to the interrupts. In my view it would be safer to leave the clock active and control the PWM bursts by changing the time-base counter. I have coded something along these lines and it seems to work. Here is a summary of what I did.

    Whole PWM initialisation:

    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // TB clocks stopped
    EDIS;
    EPwm1Regs.TBCTL.bit.CTRMODE = 3; // freeze TB counter
    EPwm1Regs.TBCTL.bit.PRDLD = 1; // immediate load
    EPwm1Regs.TBCTL.bit.PHSEN = 0; // disable phase loading
    EPwm1Regs.TBCTL.bit.SYNCOSEL = 3; // disable SYNCOUT signal
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0; // TBCLK = SYSCLKOUT
    EPwm1Regs.TBCTL.bit.CLKDIV = 0; // clock divider = /1
    EPwm1Regs.TBCTL.bit.FREE_SOFT = 0; // stop on emulation suspend
    EPwm1Regs.TBPRD = 1600; // set period for ePWM1
    EPwm1Regs.TBPHS.all = 0; // time-base Phase Register
    EPwm1Regs.TBCTR = 0; // time-base Counter Register
    EPwm1Regs.ETSEL.bit.SOCAEN = 1; // enable SOC on A group
    EPwm1Regs.ETSEL.bit.SOCASEL = 1; // select SOC from zero match
    EPwm1Regs.ETSEL.bit.INTEN = 1; // enable PWM interrupt
    EPwm1Regs.ETSEL.bit.INTSEL = 1; // generate interrupt on zero match
    EPwm1Regs.ETPS.bit.INTPRD = 1; // generate pulse on 1st event
    EPwm1Regs.ETPS.bit.SOCAPRD = 1; // generate pulse on 1st event
    EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0; // enable shadow mode
    EPwm1Regs.CMPCTL.bit.LOADAMODE = 2; // reload on CTR=zero
    EPwm1Regs.CMPA.half.CMPA = 0x0080; // set compare A value
    EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // LOW on CMPA up match
    EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // HIGH on zero match
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // start TB clocks
    EDIS;


    I have a CPU timer set up at 1 Hz frequency to start the bursts. In your implementation the trigger would come from the responding system. In the timer ISR I have these lines to start the burst:

    EPwm1Regs.TBCTL.bit.CTRMODE = 0; // release counter
    EPwm1Regs.AQCSFRC.bit.CSFA = 0; // force low

    The PWM ISR looks like this:

    #define PRDMAX 1600

    unsigned long PwmIsrCount = 0L;
    unsigned int pulseCount = 0U;
    unsigned int xprd = PRDMAX;

    // interrupt service routine - triggered by PWM1 (EPWM1_INT)
    interrupt void PwmIsr(void)
    {
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    EPwm1Regs.ETCLR.bit.INT = 1;

    EPwm1Regs.TBPRD = xprd--;
    EPwm1Regs.CMPA.half.CMPA = (xprd >> 1);

    if (1000U < PwmIsrCount++)
    {
    xprd = PRDMAX;
    PwmIsrCount = 0L;
    EPwm1Regs.TBCTL.bit.CTRMODE = 3;
    EPwm1Regs.TBCTR = 0;
    EPwm1Regs.AQCSFRC.bit.CSFA = 1;
    asm(" NOP");
    }
    }

    Seen at the pin, the signals look fine. I hope this helps.

    Regards,

    Richard
  • Thanks for the help.

    I believe I have similar Init in my code. But I still have not understand that once after all my start condition and after enabling Epwm1 ISR to trigger. It some how did not to go into the isr and in the command window I put this EPwm1Regs.ETCLR.bit.INT and made it equal to 1. then suddenly it began to go into isr regularly.

    So if you can make me understand that why did that happen?

    Also in your code above you have PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    EPwm1Regs.ETCLR.bit.INT = 1; at the beginning of the ISR (instead having it at the end) while I have it at the end of ISR. So is it done on purpose like this?

    Thanks

  • You are welcome.

    There is a kind of handshake between the PIE module and the core. When you write to the PIEACK register you are telling the core that an interrupt on that line has been handled and another can be generated. You have to clear the trigger source too, which is what these two lines are doing.

    In you code there is an intermittent condition where either the handshake takes place but not the trigger clear, or vice-versa. Most likely a new interrupt trigger appeared just after you had cleared the old one. I don't know how this happened but placing the trigger clear just before exiting the ISR may help. My suspicion is also that it has something to do with removing the peripheral clock in the way you were doing. The method I proposed avoids doing this.

    Regards,

    Richard
  • Also so you mean if I want to disable the clock and enable the clock -

    so where should I have clock divisor ? after enabling the clock right? is there like any proper sequence for it?
    Thanks,
    Sagar
  • Sagar,

    The method I suggested does not require that the PWM clock be stopped and re-started. If you want to do that, you can, but you have to set SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 1 before writing to any of the registers.

    Regards,

    Richard