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.

TMS320F28379D: ePWM interrupts on TBCTR = CMPA and also on TBCTR = CMPB

Part Number: TMS320F28379D

Hi,

I was talking to Nima Eskandari but the thread is closed, so I try making this related question, instead.

Hi Nima, here I am, bothering you again... I hope, we can reopen the thread!

To continue with the interrupts question, "TMS320F28379D: ePWM interrupts on TBCTR = CMPA and also on TBCTR = CMPB",

I have made my tests and your idea works good, but I found out that I can also use Period on ePWMxA and CMPB on the ePWMxB to generate the interrupts I need. It seems to be more simple...

However, the timing does not work as I expected:

Interrupts A and B on ePWM2 are supposed to activate an interrupt on ePWM1, which clears GPIO56 pin to low, just after the A-pin of the ePWM1 goes high.

Ideally, this should happen after around 5 uS, but this is not so crucial, as long as this remains allways the same.

The interrupts are working, but the timing not.

GPIO56 goes low at any moment, but not on the moment I want.

My logic analyzer shows, also, that the interrupts of ePWM2 are comming some (randomly) 4 till 7 uS before the changing to Low or High happens on the ePWM2-output A,

while I am expecting it just on this time or slightly after, but not before.

So, I have two questions:

1 - Why does the interrupt comes so far before the time it should come?

This is, so far, not so disturbing for my application, but:

2 - Why is Pin56 going low randomly in time?

I know, there is a propagation delay of around 14 SYSCLK till the ISR is called, but this does not explain this behaviour.

Te relevant parts of the code are included.

I wish you a nice weekend, or, better, a nice week!

Gustavo

6472.forTi_13102018.c
Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
myPeriod = 730; // Freq = 67,8 kHz, Period 14,75 uS
myDutyA = 718; // duty is 98,31%
myDutyB = 50;
myDutyFineA = 1;
myDutyFineB = 1;
myPeriodGrand = 786;
myDutyGrand = 451;
//
// epwm1_isr
//
__interrupt void epwm1_isr(void)
{
EPwm1Regs.ETSEL.bit.INTEN = 0; // Disable ePWM1 INT, until epwm2_isr enables it again
GpioDataRegs.GPBCLEAR.bit.GPIO61 = 1; // This should allways happen at the same place, ideally 6uS after ePWM1 goes High (which, in turn, remains High during 14,38 uS)
DELAY_US(100); // this is only for clarity. Here is some code
GpioDataRegs.GPBSET.bit.GPIO61 = 1; // set GPIO61 high
if(modo == 0b110)
{
modo = 0b010; // 100: time-base counter equal to CMPA when the timer is incrementing
DELAY_US(5); // Here is some code
}
else
{
modo = 0b110; // 110: time-base counter equal to CMPB when the timer is incrementing
DELAY_US(5); // Here is some code
}
EPwm2Regs.ETSEL.bit.INTSEL = modo;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; // Acknowledge this interrupt to receive more interrupts from group 3
}
//
// epwm2_isr
__interrupt void epwm2_isr(void)
{
EPwm1Regs.ETCLR.bit.INT = 1; // Clear INT flag for ePWM1 timer
EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT on ePWM1
EPwm2Regs.ETCLR.bit.INT = 1; // Clear INT flag for this timer
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; // Acknowledge this interrupt to receive more interrupts from group 3
}
void HRPWM1_Config(myPeriod)
{
EPwm1Regs.TBCTL.bit.PRDLD = TB_IMMEDIATE; // set Immediate load
EPwm1Regs.TBPRD = myPeriod; // PWM frequency
EPwm1Regs.CMPA.bit.CMPA = myDutyA; // set duty for ePWM1A
EPwm1Regs.CMPA.bit.CMPAHR = (myDutyFineA << 8); // set duty fine for ePWM1A
EPwm1Regs.CMPB.bit.CMPB = myDutyB; // set duty for ePWM1B - for the interrupt
EPwm1Regs.CMPB.all |= (myDutyFineB << 8); // set HR-duty for ePWM1B - for the interrupt
EPwm1Regs.TBPHS.all = 0;
EPwm1Regs.TBCTR = 0;
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Hi!
    Sunny Sunday, productive dreams during the night, I solved it, at least partially!

    For the record, if somebody reads it:

    To question2 : "Why is Pin56 going low randomly in time?"
    This was because, although I was disabling the interrupt for this channel until needed, the counter was running and "saving" the count for later. So, as soon as I enabled the interrupt, it was fired, anywhere on time.

    The solution was to disable/enable the counter as needed:
    EPwm1Regs.ETPS.bit.INTPRD = 0x0;

    However, question 1 "Why does the interrupt comes so far before the time it should come?" remains without answer for me.

    I suspect some (too long) propagation time to the pin. So the EPwm1Regs.ETSEL.bit.INTSEL register is processed and the interrupt is fired, while the actual signal needs more time to activate the physical pin.

    The ISR is active at around 4 til 7 uS before CMPB or Period, isn't this too much?

    This is not happening by the interrupts from ePWM1. The ISR is responding 0,53 uS after CMPB.
    This ePWM is running much faster. Is this the difference?

    I will leave this thread open, in case somebody has an answer for me.

    Anyway, I solved the issue in the same way as I did with the interrupt from ePWM1:
    Now, CMPC and CMPD on ePWM2B fire an interrupt slightly after CMPB and CTR=PRD on ePWM1A, which I can controll in time.

    I wish everybody a fine Sunday and a productive week.
    Gustavo
  • Gustavo,

    I’m a bit confused from your description of the timings, can you upload a diagram with notes to describe what you’re seeing?

    Nima
  • Hi Nima,

    thanks for answering.

    I include a simplified screenshot.

    What you see is:

    On Ch2 is the signal of ePWM2. On this edge (marker A2), CMPB triggers the interrupt.

    On this test, ePWM2 startet just there. Before this, the signal was all the time low.

    (I wanted to be sure, no counting was made before, which could trigger a waiting interrupt. Anyway, this pattern continues like this all the time)

    On Ch5 is Gpio56 going low inside the ISR. (marker A1)

    As you can see, Pin56 goes low 7,25 uS before the ePWM-Pin goes high.

    I realise, there is a delay between the CMPB count and the actual toggling of the pin, but

    are 7,25 uS not too much?

    (We have to add the propagation delay from the interrupt itself, plus the time needed to toggle pin 56 too)

    ePWM2 is slow (496 Hz) Is this the reason?

    EPwm2Regs.TBPRD = 786;
    EPwm2Regs.CMPB.bit.CMPB = 451;
    EPwm2Regs.CMPA.bit.CMPA = 451;

    with 

    EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0b100; 
    EPwm2Regs.TBCTL.bit.CLKDIV = 0x4; 

    A I said, this is not disturbing in my application, but it could be interesting to know the reason, for the future.

    Best regards,

    Gustavo

  • Okay just to clarify,
    on CMPB you generate interrupt, in the interrupt you toggle GPIO56.
    You are seeing GPIO toggle , before CMPB toggles to generate the interrupt?
  • Hi Nima, thanks for answering.

    Yes, I see the GPOI toggle around 7 uS before the ePWM pin toggles on CMPB

  • Do you have a small example code for this? I have never seen this before.
  • Hi Nima, 

    sorry for the delay, I was on travel again.

    Here is a small code (I cleaned it from all other tasks) and a screenshot where you can see what is happening.

    The time between the toggling of GPIO56 and ePWB2B (GPIO3) on CPMB is shorter (4.875 uS) then the one on Period (7.375 uS)

    Maybe is my equipment?

    Strange is that the interrupt on ePWM1 does what I expect.

    forTi28102018_V05-14102018.c
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    #include "F28x_Project.h"
    // Function Prototypes
    void initSerialPins(void);
    void HRPWM1_Config(int);
    void HRPWM2_Config(int);
    __interrupt void epwm1_isr(void);
    __interrupt void epwm2_isr(void);
    Uint16 modo,miPeriod,miPeriodFine,miDutyA,miDutyB,miPeriodGrand,miDutyGrand;
    #define PWM_CH 9 // # of PWM channels
    volatile Uint16 EPwmTZIntCount[9],Test_flag1,ph_dly; // 0,18 are extra
    volatile struct EPWM_REGS *ePWM[10]; // vars for flags
    void main(void)
    {
    //###########################################################################
    // ePWM1
    miPeriod = 730;
    miPeriodFine = 1;
    miDutyA = 718;
    miDutyB = 250;
    // ePWM2
    miPeriodGrand = 512;
    miDutyGrand = 256;
    modo = 0b110;
    //###########################################################################
    EALLOW;
    InitSysCtrl(); // Initialize System Control:PLL, WatchDog, enable Peripheral Clocks
    EDIS;
    InitGpio(); // Configure default GPI
    InitEPwmGpio(); // EPWM1A and EPWM1B
    initSerialPins();
    ePWM[1] = &EPwm1Regs; // PWM Address Map
    ePWM[2] = &EPwm2Regs; // PWM Address Map
    // Clear all interrupts and initialize PIE vector table
    DINT;
    InitPieCtrl();
    IER = 0x0000;
    IFR = 0x0000;
    InitPieVectTable();
    EALLOW;
    PieVectTable.EPWM1_INT = &epwm1_isr;
    PieVectTable.EPWM2_INT = &epwm2_isr;
    EDIS;
    IER |= M_INT3; // Enable CPU INT3 which is connected to EPWM1-3 INT
    PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
    PieCtrlRegs.PIEIER3.bit.INTx2 = 1;
    EINT; // Enable Global interrupt INTM
    //###########################################################################
    // Config ePWM1 and ePWM2
    EALLOW;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
     I hope, I am the culprit :)

    Best regards

    Gustavo

  • Just looked over everything. THIS IS NOT A PROPAGATION delay from registers to pins. This is due to incorrect logic in your code. You are generating an interrupt for EPWM2, on the PERIOD/ZERO (since they are the same) of EPWM1. When you change interrupt select inside the EPWM1 interrupt, at zero/prd, an interrupt is generated for EPWM2 where pin is toggled. That is why you are seeing this behavior.

    Overall, if you toggle a pin in an interrupt, if you see it occur before the time you though it was going to occur, that means the interrupt was fired due to a flag not being cleared or an error in your logic. In this case I am thinking as soon as you change the source of the interrupt for EPWM2, inside EPWM1 ISR which occurs at ZERO/PERIOD, an interrupt is generated for EPWM2.

    Finally, the propagation delay from a device register to pins will NOT be that large. If you see a large delay, then your logic is not executing with the timing you assumed your logic was creating.

    Always glad to help you Gustavo.

    Nima Eskandari
  • Dear Nima,
    Many thanks for your valuable help.
    No doubt it is my code, the trouble maker. It is for me the first time I program a machine this deep and I am still learning how interrupts work.
    However, I do not understand your point. If changing INTSEL for EPWM2 inside the EPWM1-ISR generates an interrupt on EPWM2 before the counter on EPWM2 reaches the value of CMPC or CMPD, then this should occur much earlier, I suppose. Instead, this happens 35 periods of EPWM1 later.
    I expected EPWM2 to wait till CMPC or CMPD match the counter. Pin 56 is set inside the EPWM2-ISR.

    I realise now, that I have included the plot for EPWM1B, Is this, maybe provoking a confusion?

    To resume it short:

    EPWM2 fires an interrupt either on CMPC or on CMPD
    This behaviour is adjusted inside the EPWM1-ISR
    You say, because of this, EPWM2 fires the interrupt much earlier, which, in turn, toggles pin 56 (inside the EPWM2-ISR)
    If this was the case, shouldn’t we see the toggling of Pin56 soon after Pin61 goes HIGH and not 35 periods later?
    I was expecting EPWM2 to start looking for the next transition of CMPC or CMPD on EPWM2 and not to react on ZERO/PERIOD of EPWM1…

    I am now again far away from my prototype and cannot check it, but:

    To solve this:

    Should I first set EPwm2Regs.ETPS.bit.INTPRD = 0x0; inside the EPWM2-ISR
    and then set it to 0x1 again inside the EPWM1-ISR, just before changing EPwm2Regs.ETSEL.bit.INTSEL
    to avoid this?

    It would be like this (I have deleted irrelevant things):

    __interrupt void epwm2_isr(void)
    {
    EPwm2Regs.ETPS.bit.INTPRD = 0x0; // deactivate int on ePWM2. Reactvate it inside the EPWM1-ISR

    GpioDataRegs.GPBTOGGLE.bit.GPIO56 = 1;

    EPwm1Regs.ETCLR.bit.INT = 1; // Clear INT flag for ePWM1 timer
    EPwm1Regs.ETPS.bit.INTPRD = 0x2; // activate interrupt on second event on EPWM1

    EPwm2Regs.ETCLR.bit.INT = 1; // Clear INT flag for this timer
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; // Acknowledge this interrupt to receive more interrupts from group 3
    }

    __interrupt void epwm1_isr(void)
    {
    EPwm1Regs.ETPS.bit.INTPRD = 0x0; // deactivate int on ePWM1 until the next int on ePWM2

    if( modo == 0b110)
    {
    modo = 0b100; // Select INT 100 for the next Int on ePWM2: time-base counter equal to CMPC when the timer is incrementing
    }
    else
    {
    modo = 0b110; // Select INT 110 for the next Int on ePWM2: time-base counter equal to CMPD when the timer is incrementing
    }

    EPwm2Regs.ETPS.bit.INTPRD = 0x1; // activate int on ePWM2
    EPwm2Regs.ETSEL.bit.INTSEL = modo; // Change time-base counter on ePWM2
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; // Acknowledge this interrupt to receive more interrupts from group 3
    }

    I wish you a nice day,
    Gustavo
  • No the issue is that even though you have turned off interrupt for EPWM2, that doesn't mean that the interrupt flag did not get set. So when you enable the interrupt, since the flag was already set, the interrupt is immediately generated.
  • Hi Nima,
    I think, I found the reason for this problem. I do not have the solution, however:

    Following your idea, thet the ISR of ePWM1 was making trouble, I cleaned everything, leaving just the ePWM2-ISR. No Int on ePWM1, no interaction of ePWM1 with ePWM2.

    The ISR looks like this:

    Pin56 is my test pin

    __interrupt void epwm2_isr(void)
    {
    GpioDataRegs.GPBTOGGLE.bit.GPIO56 = 1;
    DELAY_US(1);
    GpioDataRegs.GPBTOGGLE.bit.GPIO56 = 1;
    DELAY_US(1);
    GpioDataRegs.GPBTOGGLE.bit.GPIO56 = 1;
    DELAY_US(1);

    EPwm2Regs.ETCLR.bit.INT = 1;
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    }


    The problem persists.
    The reason seems to be by the value of TBCTL.bit.CLKDIV
    Any value of CLKDIV higher than 0 causes the ISR to start earlier.
    But also any frequency lower than 1.14 kHz is problem.

    As I have in my code:
    TBPRD = 512
    EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0b100;
    EPwm2Regs.TBCTL.bit.CLKDIV = 0x4;
    Which I have set to get a very low freq (761 Hz).
    GPIO56 toggles 4.66 uS BEFORE the ePWM-Pin goes HIGH
    See the screenshotD

    Changing this to
    TBPRD = 512
    EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0b100;
    EPwm2Regs.TBCTL.bit.CLKDIV = 0x0;
    Which gives a higher freq (12.18 kHz).
    GPIO56 toggles 83.33 uS AFTER the ePWM-Pin goes HIGH
    See the screenshotE

    This problem starts when the frequency is lower than 1.14 kHz:

    Setting
    TBPRD = 0x1111
    EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0b101;
    EPwm2Regs.TBCTL.bit.CLKDIV = 0x0;
    Which gives a freq of 1.144 kHz.
    GPIO56 toggles EXACTLY with ePWM-Pin going HIGH
    See the screenshotF

    Setting
    TBPRD = 0x1111
    EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0b110;
    EPwm2Regs.TBCTL.bit.CLKDIV = 0x0;
    Which gives a freq of 953.3 kHz.
    GPIO56 toggles 83.3 nS BEFORE the ePWM-Pin goes HIGH
    See the screenshotG

    Now, I think I can solve this for me by using the event-trigger prescaling logic to get a lower interrupt frequency without setting CLKDIV higher than 0.
    However, I would like to know, if this behaviour is normal when using very low pwm frequencys.

    A nice day for you!
    Best regards,
    Gustavo

  • Gustavo,

    I just wrote some code to do what you want to do here but in a professional manner without missing any edges.
    Please refer to this code,

    e2e.ti.com/.../2770270

    Nima Eskandari
  • thanks a lot, Nima
    I will stick to your advise., this is great help!
    SIncerely,
    Gustavo