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.

Odd TBPRD shadow register behavior with 28035

Hi,

I'm implementing HRPWM control for a buck converter and am seeing some odd behavior.  I am using 2 PWMs, each controlling the top and bottom switching for separate legs of the converter.  In the PWM controlling the Buck1 leg, the TBPRD register changes  in between updates to the register;  the TBPRDHR portion of the register changes completely and the LSB of the TBPRD register occasionally changes.  I don't see this happen in the PWM controlling the Buck 2 leg.  I have verified that there is only one place in the code that writes to these registers.  Why would the TBPRD and TBPRDHR registers change between updates?   The code that configures the PWMs and the code that updates the registers is inserted below.

Thanks for your help!

-- Matt

Code that configures the PWMs:

// PWM3

Buck1Reg->TBPRD = BUCK_PWM_COUNT;
Buck1Reg->CMPA.half.CMPA = BUCK_PWM_50PC_COUNT;

Buck1Reg->TBPHS.half.TBPHS = 0U; 
Buck1Reg->TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; 
Buck1Reg->TBCTL.bit.PRDLD = TB_SHADOW;
Buck1Reg->TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; 
Buck1Reg->TBCTL.bit.HSPCLKDIV = TB_DIV1;
Buck1Reg->TBCTL.bit.CLKDIV = TB_DIV1;
Buck1Reg->CMPCTL.bit.SHDWAMODE = CC_SHADOW;
Buck1Reg->CMPCTL.bit.SHDWBMODE = CC_SHADOW;
Buck1Reg->CMPCTL.bit.LOADAMODE = CC_CTR_ZERO_PRD;
Buck1Reg->CMPCTL.bit.LOADBMODE = CC_CTR_ZERO_PRD; 
Buck1Reg->AQCTLA.bit.CAU = AQ_SET; 
Buck1Reg->AQCTLA.bit.CAD = AQ_CLEAR;
Buck1Reg->DBCTL.bit.OUT_MODE = DB_DISABLE; 
EALLOW;
Buck1Reg->HRCNFG.all = 0x0;
Buck1Reg->HRCNFG.bit.EDGMODE = HR_BEP; 
Buck1Reg->HRCNFG.bit.CTLMODE = HR_CMP; 
Buck1Reg->HRCNFG.bit.HRLOAD = HR_CTR_ZERO_PRD;
Buck1Reg->HRCNFG.bit.AUTOCONV = 1; 
Buck1Reg->HRPCTL.bit.TBPHSHRLOADE = 1;
Buck1Reg->HRPCTL.bit.HRPE = 1; // Turn on high-resolution period control.
EDIS;

// EPWM 4 
// Configure for HRPWM high-res period and duty cycle control
Buck2Reg->TBPRD = BUCK_PWM_COUNT; 
Buck2Reg->CMPA.half.CMPA = BUCK_PWM_50PC_COUNT;

Buck2Reg->TBPHS.half.TBPHS = 0U; 
Buck2Reg->TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; 
Buck2Reg->TBCTL.bit.PHSEN = TB_ENABLE; 
Buck2Reg->TBCTL.bit.PRDLD = TB_SHADOW;
Buck2Reg->TBCTL.bit.PHSDIR = TB_DOWN;
Buck2Reg->TBCTL.bit.HSPCLKDIV = TB_DIV1; 
Buck2Reg->TBCTL.bit.CLKDIV = TB_DIV1;
Buck2Reg->CMPCTL.bit.SHDWAMODE = CC_SHADOW;
Buck2Reg->CMPCTL.bit.SHDWBMODE = CC_SHADOW;
Buck2Reg->CMPCTL.bit.LOADAMODE = CC_CTR_ZERO_PRD; 
Buck2Reg->CMPCTL.bit.LOADBMODE = CC_CTR_ZERO_PRD; 
Buck2Reg->AQCTLA.bit.CAU = AQ_SET; 
Buck2Reg->AQCTLA.bit.CAD = AQ_CLEAR;
Buck2Reg->DBCTL.bit.OUT_MODE = DB_DISABLE; 
EALLOW;
Buck2Reg->HRCNFG.all = 0x0;
Buck2Reg->HRCNFG.bit.EDGMODE = HR_BEP; 
Buck2Reg->HRCNFG.bit.CTLMODE = HR_CMP;
Buck2Reg->HRCNFG.bit.HRLOAD = HR_CTR_ZERO_PRD;
Buck2Reg->HRCNFG.bit.AUTOCONV = 1; 
Buck2Reg->HRPCTL.bit.TBPHSHRLOADE = 1;
Buck2Reg->HRPCTL.bit.HRPE = 1; 
EDIS;

Code that updates the PWM registers:

//PWM 3

Buck1Reg->TBPRD = (buckPeriod >> 16); // Period TBCLK counts
Buck1Reg->TBPRDHR = (buckPeriod & 0xFF00); // Period TBCLK counts
Buck1Reg->CMPA.all = (buckPeriod>>1) & (0xFFFFFF00);

//PWM 4

Buck2Reg->TBPRD = (buckPeriod >> 16); // Period TBCLK counts
Buck2Reg->TBPRDHR = (buckPeriod & 0xFF00); // Period TBCLK counts
Buck2Reg->CMPA.all = (buckPeriod>>1) & (0xFFFFFF00);
Buck2Reg->TBPHS.all = (buckPhase) & (0xFFFFFF00);

  • Hi Matt,

    TBPRD and TBPRDHR may change between updates when you are using high resolution period mode (HRPCTL[HRPE] = 1). This is a result of the fractional system clock part of the PWM period (i.e. TBPRDHR). If the register values for these registers are the same for both PWM modules the same effect should be seen on both PWMs, unless the second PWM module being used does not support HRPWM. Please note that it is possible that not all PWM modules on the device support HRPWM.

    Hrishi

     

  • Hi Hrishi,

    Thank you for your response.  It certainly does explain what I'm seeing.

    However it does lead to some more questions.

    1)  As I noted, I'm only seeing the TBPRD and TDPRDHR registers change between updates on the "upstream" PWM.  I have the TBCTL[PHSEN] bit set on the  "downstream" PWM.  If I don't set TBCTL[PHSEN] on the downstream PWM, then I see the TBPRD and TBPRDHR registers change between updates on both PWMs.  Is this expected behavior?

    2)  I'm running the SFO() routine in the background and have HRCNFG[AUTOCONV] set.  Therefore the SFO() routine is updating the TBPRD and TDPRDHR automatically.  Are those registers updated atomically?  If not, what prevents the PWM from detecting a CMP event erroneously if only one of the TBPRD and TDPRDHR had been udpated at that instant?

    3)  Since the SFO() routine is called asynchronously to the application firmware that is updating the TBPRD and TBPRDHR registers, is it possible for SFO() to read the TBPRD and TBPRDHR registers when only one of them has been updated, therefore doing its scaling with only partial information?

    Thanks,

    Matt

  • Hi Matt,

    Please see my answers below:

    1)  As I noted, I'm only seeing the TBPRD and TDPRDHR registers change between updates on the "upstream" PWM.  I have the TBCTL[PHSEN] bit set on the  "downstream" PWM.  If I don't set TBCTL[PHSEN] on the downstream PWM, then I see the TBPRD and TBPRDHR registers change between updates on both PWMs.  Is this expected behavior?

    HN: No this is not expected. Please make sure you are following the 'High-Resolution Period Configuration' steps listed in the HRPWM user guide exactly (particularly, steps 5 to 8).

    2)  I'm running the SFO() routine in the background and have HRCNFG[AUTOCONV] set.  Therefore the SFO() routine is updating the TBPRD and TDPRDHR automatically.  Are those registers updated atomically?  If not, what prevents the PWM from detecting a CMP event erroneously if only one of the TBPRD and TDPRDHR had been udpated at that instant?

    HN: SFO routine does not update TBPRD:TBPRDHR registers. These registers are updated when the user writes to them, typically, inside an ISR. You have two phase shifted PWM modules with changing frequency, which means you will have to make sure that all register updates occur before the event that loads shadow registers to active registers (CTR = 0). Please refer to my forum post below, where I present a way to make sure all register updates are done correctly (please refer to the attachment) - http://e2e.ti.com/support/microcontrollers/c2000/f/171/p/317898/1112702.aspx#1112702

    3)  Since the SFO() routine is called asynchronously to the application firmware that is updating the TBPRD and TBPRDHR registers, is it possible for SFO() to read the TBPRD and TBPRDHR registers when only one of them has been updated, therefore doing its scaling with only partial information?

     HN: SFO routine updates the MEP logic and is not involved in updating PRD registers.

    Hrishi