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.

epwm register changes are not applied

I'm trying to have two blocks of 3 PWMs each. The first 3 should be synchronized to each other while the other 3 should be shifted by a half period. For this purpose I decided to manipulate the PWM_INIT_MACRO() from the example PM_Sensorless.

The 3d ePWM from the first block should generate a synchronization event when it reaches the Period-Value (in Up-Down count mode). At this point, the following PWMs load 0 to their counter and will be delayed by 180°.

But right after execution of  the PWM_INIT_MACRO() both SYNCOSEL and PHSEN are 0, so the changes are not applied and the code doesn't work. If I apply the changes manually in debug mode, it works. Why are the values not applied to the registers, or are there any other write-commands that cause a reset of the register?

The Code I use is here below, it's almost identical to the example code:

#define PWM_INIT_MACRO(m)                                                    \
         /* Setup Sync*/                                                    \
         m->PwmARegs->TBCTL.bit.SYNCOSEL = 0;       /* Pass through sync-signal to next ePWM*/            \
         m->PwmBRegs->TBCTL.bit.SYNCOSEL = 0;       /* Pass through sync-signal to next ePWM*/            \
         m->PwmCRegs->TBCTL.bit.SYNCOSEL = 2;       /* Sync-Event for next ePWM at Counter = Period. Following ePWMs will have 50% Phase delay */            \
                                                                            \
         /* Allow each timer to be sync'ed*/                                \
         m->PwmARegs->TBCTL.bit.PHSEN = 1;            /*Enable Phase Load */        \
         m->PwmBRegs->TBCTL.bit.PHSEN = 1;                                        \
         m->PwmCRegs->TBCTL.bit.PHSEN = 1;                                        \
                                                                            \
         /* Init Timer-Base Period Register for EPWM1-EPWM3*/                \
         m->PwmARegs->TBPRD = m->pwm.PeriodMax;                                        \
         m->PwmBRegs->TBPRD = m->pwm.PeriodMax;                                        \
         m->PwmCRegs->TBPRD = m->pwm.PeriodMax;                                        \
                                                                            \
         /* Init Timer-Base Phase Register for EPWM1-EPWM3 (Value loaded to Counter on Sync-Event)*/                \
         m->PwmARegs->TBPHS.half.TBPHS = 0;                                    \
         m->PwmBRegs->TBPHS.half.TBPHS = 0;                                    \
         m->PwmCRegs->TBPHS.half.TBPHS = 0;                                    \
                                                                            \
         /* Init Timer-Base Control Register for EPWM1-EPWM3*/                \
         m->PwmARegs->TBCTL.all = PWM_INIT_STATE;    /* Count Up-Down, After Sync start with up Count,... */                            \
         m->PwmBRegs->TBCTL.all = PWM_INIT_STATE;                                \
         m->PwmCRegs->TBCTL.all = PWM_INIT_STATE;                                \
                                                                            \
         /* Init Compare Control Register for EPWM1-EPWM3*/                    \
         m->PwmARegs->CMPCTL.all = CMPCTL_INIT_STATE;        /*Load from Shadowed Registers when Counter is at 0*/                    \
         m->PwmBRegs->CMPCTL.all = CMPCTL_INIT_STATE;                            \
         m->PwmCRegs->CMPCTL.all = CMPCTL_INIT_STATE;                            \
                                                                            \
         /* Init Action Qualifier Output A Register for EPWM1-EPWM3*/        \
         m->PwmARegs->AQCTLA.all = AQCTLA_INIT_STATE;        /* SET when counting Up, CLEAR when counting down*/                    \
         m->PwmBRegs->AQCTLA.all = AQCTLA_INIT_STATE;                            \
         m->PwmCRegs->AQCTLA.all = AQCTLA_INIT_STATE;                            \
                                                                            \
         /* Init Dead-Band Generator Control Register for EPWM1-EPWM3*/        \
         m->PwmARegs->DBCTL.all = DBCTL_INIT_STATE;        /* Enable Dead-Band Module, Dead-Band (both signals low during this time) */            \
         m->PwmBRegs->DBCTL.all = DBCTL_INIT_STATE;                            \
         m->PwmCRegs->DBCTL.all = DBCTL_INIT_STATE;                            \
                                                                            \
         /* Init Dead-Band Generator for EPWM1-EPWM3*/                        \
         m->PwmARegs->DBFED = DBCNT_INIT_STATE;            /* Set number of delay-counts between switching edges */                \
         m->PwmARegs->DBRED = DBCNT_INIT_STATE;                                \
         m->PwmBRegs->DBFED = DBCNT_INIT_STATE;                                \
         m->PwmBRegs->DBRED = DBCNT_INIT_STATE;                                \
         m->PwmCRegs->DBFED = DBCNT_INIT_STATE;                                \
         m->PwmCRegs->DBRED = DBCNT_INIT_STATE;                                \
                                                                            \
         /* Init PWM Chopper Control Register for EPWM1-EPWM3*/                \
         m->PwmARegs->PCCTL.all = PCCTL_INIT_STATE;            /* No PWM-Chopping*/                \
         m->PwmBRegs->PCCTL.all = PCCTL_INIT_STATE;                            \
         m->PwmCRegs->PCCTL.all = PCCTL_INIT_STATE;                            \
                                                                            \
         EALLOW;                       /* Enable EALLOW */                    \
                                                                            \
         /* Init Trip Zone Select Register*/                                \
         m->PwmARegs->TZSEL.all = TZSEL_INIT_STATE;                            \
         m->PwmBRegs->TZSEL.all = TZSEL_INIT_STATE;                            \
         m->PwmCRegs->TZSEL.all = TZSEL_INIT_STATE;                            \
                                                                             \
         /* Init Trip Zone Control Register*/                                \
         m->PwmARegs->TZCTL.all = TZCTL_INIT_STATE;                            \
         m->PwmBRegs->TZCTL.all = TZCTL_INIT_STATE;                            \
         m->PwmCRegs->TZCTL.all = TZCTL_INIT_STATE;                            \
                                                                            \
         EDIS;                         /* Disable EALLOW*/   

  • Hello Frau Haggenmacher,

    Thoughts:
    1) make sure you do a Rebuild All.  Sometimes the IDE is not completely competent when the header files changes (and the header file contains macroed source code).
    2) Make sure that m is defined as the PWMs you wish to edit.  Is any of the code in your edited file correctly writing registers?
    3) May be a bad comment, but you may also want to double-check that CCS is looking at your edited version vs the library version.

    ===

    Aside: I would recommend having the first PWM be the master PWM and then all other PWMs synch to it - the other two (in your first group of three) having no offset; the other set of three with a 180degree offset.


    Thank you,
    Brett

  • Hi Brett,

    thanks for your comments, actually it helped me to double check the code and I found the reason for the changes not to be applied: shortly after writing to single bits of the TBCTL register, the whole register is written. Since this part of code comes from the PM_Sensorless example, I suggest TI should revise the code...
    But anyway: I think I will follow your suggestion and synchronize all PWM to the same source and just add the phase shift to the synchronization value.

    Best regards
    Nicola

    PS: I don't know where you got the "Frau" from, but let me tell you that you got it wrong ;-)
  • Glad to have helped.

    On the P.S. note:  Sorry about this.  :(


    -Brett

  • Hi,

    I finally implemented the PWM-Groups with 180° phase delay, but it cost me some time since the behavior wasn't as expected.

    First I tried to pass through the SYNC signal to all ePWM Modules (SYNCOSEL = 0) and synchronize them all by writing a ePWM1.TBCTL.bit.SWSYNC = 1. The first group of PWM had to load 0 into the counter while the second group had to load the same value as in the TBPRD register, resulting in a 180° phase shift. But this did not work: the phase shift was not 180° and even worse, it changed every time I triggered SWSYNC !  I even tried to Synchronize all the clocks by deactivating and re-activating TBCLKSYNC, with no effect at all.

    What I found out as a working solution is to synchronize all the PWMs from the first group to TBCTR = 0 (SYNCOSEL = 1) and to pass through the sync-signal in the second group (SYNCOSEL = 0). The value in TBPHS remains 0 for the first ones and TBPRD for the latter.

    The Scope image shows now that both the PWMs and the ISR that are triggered by the PWM have 180° phase shift. Signals 1 and 3 show the signal of ePWM1 and ePWM4. Signal 2 and 4 show the duration of the execution of the ISR which is triggered at TBCTR = 0 of ePWM1 or ePWM4 respectively (ISR starts in the middle of the LOW-time of the pwm, at the same time the ADC is also triggered, current in phase A & B is measured).

  • Hello Herr Haggenmacher,

    Glad you were able to figure it out! 

    As you likely found, Figure 3-5 and Figure 3-7 in the current F2806x TRM are often helpful for comprehending ePWM synchronization.


    Thank you,
    Brett