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.

TMS320F28027: Limitation of HRPWM duty cycle

Part Number: TMS320F28027

               I work with a TI piccolo TMS320F28027. I have a problem that I can’t explain yet without your help. I think it is the duty cycle range limitation who cause my problem:
               My scheme is a buck converter control by the MCU. I try to put duty cycle to 0 to ensure inhibition of buck. I am in standby Mode. In all the product we made (more than 30000), I don’t see my problem except on one product. I see a duty cycle of 50ns every 0,5ms (2KHz). My switch frequency is at 100KHz. I don’t understand this little pulse at 2KHz. Perhaps it come from the duty cycle range limitation where the first three cycle are undefined behavior on the ePWMxA output.
               So is this duty cycle range limitation could create a repetitive duty cycle when I want 0%? Is it repeatable or random?

  • Hi Barsanges Arnaud,

    If you disable the HRPWM features on this device, does the glitch still happen?
    How are you setting the duty cycle to 0%?
    What is your SYSCLK frequency?
    Are you using any other features such as deadband? A general overview of the configuration would be helpful.

    Regards,
    Kris
  •   Hello Kris,

       My problem appears only on one product. On the 29999 same other products, I don't see this pulse when I put the PWM in standBy mode at 0%.

    I just want to know if it is possible that the PWM could create this pulse at 2KHz if it is turn ON and value is at 0 because the duty cycle was unknown during the first three cycle? My PWM is at 100KHz.

       To set duty cycle, I use PID loop with variable. I enter IQ(-0.2) for setpoint of the loop:  

      RampeSoftStart_Buck1.TargetValue = INIT_RAMPE;  
      RampeSoftStart_Buck1.SetpointValue = INIT_RAMPE;

      To ensure the PID don't cause this pulse, we put a short circuit on the ADC measurement of voltage without change on PWM output, so there are no interference.

      The config of the PWM is (2 PWM interleaved so its only the config of PWM1 below)

    void HRPWM1_Config(Uint16 period1)
    {
     /* ePWM1 register configuration with HRPWM
      ePWM1A toggle low/high with MEP control on Rising edge
      Setup TBCLK */
     EALLOW;

     EPwm1Regs.TBCTL.bit.PRDLD   = TB_IMMEDIATE;  /* set Immediate load */
     EPwm1Regs.TBPRD     = period1 - 1;  /* PWM frequency = 1 / period */
     /* Set Compare values */
     EPwm1Regs.CMPA.half.CMPA   = 0U;     /* set duty 50% initially */
        EPwm1Regs.CMPA.half.CMPAHR   = 0U;     /* initialize HRPWM extension */
     EPwm1Regs.CMPB      = 0U;     /* set duty 50% initially */
     EPwm1Regs.TBPHS.all    = 0U;
     EPwm1Regs.TBCTR     = 0U;

     /* Setup counter mode */
     EPwm1Regs.TBCTL.bit.CTRMODE  = TB_COUNT_UP;
     EPwm1Regs.TBCTL.bit.PHSEN   = TB_DISABLE;
     EPwm1Regs.TBCTL.bit.SYNCOSEL  = ET_CTR_PRD;  
     EPwm1Regs.TBCTL.bit.HSPCLKDIV  = TB_DIV1;
     EPwm1Regs.TBCTL.bit.CLKDIV   = TB_DIV1;

     /* Setup shadowing */
     EPwm1Regs.CMPCTL.bit.LOADAMODE  = CC_CTR_ZERO;
     EPwm1Regs.CMPCTL.bit.LOADBMODE  = CC_CTR_ZERO;
     EPwm1Regs.CMPCTL.bit.SHDWAMODE  = CC_SHADOW;
     EPwm1Regs.CMPCTL.bit.SHDWBMODE  = CC_SHADOW;


     /* Set actions PWM toggle low/high */
     EPwm1Regs.AQCTLA.bit.ZRO   = AQ_SET;  /* PWM toggle low/high */
     EPwm1Regs.AQCTLA.bit.CAU   = AQ_CLEAR;

     EPwm1Regs.AQCTLB.bit.ZRO   = AQ_SET;
     EPwm1Regs.AQCTLB.bit.CBU   = AQ_CLEAR;

     EDIS;
    }

    the System control config is :

    /*---------------------------------------------------------------------------
     InitSysCtrl:
    ---------------------------------------------------------------------------
     This function initializes the System Control registers to a known state.
     - Disables the watchdog
     - Set the PLLCR for proper SYSCLKOUT frequency
     - Set the pre-scaler for the high and low frequency peripheral clocks
     - Enable the clocks to the peripherals*/

    void InitSysCtrl(void)
    {
        /* Disable the watchdog */
     DisableDog();

        /* *IMPORTANT*
         The Device_cal function, which copies the ADC & oscillator calibration values
         from TI reserved OTP into the appropriate trim registers, occurs automatically
         in the Boot ROM. If the boot ROM code is bypassed during the debug process, the
         following function MUST be called for the ADC and oscillators to function according
         to specification. The clocks to the ADC MUST be enabled before calling this
         function.
         See the device data manual and/or the ADC Reference
         Manual for more information. */

        EALLOW;
        SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1U; /* Enable ADC peripheral clock*/
        (*Device_cal)();
        SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 0U; /* Return ADC clock to original state*/
        EDIS;

        /* Select Internal Oscillator 1 as Clock Source (default), and turn off all unused clocks to
         conserve power.*/
        IntOsc1Sel();

        /* Initialize the PLL control: PLLCR and DIVSEL
         DSP28_PLLCR and DSP28_DIVSEL are defined in DSP2802x_Examples.h*/
        InitPll(DSP28_PLLCR,DSP28_DIVSEL);

        /* Initialize the peripheral clocks */
        InitPeripheralClocks();
    }

    The init of PLL config:

    This function initializes the PLLCR register.*/

    void InitPll(Uint16 pllcr, Uint16 clkindiv)
    {
     volatile Uint16 iVol;

        /* Make sure the PLL is not running in limp mode*/
        if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0U)
        {
           EALLOW;
           /* OSCCLKSRC1 failure detected. PLL running in limp mode.
             Re-enable missing clock logic.*/
           SysCtrlRegs.PLLSTS.bit.MCLKCLR = 1U;
           EDIS;
           /* Replace this line with a call to an appropriate SystemShutdown function */
           /* Uncomment for debugging purposes  */
           asm("        ESTOP0");    
        }

        /* DIVSEL MUST be 0 before PLLCR can be changed from
         0x0000. It is set to 0 by an external reset XRSn
         This puts us in 1/4*/
        if (SysCtrlRegs.PLLSTS.bit.DIVSEL != 0U)
        {
         EALLOW;
            SysCtrlRegs.PLLSTS.bit.DIVSEL = 0U;
            EDIS;
        }

        /* Change the PLLCR*/
        if (SysCtrlRegs.PLLCR.bit.DIV != pllcr)
        {
           EALLOW;
           /* Before setting PLLCR turn off missing clock detect logic*/
           SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1U;
           SysCtrlRegs.PLLCR.bit.DIV = pllcr;
           EDIS;

           /* Optional: Wait for PLL to lock.
             During this time the CPU will switch to OSCCLK/2 until
             the PLL is stable.  Once the PLL is stable the CPU will
             switch to the new PLL value.
         
             This time-to-lock is monitored by a PLL lock counter.
         
             Code is not required to sit and wait for the PLL to lock.
             However, if the code does anything that is timing critical,
             and requires the correct clock be locked, then it is best to
             wait until this switching has completed.

             Wait for the PLL lock bit to be set.

             The watchdog should be disabled before this loop, or fed within
             the loop via ServiceDog().

             Uncomment to disable the watchdog
            */
           DisableDog();

           while(SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1U)
           {
               /* Uncomment to service the watchdog ServiceDog(). */
           }

           EALLOW;
           SysCtrlRegs.PLLSTS.bit.MCLKOFF = 0U;
           EDIS;
     }

        /* If switching to 1/2*/
        if((clkindiv == 1U)||(clkindiv == 2U))
       {
         EALLOW;
            SysCtrlRegs.PLLSTS.bit.DIVSEL = clkindiv;
            EDIS;
        }

        /* If switching to 1/1
         * First go to 1/2 and let the power settle
           The time required will depend on the system, this is only an example
         * Then switch to 1/1*/
     if(clkindiv == 3U)
        {
            EALLOW;
            SysCtrlRegs.PLLSTS.bit.DIVSEL = 2U;
            DSP28x_usDelay(300U);
            SysCtrlRegs.PLLSTS.bit.DIVSEL = 3U;
            EDIS;
        }
    }

    The Peripheral Clock init

    oid InitPeripheralClocks(void)
    {
      EALLOW;

     /* LOSPCP prescale register settings, normally it will be set to default values*/

        GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 3U;  /* GPIO18 = XCLKOUT*/
        SysCtrlRegs.LOSPCP.all = 0x0002U;

     /* XCLKOUT to SYSCLKOUT ratio.  By default XCLKOUT = 1/4 SYSCLKOUT*/
        SysCtrlRegs.XCLK.bit.XCLKOUTDIV=2U; /* Set XCLKOUT = SYSCLKOUT/1*/

     /* Peripheral clock enables set for the selected peripherals.
       If you are not using a peripheral leave the clock off
       to save on power.

       Note: not all peripherals are available on all 2802x derivates.
       Refer to the datasheet for your particular device.

       This function is not written to be an example of efficient code.*/

        SysCtrlRegs.PCLKCR0.bit.ADCENCLK   = 1U;  /* ADC   */
        SysCtrlRegs.PCLKCR3.bit.COMP1ENCLK   = 1U;    /* COMP1 */
        SysCtrlRegs.PCLKCR3.bit.COMP2ENCLK   = 1U;    /* COMP2 */
        SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK  = 1U;   /* CPU Timer-0 */
        SysCtrlRegs.PCLKCR3.bit.CPUTIMER1ENCLK  = 1U;   /* CPU Timer-1 */
        SysCtrlRegs.PCLKCR3.bit.CPUTIMER2ENCLK  = 1U;   /* CPU Timer-2 */
        SysCtrlRegs.PCLKCR1.bit.ECAP1ENCLK   = 0U;    /* eCAP1 */
        SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK   = 1U;    /* EPWM1 */
        SysCtrlRegs.PCLKCR1.bit.EPWM2ENCLK   = 1U;    /* EPWM2 */
        SysCtrlRegs.PCLKCR1.bit.EPWM3ENCLK   = 1U;    /* EPWM3 */
        SysCtrlRegs.PCLKCR1.bit.EPWM4ENCLK   = 1U;    /* EPWM4 */
        SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK  = 1U;     /* GPIO  */
        SysCtrlRegs.PCLKCR0.bit.HRPWMENCLK  = 1U;    /* HRPWM */
        SysCtrlRegs.PCLKCR0.bit.SCIAENCLK   = 1U;    /* SCI-A */
        SysCtrlRegs.PCLKCR0.bit.SPIAENCLK   = 0U;    /* SPI-A */

        SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC   = 1U;    /* Enable TBCLK within the EPWM */

        EDIS;
    }

  • Hi Barsanges Arnaud,

    Are you able to replicate this problem with the device not in standby mode? For example, could you disable interrupts and do a while(1) loop, or somehow simulate it while keeping the processor awake?

    I want to see if the pulses only occur in standby or if that just happens to be when you're seeing them.

    Regards,
    Kris
  • Hi Kris,

    I have 30000 products without problem. This problem appears during is "running life" on only one of the 30000 products. I can't at this moment change anything of the setting on this products. I need to keep this default to try to undersatand it correctly. It's our automotive process who impose me that I don't change nothing.

    So I can't say if I could see the pulse if I disable interrupt.

    I just could say that I don't see this pulse in the same configuration on other product.

    I saw on datasheet that the limitation of HRPWM indicate that the first 3 cycling instruction of the period of PWM are undefined (SPRUGE8E-february 2009-Revised October 2011 page 21 §2.3.3 Duty Cycle Range Limitation).

    I just want to know if during the 3 SYSCLK cycles after start of period, I could have a logical high state of output as if I request 0 duty cycle? If it is possible if I could have a different state during this 3 SYSCLK between 2 period (period 1 at high level, Period 2 at low level, Period 3 at low level, period 4 at High level, ...)?

  • Hi BARSANGES Arnaud,

    This could be related to the HRPWM cycle limitations, but without being able to perform more tests it's going to be very difficult to say. We would need to be able to do those experiments suggested on the device to further determine the cause.

    Regards,

    Kris

  • Hi Kris,

    I understand it is difficult to say that it's come from HRPWM limitation without Tests. I return back from my Customer to discuss with him about the possibility to test this function.

    Regards.

  • Hi Kris,

    I wish you a Happy new year and healthness.

    MCU1 = MCU with fault

    MCU2 = new MCU on other card without fault

    I read and save memory on my previous MCU1. I use the save Hex to load another MCU2 who could not cause my problem. I don't see pulse on the new card with the same memory. I am going to have dicussion with my Customer to know if I could change this MCU1 on the card 1 and replace it by a new to ensure problem's come from MCU1. If Yes, is it possible that I send you MCU1 for expertise?

    I Think it's not a fault but just the limit of mcu who cause my problem...

  • Hi Barsanges Arnaud,

    I will check to see if we can accept this as a customer return to run testing on it. I will get back with you with information on how to do this.

    Regards,
    Kris
  • Barsanges Arnaud,

    We would like to try some additional tests before returning the unit. After your customer replaces the unit, please also have them try the failing unit on another board. Let us know if the problem follows the board or the unit.

    Regards,
    Kris
  • Hi Kris,

    I make additional tests today:

    I replace the unit by a new one on the board where I found my problem. After flashing the unit with the program, I don't find the pulse on HRPWM output. I think the problem comes from the unit.

    My Customer don't want to check the unit on other board to see if the default follow the unit. He want to have the minimum of manipulation on the unit.

    I think I need to send you the unit for expertise. How I could make this action?

    Regards,

    Arnaud BARSANGES

  • Hi Arnaud Barsanges,

    We recommend that you try the unit on another board prior to returning the unit. If, however, you are prepared to return the unit please return it through the channel in which it was purchased. In the return document please include a link to this E2E thread.

    Thanks,
    Kris