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.

CCS/TMS320F28335: eCAP as APWM synchronize with EPWM never reaches PRD=CTR

Part Number: TMS320F28335

Tool/software: Code Composer Studio

Hi,

Im working with the ECAP as PWM signal. These are the details of my test:

  • I used the ECAP1 interrupt (PRD=CTR) and the ePWM1 interrupt (PRD=CTR).
  • The ePWM1 is configured as UP/DOWN count (symmetrical wave carrier). 
  • In the ePWM1 interrupt values for the CMP and CTRPHS are written in the shadow CMP register (CAP4) and CTRPHS register.
  • The ECAP1 interrupt is only used to toggle a gpio to see that the interruptions is done.
  • Both signals (ECAP1 and EPWM1) has the same period.

My problems starts when I synchronize ECAP1 with ePWM1 trough the CTR_EQ_ZERO of the ePWM1 and the phase of ECAP1 is 0 or near 0. The interrupt of the eCAP nevers happends and therefore the shadow register of CAP4 is not written in CAP2 due CTR=PRD never happends!. If I dissable the synchronize both interrutptions enter without any problem and the duty values are properly written. Due to the application requierements I need the ePWM synchronized with the eCAP, there is any solution to ensure the PRD=CTR of the ECAP in order to load properly the values of CAP4? Or is possible to update CAP2 values at the synchronize moment? Because in the reference guide of the eCAP they said that CAP4 and CAP3 are loaded in CAP1 and CAP2 at PRD=CTR.

Here the code, used the same definitions that are used in the eCAP reference guide:

//==============================================================================================================================

interrupt void APWM_ISR1()
{
_isr_counter++; // This counter is used only for debug mode
if(_isr_counter>=150){_isr_counter=0;}
GpioDataRegs.GPATOGGLE.bit.GPIO16=1;
// Acknowledge this interrupt to receive more interrupts from group 4
PieCtrlRegs.PIEACK.all |= PIEACK_GROUP4;
//Here the order is very important! First CTR_EQ_PRD then INT flag
ECap1Regs.ECCLR.bit.CTR_EQ_PRD=1; //clear flag
ECap1Regs.ECCLR.bit.INT=1; //clear flag
}


//==============================================================================================================================
// ePWM interrupt
interrupt void EPWM_SYNC_ISR()
{

ECap1Regs.CAP4= _newDuty_Value; //Uint32 variable (If its different than the start value when synch enable and phase = 0 do not update the value!) Why?

ECap1Regs.CTRPHS= _newPhase_Value; //Uint32 variable 





/* My code for new Duty and Phase Values...

Increase the duty from 0 to 1 and adapt to Uint32 values based on the PRD

Change the phase value and adapt to Uint32 values based on the PRD, for ECAP1 always 0!



*/

// Acknowledge this interrupt to receive more interrupts from group 3

PieCtrlRegs.PIEACK.all |= PIEACK_GROUP3;
// Clear EPWMxINT flag
EPwm1Regs.ETCLR.bit.INT = 1;
}

//==============================================================================================================================
// MAIN
//==============================================================================================================================
void main(void)
{

//Configuraton of DSP
EALLOW;
SysCtrlRegs.WDCR = 0x0068; // watchdog OFF
SysCtrlRegs.PLLSTS.bit.DIVSEL = 2; // PLL
SysCtrlRegs.PLLCR.bit.DIV = 10; // 30MHz * 10 / 2 = 150 MHz
SysCtrlRegs.HISPCP.all = 0x0001;
SysCtrlRegs.LOSPCP.all = 0x0002;
SysCtrlRegs.PCLKCR0.all = 0x0000;
SysCtrlRegs.PCLKCR1.all = 0x0000;
SysCtrlRegs.PCLKCR3.all = 0x0000;

//Enabling PWM & ECAP CLK
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Disable TBCLK within the ePWM
SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 1; // Enable CLK for EPWM1
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Enable TBCLK within the ePWM

//Enabling GPIO CLK
SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1;
//Enabling TMR0 CLK
SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK=1;
EDIS;

//The GPIO clock must be enabled,
EALLOW;
//ENABLE COMMAND
GpioCtrlRegs.GPADIR.bit.GPIO16 = 1; // GPIOX = out
EDIS;

//Configure outputs for ePWM
EALLOW;
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;
GpioCtrlRegs.GPADIR.bit.GPIO0 = 1; // GPIOX = output
GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;
GpioCtrlRegs.GPADIR.bit.GPIO1 = 1; // GPIOX = output
GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 1;
GpioCtrlRegs.GPADIR.bit.GPIO4 = 1; // GPIOX = output
GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 1;
GpioCtrlRegs.GPADIR.bit.GPIO5 = 1; // GPIOX = output
GpioCtrlRegs.GPAMUX1.bit.GPIO10 = 1;
GpioCtrlRegs.GPADIR.bit.GPIO10 = 1; // GPIOX = output
GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 1;
GpioCtrlRegs.GPADIR.bit.GPIO11 = 1; // GPIOX = output
EDIS;



/CONFIGURE 1 PWM, FOR 50 uS PERIOD,
//Time base
EPwm1Regs.TBPRD=(TSW_us*75); //CLK frequency is 150 MHz, 6.67 ns.
//Count type
EPwm1Regs.TBPHS.half.TBPHS=0; // Set Phase register to zero
EPwm1Regs.TBCTR=0; // clear TB counter
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Phase loading disabled
EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW;

//Base time
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // TBCLK = SYSCLKOUT
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;

//Compare Shadowed mode
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; //Use shadowed mode for CMPA
EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; //Use shadowed mode for CMPB
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // load on CTR = Zero
EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // load on CTR = Zero

//Counter Compare: initial values;
EPwm1Regs.CMPA.half.CMPA=0; //Not PWM ratio at the start
EPwm1Regs.CMPB=0; //Not PWM ratio at the start



//Action Qualifier: Complementary mode
EPwm1Regs.AQCTLB.bit.PRD = AQ_SET; //Set EPWMxB Transitions FROM 0 to 1 (AQ_SET) by CMPA CAD (CROSSING DOWN)
EPwm1Regs.AQCTLB.bit.CAU = AQ_CLEAR; //Set EPWMxB Transitions FROM 1 to 0 (AQ_CLEAR) by CMPA CAU (CROSSING UP)
//i.e. If CMPB increases, duty of EPWMA increases.

//IF DEADBAND IS ENABLED AS COMPLEMENTARY ACTIVE HIGH, AQCTLA bits are OVERWRITTEN!!!
EPwm1Regs.AQCTLA.bit.PRD = AQ_CLEAR; //Set EPWMxA Transitions FROM 1 to 0 (AQ_CLEAR) by CMPB CAD (CROSSING DOWN)
EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; //Set EPWMxA Transitions FROM 0 to 1 (AQ_SET) by CMPB CAU (CROSSING UP)
//i.e. If CMPB increases, duty of EPWMB decreases.
//deadband
EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // enable Dead-band module, rising of ePWMB is delayed, falling of ePWMA is delayed
EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; // Active HIC complementary
//IF DEADBAND IS ENABLED AS COMPLEMENTARY ACTIVE HIGH, AQCTLB bits are OVERWRITTEN!!!
EPwm1Regs.DBFED = dt_1; // FED = XX TBCLKs; 1 TBCLK=SYSCLKOUT = 6.67 ns;
EPwm1Regs.DBRED = dt_1; // RED = XX TBCLKs; 299 ~ 2us

 

//Configure outputs for aPWM
EALLOW;
// ECAP Clocks
SysCtrlRegs.PCLKCR1.bit.ECAP1ENCLK = 1; // Enable CLK for ECAP1
SysCtrlRegs.PCLKCR1.bit.ECAP2ENCLK = 1; // Enable CLK for ECAP2
SysCtrlRegs.PCLKCR1.bit.ECAP3ENCLK = 1; // Enable CLK for ECAP3
SysCtrlRegs.PCLKCR1.bit.ECAP4ENCLK = 1; // Enable CLK for ECAP4
SysCtrlRegs.PCLKCR1.bit.ECAP5ENCLK = 1; // Enable CLK for ECAP5
SysCtrlRegs.PCLKCR1.bit.ECAP6ENCLK = 1; // Enable CLK for ECAP6
// ECAP pins as output
GpioCtrlRegs.GPAMUX2.bit.GPIO24 = 1;
GpioCtrlRegs.GPADIR.bit.GPIO24 = 1; // GPIOX = output
GpioCtrlRegs.GPAMUX2.bit.GPIO25 = 1;
GpioCtrlRegs.GPADIR.bit.GPIO25 = 1; // GPIOX = output
GpioCtrlRegs.GPAMUX2.bit.GPIO26 = 1;
GpioCtrlRegs.GPADIR.bit.GPIO26 = 1; // GPIOX = output
GpioCtrlRegs.GPAMUX2.bit.GPIO27 = 1;
GpioCtrlRegs.GPADIR.bit.GPIO27 = 1; // GPIOX = output
GpioCtrlRegs.GPBMUX2.bit.GPIO48 = 1;
GpioCtrlRegs.GPBDIR.bit.GPIO48 = 1; // GPIOX = output
GpioCtrlRegs.GPBMUX2.bit.GPIO49 = 1;
GpioCtrlRegs.GPBDIR.bit.GPIO49 = 1; // GPIOX = output
EDIS;

 

//Preset Values:
GpioDataRegs.GPACLEAR.bit.GPIO16=1;
// Define PWM duty
EPwm1Regs.CMPB=(TSW_us*75)*duty1;


EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO;

ECap1Regs.ECCTL2.bit.CAP_APWM = EC_APWM_MODE; // Enable APWM mode
ECap1Regs.ECCTL2.bit.APWMPOL = EC_ACTV_LO; // Active Low
ECap1Regs.ECCTL2.bit.SYNCI_EN = EC_ENABLE; // Synch: Master ePWM1
ECap1Regs.ECCTL2.bit.SYNCO_SEL = EC_SYNCIN; // Send Signal to ECAP2
ECap1Regs.ECCTL2.bit.TSCTRSTOP=EC_RUN; // RUN the clock
ECap1Regs.CAP1 = 50*150; // Set Period of the signal.


//Enable ECAP Interrupts
DINT; //Dissable Interrupts
ECap1Regs.ECEINT.all=0; //Dissable all interrupts
ECap1Regs.ECCLR.all=1; //Clear all flags
ECap1Regs.ECEINT.bit.CTR_EQ_PRD=1; //Enable CTR=CMP Interrupt
EALLOW;
*(&PieVectTable.ECAP1_INT) = APWM_ISR1; //Set the isr function
IER |= M_INT4;
PieCtrlRegs.PIEIER4.bit.INTx1 |= 1;
EDIS;

//Enable ePWM interrupts
EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_PRD; // Select INT on Period event
EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT
EPwm1Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st event
// enable PWM interrupts
EALLOW;
*(&PieVectTable.EPWM1_INT + 0) = EPWM_SYNC_ISR;
EDIS;
// Enable CPU INT3 which is connected to EPWM1-6 INT:
IER |= M_INT3;
// PIE enable
PieCtrlRegs.PIEIER3.all |= 1 << 0;


//Preset APWM Values
ECap1Regs.CAP1 =50*150; // Set Period value (150 no Preescaler)
ECap1Regs.CAP2 =50*150*0.5; // Set Compare value (150 no Preescaler)
ECap1Regs.CTRPHS = 0x0; // make phase zero



//Enable Interrupts;
// Enable the PIE
PieCtrlRegs.PIECTRL.bit.ENPIE = 1;

// Enables PIE to drive a pulse into the CPU
PieCtrlRegs.PIEACK.all = 0xFFFF;

// Enable Interrupts at the CPU level
EINT;

// Enable Global realtime interrupt DBGM
ERTM;

//*********************************************************************************
// Infinity Loop
//*********************************************************************************
while (1)
{
//****************************************************************
}//End Infinity Loop
}//END MAIN

  • I'm having a little trouble picturing this scenario. Do you stop getting interrupts or is it just the interrupt following the update is missed?

    You're correct that the shadow load only happens when CTR=PRD. The sync-in is only for the phase.

    Whitney
  • Hi Whitney,

    I stop getting interrupts, but only the eCAP1 interrupt, ePWM1 PRD=CTR occurs every cycle properly. I'll try  to clarify what i want to do:

    • I want an eCAP1 as APWM1, synchronize with the ePWM1
    • Every new cycle the new values (calculated before and already set in the shadow registers) should be updated.
    • But, for a fixed phase shift of zero and eCAP1 sync with ePWM1 CTR=ZERO, the compare value is not updated in the CAP2. Following the guide, is mentioned that shadow register is loaded at PRD=CMP and phase at sync signal. So, I create the interrupt of ECAP1 at PRD=CTR to see a train pulse and put a debug breakpoint, in order to know if im reaching this interruption. When ePWM and eCAP1 are sync in the moment that ePWM  CTR=ZERO the phase is loaded and the PRD=CTR of the eCAP never happends, therefore the CAP2 remains with the previous value. My conclusion at the moment is that sync signal occurs before PRD=CTR then phase is loaded making CTR=0 and never reaches the PRD. 

    There is any way to wait or check if the PRD=CTR ocurrs before update the phase or force an update of CAP2 at the sync? Or force the phase / sync_signal to update when CAP4 is loaded into CAP2? Or check if CAP2 have not been updated and therefore do not update the phase?

    And why the CTR=ZERO of ePWM ocurrs before CTR=PRD of eCAP if both are set with the same period and same phase? 

    Miguel,

     

  • Okay, I think I see what you're saying. So if you decrease the eCAP period value by one or two counts so that there's a little more time between the PRD event and the sync event, I'm guessing a phase of 0 doesn't cause this issue anymore?

    Whitney
  • Yes, you are correct. I reduce my PRD from 7500 to 7499 and now it loads the shadows correctly and it enter in the interruption.
    Thank you!