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: PWM update latency

Part Number: TMS320F28379D
Other Parts Discussed in Thread: C2000WARE

Hello,

 

My customer is using TMS320F28379D and having trouble with PWM output.

They are using CLA for updating EPWM_REGS shadow registers, ISR is triggered by ADC conversion complete.

 

ADC sampling period: 1us

PWM cycle : 0.2us

  

In the 1st screenshot above, there are 1us latency after CLA processing completion to PWM update (see ①)

When changing the ADC sampling period from 1us to 10us, the latency ① also becomes 10us. Please see the 2nd screenshot.

How can we reduce the latency?

 

 

Also, it looks like CLA processing results in period ② in the 1st screenshot are not reflected to the PWM output.

Are there any limitation?

 

Here are EPWM register settings.

==================

    EPwm1Regs.TBCTL.all = (EPwm1Regs.TBCTL.all & ~0x3FFF) | 0x38;

    EPwm1Regs.TBPRD = 19;              // Time Base Period Register

    EPwm1Regs.TBPHS.all = (EPwm1Regs.TBPHS.all & ~0xFFFF0000) | 0x0;

    EPwm1Regs.TBCTR = 0x0000;          /* Clear counter*/

    EPwm1Regs.CMPCTL.all = (EPwm1Regs.CMPCTL.all & ~0x5F) | 0x0;

    EPwm1Regs.CMPCTL2.all = (EPwm1Regs.CMPCTL2.all & ~0x50) | 0x0;

    EPwm1Regs.CMPA.bit.CMPA = 10;      // Counter Compare A Register

    EPwm1Regs.CMPB.bit.CMPB = 32000;   // Counter Compare B Register

    EPwm1Regs.CMPC = 32000;            // Counter Compare C Register

    EPwm1Regs.CMPD = 32000;            // Counter Compare D Register

    EPwm1Regs.AQCTLA.all = 146;        // Action Qualifier Control Register For Output A

    EPwm1Regs.AQCTLB.all = 2310;       // Action Qualifier Control Register For Output B

    EPwm1Regs.AQSFRC.all = (EPwm1Regs.AQSFRC.all & ~0xC0) | 0x0;

    EPwm1Regs.AQCSFRC.all = (EPwm1Regs.AQCSFRC.all & ~0xF) | 0x0;

    EPwm1Regs.DBCTL.all = (EPwm1Regs.DBCTL.all & ~0x803F) | 0x0;

    EPwm1Regs.DBRED.bit.DBRED = 0;     // Dead-Band Generator Rising Edge Delay Count Register

    EPwm1Regs.DBFED.bit.DBFED = 0;     // Dead-Band Generator Falling Edge Delay Count Register

    EPwm1Regs.ETSEL.all = (EPwm1Regs.ETSEL.all & ~0xFF7F) | 0x1001;

    EPwm1Regs.ETPS.all = (EPwm1Regs.ETPS.all & ~0x3303) | 0x1101;

    EPwm1Regs.PCCTL.all = (EPwm1Regs.PCCTL.all & ~0x7FF) | 0x0;

    EPwm1Regs.TZSEL.all = 0;           // Trip Zone Select Register

    EPwm1Regs.TZCTL.all = (EPwm1Regs.TZCTL.all & ~0xFFF) | 0xFFF;

    EPwm1Regs.TZEINT.all = (EPwm1Regs.TZEINT.all & ~0x7E) | 0x0;

    EPwm1Regs.DCACTL.all = (EPwm1Regs.DCACTL.all & ~0x30F) | 0x4;

    EPwm1Regs.DCBCTL.all = (EPwm1Regs.DCBCTL.all & ~0x30F) | 0x0;

    EPwm1Regs.DCTRIPSEL.all = (EPwm1Regs.DCTRIPSEL.all & ~ 0xFFFF) | 0x1010;

    EPwm1Regs.TZDCSEL.all = (EPwm1Regs.TZDCSEL.all & ~0xFFF) | 0x0;

    EPwm1Regs.DCFCTL.all = (EPwm1Regs.DCFCTL.all & ~0x3F) | 0x10;

    EPwm1Regs.DCFOFFSET = 0;           // Digital Compare Filter Offset Register

    EPwm1Regs.DCFWINDOW = 0;           // Digital Compare Filter Window Register

    EPwm1Regs.DCCAPCTL.all = (EPwm1Regs.DCCAPCTL.all & ~0x1) | 0x0;

    EPwm1Regs.HRCNFG.all = (EPwm1Regs.HRCNFG.all & ~0xA0) | 0x0;

    EPwm1Regs.EPWMXLINK.bit.TBPRDLINK = 0;

    EPwm1Regs.EPWMXLINK.bit.CMPALINK = 0;

    EPwm1Regs.EPWMXLINK.bit.CMPBLINK = 0;

    EPwm1Regs.EPWMXLINK.bit.CMPCLINK = 0;

    EPwm1Regs.EPWMXLINK.bit.CMPDLINK = 0;

==================

 

 

Thanks & Regards,

-Shibata

 

 

  • Hi,

    Since you mention that the latency increase to 10us when the ADC sampling period changes to 10 us so it clearly suggests that the current sensed value is actually getting processed in the next ISR instead of current one or the PWM period and duty values are getting updated on next events. Did you try using the immediate load option instead of shadowed one for EPWM updates just to debug the root-cause?

    As such there are no limitations in terms of EPWM updates by CLA, you can also look into the latest CLA examples that we provide inside C2000Ware which showcases the sensing and actuation with standalone CLA at a high frequency. Although these examples are for F28004x device but probably could be a good reference for your development

    C:\ti\c2000\C2000Ware_<version_number>\driverlib\f28004x\examples\cla

    Also there is an Application Report based on the above examples on CLA: 

    If my reply answers your question please click on "This resolved my issue" button located at the bottom of my post.

    Regards

    Himanshu

  • Hi Himanshu,

     

    Thanks to your comments, customer found the rootcause.

    They read ADC value and set to an variable by C28x, and then passed it to CLA.

    That causes the delay and the previous ADC value was used for PWM calculation in CLA.

    After changing the implementation to read ADC register by CLA directly, the latency in ① and ② disappeared.

     

    Now here is another question with the new implementation.

    They are using 0.6us CPU timer interrupt, and ADC value is set to variable abc in TINT0_isr.

    But it looks like abc is not updated during period ②.

    Do you have any idea why?

     

    Please find timer ISR and timer configuration code below:

    =========================== 

    interrupt void TINT0_isr(void)

    {

          #ifdef PIEMASK0

            volatile unsigned int PIEIER1_stack_save = PieCtrlRegs.PIEIER1.all;

          #endif

     

          #ifdef PIEMASK0

            PieCtrlRegs.PIEIER1.all &= ~PIEMASK0;      /* disable group1 lower/equal priority interrupts */

          #endif

             

          asm(" RPT #5 || NOP");               /* wait 5 cycles */

          IFR &= ~IFRMASK;                           /* eventually disable lower/equal priority pending interrupts */

          PieCtrlRegs.PIEACK.all = IFRMASK;          /* ACK to allow other interrupts from the same group to fire */

          IER |= 1;

          EINT;                                /* global interrupt enable */

          rt_OneStep();                        //← There is a line “adc = (AdcaResultRegs.ADCRESULT0)” in this function.

          DINT;                                /* disable global interrupts during context switch, CPU will enable global interrupts after exiting ISR */

          #ifdef PIEMASK0

            PieCtrlRegs.PIEIER1.all = PIEIER1_stack_save;/*restore PIEIER register that was modified */

          #endif 

    }

     

     

    void configureTimer0(float baseRate, float systemClock)         //←baseRate=6.0E-7[s]、systemClock=200[MHz] here.

    {

        #ifdef CPU1

            EINT;

            uint32_t ipcCountVar = 0;

            if (0x425 == mwInitStart)

            {

                /* Wait until completion of CPU2 GPIO initialization */

                while ((0x36E != mwInitEnd))

                {

                    ipcCountVar++;

                }

            }

        DINT;

            #ifndef MW_EXEC_PROFILER_ON

        CpuTimer0.RegsAddr = &CpuTimer0Regs;

        CpuTimer0Regs.PRD.all  = 0xFFFFFFFF;

        CpuTimer0Regs.TPR.all  = 0;

        CpuTimer0Regs.TPRH.all = 0;

        CpuTimer0Regs.TCR.bit.TSS = 1;

        CpuTimer0Regs.TCR.bit.TRB = 1;

        CpuTimer0.InterruptCount = 0;

            #endif

            ConfigCpuTimer(&CpuTimer0, systemClock, baseRate * 1000000);

            StartCpuTimer0();

     

            EALLOW;

            PieVectTable.TIMER0_INT = &TINT0_isr;     /* Hook interrupt to the ISR*/

            EDIS;

     

            PieCtrlRegs.PIEIER1.bit.INTx7 = 1;   /* Enable interrupt TINT0 */

            IER |= M_INT1;

    }

    =========================== 

    Best regards,

    -Shibata

  • Hi,

    Good to know that the earlier issue was resolved. Regarding the new issue, I have couple of questions below to help debug the configuration:

    • Have you tested that timer interrupt is getting triggered correctly, does the program enters the timer ISR every time?
    • If the answer to above question is yes and if the variable 'adc' is not getting updated then is the optimization enabled for the project? Because in that case better to declare the variable with "volatile" keyword

    If my reply answers your question please click on "This resolved my issue" button located at the bottom of my post.

    Regards

    Himanshu

  • Hello Himanshu,

     

    I will update you once I get the feedback from customer.

     

    Best regards,

    -Shibata

  • Hello,

    Okay sure please keep us posted if the issue got resolved.

    If my reply answers your question please click on "This resolved my issue" button located at the bottom of my post.

    Regards

    Himanshu