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.

TMS320F280049: Can not realize HRPWM

Part Number: TMS320F280049
Other Parts Discussed in Thread: C2000WARE

Hi experts,

My customer used the HRPWM demo of C2000Ware_3_04_00_00, but found the HRPWM did not enabled. The configuration is the same as demo:

int MEP_ScaleFactor; // Global variable used by the SFO library

                     // Result can be used for all HRPWM channels

                     // This variable is also copied to HRMSTEP

                     // register by SFO() function.

 

volatile struct EPWM_REGS *ePWM[] = {0, &EPwm1Regs, &EPwm2Regs};

while(status == SFO_INCOMPLETE)

    {

        status = SFO();

        if(status == SFO_ERROR)

        {

            //error();   // SFO function returns 2 if an error occurs & # of MEP

        }              // steps/coarse step exceeds maximum of 255.

    }

 

       SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    initHRPWM(LLC_PWM_PER_DFT);

       SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

When calling HRPWM, they do not use the automatic compensation function, but rather calculate the compensation 'compCount' themselves:

HRPWM_setTimeBasePeriod(EPWM1_BASE, compCount);

They compared the codes with our demo, they were the same. However, HRPWM  still could not be implemented.

Could you help with this? Thank you in advance!

  • When they use the demo code on their HW without any HRPWM setting changes, does it work properly?

  • It works properly when using the demo code.

  • They use 'hrpwm_ex3_prd_updown_sfo' demo. It works properly without any change.

  • Then the issue exists within the HRPWM value calculation.

    Can they validate the registers by capturing the TBPRD and TBPRDHR? This can ensure the right value is written to the registers.

    Have the customer check Registers view in CCS after the HRPWM_setTimeBasePeriod(EPWM1_BASE, compCount);

  • PWM frequency=1.5MHz,

    TBPRD0x21

    TBPRDHR: 0x1300

  • Are those the values they expected to write to the registers?

    Everything comes down to how they are doing their calculation. 

    Is there NO HR part at all on the waveform?

    Nima

  • Hi Nima,

    Those values are what they expected. This is the same both in the demo codes and in their codes. 

    From the waveform, with the same 1.5MHz, the test result of demo is 1.5006MHz, the test result of their codes is 1.513317MHz. This value is the same as without HR.

    I put part of their codes here for your reference:

    #include "SFO_V8.h"

    void InitEPwm1Gpio(void)

    {

       EALLOW;

     

    /* Disable internal pull-up for the selected output pins

       for reduced power consumption */

    // Pull-ups can be enabled or disabled by the user.

    // Comment out other unwanted lines.

     

    // 0: Pull-up enabled  1: Pull-up disabled

        GpioCtrlRegs.GPAPUD.bit.GPIO0 = 1;    // Disable pull-up on GPIO0 (EPWM1A)

        GpioCtrlRegs.GPAPUD.bit.GPIO1 = 1;    // Disable pull-up on GPIO1 (EPWM1B)

       

     

    /* Configure EPWM-1 pins using GPIO regs*/

    // This specifies which of the possible GPIO pins will be EPWM1 functional pins.

    // Comment out other unwanted lines.

     

        GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;   // Configure GPIO0 as EPWM1A    pin79

        GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;   // Configure GPIO1 as EPWM1B    pin78

     

        EDIS;

    }

    void initHRPWM(UInt32 period)

    {

    #if 1

        EPWM_setEmulationMode(EPWM1_BASE, EPWM_EMULATION_FREE_RUN);

     

        //

        // Set-up TBCLK

        //

        EPWM_setPeriodLoadMode(EPWM1_BASE, EPWM_PERIOD_SHADOW_LOAD);

        EPWM_setTimeBasePeriod(EPWM1_BASE, period-1);

        EPWM_setPhaseShift(EPWM1_BASE, 0U);

        EPWM_setTimeBaseCounter(EPWM1_BASE, 0U);

     

        //

        // set duty 50% initially

        //

        HRPWM_setCounterCompareValue(EPWM1_BASE, HRPWM_COUNTER_COMPARE_A, (period/2 << 8));

        HRPWM_setCounterCompareValue(EPWM1_BASE, HRPWM_COUNTER_COMPARE_B, (period/2 << 8));

     

     

        //

        // Set up counter mode

        //

        EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP_DOWN);

        EPWM_disablePhaseShiftLoad(EPWM1_BASE);

        EPWM_setClockPrescaler(EPWM1_BASE,

                               EPWM_CLOCK_DIVIDER_1,

                               EPWM_HSCLOCK_DIVIDER_1);

        EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_DISABLED);

     

        //

        // Set up shadowing

        //

        EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE,

                                             EPWM_COUNTER_COMPARE_A,

                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);

        EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE,

                                             EPWM_COUNTER_COMPARE_B,

                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);

     

        //

        // Set actions

        //

     

        EPWM_setActionQualifierAction(EPWM1_BASE,

                                      EPWM_AQ_OUTPUT_A,

                                      EPWM_AQ_OUTPUT_HIGH,

                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

     

     

        EPWM_setActionQualifierAction(EPWM1_BASE,

                                      EPWM_AQ_OUTPUT_B,

                                      EPWM_AQ_OUTPUT_HIGH,

                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);

     

        EPWM_setActionQualifierAction(EPWM1_BASE,

                                      EPWM_AQ_OUTPUT_A,

                                      EPWM_AQ_OUTPUT_LOW,

                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);

        EPWM_setActionQualifierAction(EPWM1_BASE,

                                      EPWM_AQ_OUTPUT_B,

                                      EPWM_AQ_OUTPUT_LOW,

                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);

     

     

        HRPWM_setMEPEdgeSelect(EPWM1_BASE, HRPWM_CHANNEL_A, HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE);

        HRPWM_setMEPControlMode(EPWM1_BASE, HRPWM_CHANNEL_A, HRPWM_MEP_DUTY_PERIOD_CTRL);

        HRPWM_setCounterCompareShadowLoadEvent(EPWM1_BASE, HRPWM_CHANNEL_A, HRPWM_LOAD_ON_CNTR_ZERO_PERIOD);

     

        HRPWM_setMEPEdgeSelect(EPWM1_BASE, HRPWM_CHANNEL_B, HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE);

        HRPWM_setMEPControlMode(EPWM1_BASE, HRPWM_CHANNEL_B, HRPWM_MEP_DUTY_PERIOD_CTRL);

        HRPWM_setCounterCompareShadowLoadEvent(EPWM1_BASE, HRPWM_CHANNEL_B, HRPWM_LOAD_ON_CNTR_ZERO_PERIOD);

     

        HRPWM_disableAutoConversion(EPWM1_BASE);

     

        //

        // Turn on high-resolution period control.

        //

     

        HRPWM_enablePeriodControl(EPWM1_BASE);

        HRPWM_enablePhaseShiftLoad(EPWM1_BASE);

     

        EPWM_forceSyncPulse(EPWM1_BASE);

    #endif

    }

    while(status == SFO_INCOMPLETE)

        {

            status = SFO();

            if(status == SFO_ERROR)

            {

                //error();   // SFO function returns 2 if an error occurs & # of MEP

            }              // steps/coarse step exceeds maximum of 255.

        }

     

        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

        /* Initialize Peripherals :*/

        //Periphcfg();//

        initHRPWM(LLC_PWM_PER_DFT);

    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

     

    fPWMperiod = 100000000/fPWMFreqtest/2.0f;/* fPWMFreqtest = 1.5MHz = 1500000*/

        fPWMperiodFrac = fPWMperiod - (UInt16)(fPWMperiod);

       

        count = (UInt16)(fPWMperiodFrac*256*56+128)>>8;

       

        //EPwm1Regs.TBPRD = (UInt16)(fPWMperiod);

        //EPwm1Regs.TBPRDHR = (UInt16)count<<8;

     

     

        compCount = (((UInt16)fPWMperiod) << 8UL) + count;

        HRPWM_setTimeBasePeriod(EPWM1_BASE, compCount);

     

        //EPwm1Regs.CMPA.bit.CMPAHR        = (UInt16)(fPWMperiod*0.5);  /* Set PWM duty as 50% */

        //EPwm1Regs.CMPB.bit.CMPBHR        = (UInt16)(fPWMperiod*0.5);  /* Set PWM duty as 50% */

       

        status = SFO(); // in background, MEP calibration module

                                   // continuously updates MEP_ScaleFactor

       

        if (status == SFO_ERROR)

        {

            //error();   // SFO function returns 2 if an error occurs & #                               // of MEP steps/coarse step

        }

     

  •     EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE,

                                             EPWM_COUNTER_COMPARE_A,

                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);

        EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE,

                                             EPWM_COUNTER_COMPARE_B,

                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);

    They need to be on both ZERO and PRD.

    HRPWM_disableAutoConversion(EPWM1_BASE);

     

    If they enable this, everything works as expected?

  •     EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE,

                                             EPWM_COUNTER_COMPARE_A,

                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);

        EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE,

                                             EPWM_COUNTER_COMPARE_B,

                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);

    They need to be on both ZERO and PRD.

    But in our demo, they both load on ZERO. Which one need to be on PRD?

  • HRPWM_disableAutoConversion(EPWM1_BASE);

    If they enable this, everything works as expected?

    They have tried to enable this, HR did not work.

  • I'm a bit confused Angela. IF the example originally provided works, and the customer has only switched from AUTO-CONVERT to manual convert, then how come switching back to AUTO-CONVERT does not work?

  • Hi Nima,

    Both mode in the demo works well. But they migrated this part into their own codes, both modes could not work.

  • Okay then lets first get the AUTO-CONVERT mode to work in their setup. Share the PINMUX, SFO calling, and EPWM Init Code.

    Nima

  • Hi Nima,

    Please check the configuration:

    1.PINMUX:

    void InitEPwm1Gpio(void)

    {

       EALLOW;

     

    /* Disable internal pull-up for the selected output pins

       for reduced power consumption */

    // Pull-ups can be enabled or disabled by the user.

    // Comment out other unwanted lines.

     

    // 0: Pull-up enabled  1: Pull-up disabled

        GpioCtrlRegs.GPAPUD.bit.GPIO0 = 1;    // Disable pull-up on GPIO0 (EPWM1A)

        GpioCtrlRegs.GPAPUD.bit.GPIO1 = 1;    // Disable pull-up on GPIO1 (EPWM1B)

       

     

    /* Configure EPWM-1 pins using GPIO regs*/

    // This specifies which of the possible GPIO pins will be EPWM1 functional pins.

    // Comment out other unwanted lines.

     

        GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;   // Configure GPIO0 as EPWM1A    pin79

        GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;   // Configure GPIO1 as EPWM1B    pin78

     

        EDIS;

    }

    2.EPWM Init

    EPwm1Regs.TBCTL.bit.PRDLD      = TB_SHADOW;         /* Set Shadow load */

        EPwm1Regs.TBCTL2.bit.PRDLDSYNC = 0;                  /*must add sync point for load if need large delay*/

        EPwm1Regs.TBCTL.bit.CTRMODE    = TB_COUNT_UPDOWN;   /* Count-up mode */

        EPwm1Regs.TBCTL.bit.PHSEN      = TB_DISABLE;        /* Disable phase loading */

        EPwm1Regs.TBCTL.bit.SYNCOSEL   = TB_CTR_ZERO;       /* Sync Output Select: TBCTR = 0x00 */

        EPwm1Regs.TBCTL.bit.HSPCLKDIV  = TB_DIV1;           /* TBCLK = EPWMCLK / (HSPCLKDIV x CLKDIV) */

        EPwm1Regs.TBCTL.bit.CLKDIV     = TB_DIV1;           /*       = 100MHz / (1*1) = 100MHz */

        EPwm1Regs.TBPRD                = LLC_PWM_PER_DFT;   /* PWM frequency = 60kHz */

     

        EPwm1Regs.CMPA.bit.CMPA        = LLC_PWM_DUTY_DFT;  /* Set PWM duty as 50% */

        EPwm1Regs.CMPA.bit.CMPAHR      = (1 << 8);    // initialize HRPWM extension

        EPwm1Regs.CMPB.bit.CMPB        = LLC_PWM_DUTY_DFT;  /* Set PWM duty as 50% */

        EPwm1Regs.CMPB.all |= 1;

        EPwm1Regs.CMPC                 = LLC_PWM_DUTY_DFT + 7;

        EPwm1Regs.CMPD                 = 7;

     

        EPwm1Regs.TBCTL.bit.FREE_SOFT  = 3;

     

        EPwm1Regs.TBPHS.all            = 0;                  /* Set as master, phase =0 */

        EPwm1Regs.TBCTR                = 0;                 /* Time base counter =0 */

     

        EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;       /* Load on CTR=PRD */

        EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;       /* Load on CTR=PRD */

        EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;         /* Shadow mode. Operates as a double buffer. */

        EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;         /* Shadow mode. Operates as a double buffer. */

     

        EPwm1Regs.AQCTLA.bit.CAU       = AQ_SET;            /* Set PWM1A on Zero */

        EPwm1Regs.AQCTLA.bit.CBD       = AQ_CLEAR;          /* Clear PWM1A on event A, up count */

        EPwm1Regs.AQCTLB.bit.CAU       = AQ_SET;            /* Set PWM1B on Zero */

        EPwm1Regs.AQCTLB.bit.CBD       = AQ_CLEAR;          /* Clear PWM1B on event B, up count */

     

        EPwm1Regs.AQSFRC.bit.RLDCSF    = 3;                 /* When software Force event come,Load immediately */

     

     

        EPwm1Regs.DBCTL.bit.IN_MODE    = DBA_RED_DBB_FED;   /* EPWMxA is the source for both delays */

        EPwm1Regs.DBCTL.bit.OUT_MODE   = DB_FULL_ENABLE;    /* Enable Dead-band module */

        EPwm1Regs.DBCTL.bit.POLSEL     = DB_ACTV_HIC;       /* Active High Complementary (AHC) */

        EPwm1Regs.DBCTL.bit.SHDWDBREDMODE = 1;              /*enable shadow mode of DB*/

        EPwm1Regs.DBCTL.bit.LOADREDMODE = 1;                /*load shadow on prd*/

        EPwm1Regs.DBCTL.bit.SHDWDBFEDMODE = 1;              /*enable shadow mode of DB*/

        EPwm1Regs.DBCTL.bit.LOADFEDMODE = 1;                /*load shadow on prd*/

     

        EPwm1Regs.DBRED.bit.DBRED      = LLC_INIT_DEADBAND; /* RED = 10 TBCLKs initially */

        EPwm1Regs.DBFED.bit.DBFED      = LLC_INIT_DEADBAND; /* FED = 10 TBCLKs initially */

     

     

        EPwm1Regs.AQCSFRC.bit.CSFA     = 1;                 /* Disable EPWM1A output */

        EPwm1Regs.AQCSFRC.bit.CSFB     = 2;                 /* Disable EPWM1B output */

     

        EALLOW;

        EPwm1Regs.HRCNFG.all = 0x0;

        EPwm1Regs.HRCNFG.bit.EDGMODE   = HR_BEP;          // MEP control on both edges.

        EPwm1Regs.HRCNFG.bit.CTLMODE   = HR_CMP;          // CMPAHR and TBPRDHR HR control.

        EPwm1Regs.HRCNFG.bit.HRLOAD    = HR_CTR_ZERO_PRD; // load on CTR = 0 and CTR = TBPRD

        EPwm1Regs.HRCNFG.bit.EDGMODEB  = HR_BEP;      // MEP control on both edges

        EPwm1Regs.HRCNFG.bit.CTLMODEB  = HR_CMP;      // CMPBHR and TBPRDHR HR control

        EPwm1Regs.HRCNFG.bit.HRLOADB   = HR_CTR_ZERO_PRD; // load on CTR = 0 and CTR = TBPRD

        EPwm1Regs.HRCNFG.bit.AUTOCONV  = 1;               // Enable autoconversion for HR period

        EPwm1Regs.HRPCTL.bit.TBPHSHRLOADE = 1;   // Enable TBPHSHR sync

                             // (required for updwn

                             //  count HR control)

        EPwm1Regs.HRPCTL.bit.HRPE = 1;          // Turn on high-resolution

                             // period control.

     

        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;   // Enable TBCLK within

                             // the EPWM

        EPwm1Regs.TBCTL.bit.SWFSYNC = 1;        // Synchronize high

                                     // resolution phase to

                                     // start HR period

        EDIS;

    3. SFO calling

    They use as our demo code.

  •     EPwm1Regs.AQCTLA.bit.CAU       = AQ_SET;            /* Set PWM1A on Zero */

        EPwm1Regs.AQCTLA.bit.CBD       = AQ_CLEAR;          /* Clear PWM1A on event A, up count */

        EPwm1Regs.AQCTLB.bit.CAU       = AQ_SET;            /* Set PWM1B on Zero */

        EPwm1Regs.AQCTLB.bit.CBD       = AQ_CLEAR;          /* Clear PWM1B on event B, up count */

    Is the second line supposed to be CAD? Not CBD?

  • EPwm1Regs.AQCTLA.bit.CAU       = AQ_SET;            /* Set PWM1A on Zero */

    EPwm1Regs.AQCTLA.bit.CBD       = AQ_CLEAR;          /* Clear PWM1A on event A, up count */

    These two lines indicate that for PWMA. In the up count mode, the PWMA output  high when the counter = CMPA. In the down count mode, PWMA output  low when counter = CMPB.

  • Hi Nima,

    As the customer can not send us the whole project, could you put these codes in your project to reproduce the issue? 

  • I dont believe that will result in correct behavior. CAU and CAD should be used together if I remember this correctly. Can you try this and see if it resolves the issue?

    Also you have sent me both driverlib code and bitfield code. Which one is the customer using? 

    Also this:

    EPwm1Regs.AQCTLA.bit.CBD       = AQ_CLEAR;          /* Clear PWM1A on event A, up count */

    Is different from the original example, so the AUTO-CONVERT is not the only change the customer has made. Are there any other changes?

  • I think customer use both  driverlib and bitfield. In their old project, they used bit field, but they did not add HRPWM. So only the HRPWM part used driverlib.

  • EPwm1Regs.AQCTLA.bit.CBD       = AQ_CLEAR;          /* Clear PWM1A on event A, up count *

    Understood, please have them change this back to CAD and the HR portion should work. With AUTO-CONVERT