Hello there,
I am observing something strange with my F28335 microncontroller. I have configured EPWM2 to run at 25kHz and I want it to generate an interrupt request at the same frequency. EPWM2 is configured as follows:
void init_epwm2(void) { EALLOW; GpioCtrlRegs.GPAPUD.bit.GPIO2 = 1; // Disable pull-up on GPIO2 (EPWM2A) GpioCtrlRegs.GPAPUD.bit.GPIO3 = 1; // Disable pull-up on GPIO3 (EPWM3B) /* Configure ePWM-2 pins using GPIO regs*/ // This specifies which of the possible GPIO pins will be ePWM2 functional pins. GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1; // Configure GPIO2 as EPWM2A GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 1; // Configure GPIO3 as EPWM2B EDIS; // Setup TBCLK EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up EPwm2Regs.TBPRD = SWITCHING_PERIOD;//EPWM2_TIMER_TBPRD; // Set timer period EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading EPwm2Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0 EPwm2Regs.TBCTR = 0x0000; // Clear counter EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; //TB_DIV2; // Clock ratio to SYSCLKOUT EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1; //TB_DIV2; // Setup shadow register load on ZERO EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // Set Compare values EPwm2Regs.CMPA.half.CMPA = 0;//SWITCHING_PERIOD; // Set compare A value. We want PWMB to be zero on start, so make PWMA maximum on start. EPwm2Regs.CMPB = 0;//EPWM2_MAX_CMPB; // Set Compare B value EPwm2Regs.CMPA.half.CMPAHR = (1 << 8); //Set initial value for CMPAHR // Set actions EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET;//AQ_CLEAR; // Clear PWM2A on Period EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR;//AQ_SET; // Set PWM2A on event A, up count EPwm2Regs.AQCTLB.bit.ZRO = AQ_CLEAR; // Clear PWM2B on Period EPwm2Regs.AQCTLB.bit.CBU = AQ_SET; // Set PWM2B on event B, up count // Configure Interrupt EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event EPwm2Regs.ETSEL.bit.INTEN = 1; //Enable Interrupt EPwm2Regs.ETPS.bit.INTPRD = 0x01; //Interrupt on first event //ET_3RD; // Generate INT on 3rd event // Active Low PWMs - Setup Deadband EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;//DB_ACTV_LO; EPwm2Regs.DBRED = 10;//5;//EPWM1_MIN_DB; EPwm2Regs.DBFED = 20;//5;//50;//EPWM1_MIN_DB; //Trip-zone configuration for fault conditions and High-resoultion configuration EALLOW; EPwm2Regs.TZSEL.bit.OSHT1 = 0x01; //Enable TZ1 as a one-shot trip source for this ePWM module EPwm2Regs.TZCTL.bit.TZA = 0x02; //Force EPWM1A to a low state EPwm2Regs.TZCTL.bit.TZB = 0x02; //Force EPWM1B to a low state EPwm2Regs.TZFRC.bit.OST = 1; //Force one-shot trip condition EPwm2Regs.HRCNFG.bit.HRLOAD = 0; //High resolution counter loaded at "counter equal zero" EPwm2Regs.HRCNFG.bit.CTLMODE = 0; //CMPAHR controls edge position EPwm2Regs.HRCNFG.bit.EDGMODE = 0x02; //MEP control is done on falling edge EDIS; }
I also want to use EPWM1 to generate ADC triggers. I have configured EPWM1 as follows:
void init_epwm1(void) { EALLOW; 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. GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // Configure GPIO0 as EPWM1A GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; // Configure GPIO1 as EPWM1B EDIS; // Setup TBCLK EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up EPwm1Regs.TBPRD = 600;//EPWM1_TIMER_TBPRD; // Set timer period EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0 EPwm1Regs.TBCTR = 0x0000; // Clear counter EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1; // Setup shadow register load on ZERO EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // Set Compare values EPwm1Regs.CMPA.half.CMPA = 0;//EPWM1_MIN_CMPA; // Set compare A value EPwm1Regs.CMPB = 0;//EPWM1_MIN_CMPB; // Set Compare B value // Set actions EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // Set PWM1A on Zero EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clear PWM1A on event A, up count EPwm1Regs.AQCTLB.bit.ZRO = AQ_CLEAR;//AQ_SET; // Set PWM1B on Zero EPwm1Regs.AQCTLB.bit.CBU = AQ_SET;//AQ_CLEAR; // Clear PWM1B on event B, up count //Enable SOCA EPwm1Regs.ETSEL.bit.SOCAEN = 0x01; //Enable EPWM1 SOCA Pulse. This will trigger the ADC conversion sequence EPwm1Regs.ETSEL.bit.SOCASEL = 0x01; //Enable event time-base counter equal to period (TBCTR = TBPRD) EPwm1Regs.ETPS.bit.SOCAPRD = 0x02; // Generate pulse on 1st event // Interrupt where we will change the Compare Values EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event EPwm1Regs.ETSEL.bit.INTEN = 0; // Disable interrupt INT EPwm1Regs.ETPS.bit.INTPRD = 0x00; // Disable the interrupt event counter. No interrupt will be generated and ETFRC[INT] is ignored. // Active Low PWMs - Setup Deadband EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;//DB_ACTV_LO; EPwm1Regs.DBRED = 20;//5;//EPWM1_MIN_DB; EPwm1Regs.DBFED = 40;//5;//50;//EPWM1_MIN_DB; //Falling edge deadtime EALLOW; //Trip-zone configuration for fault conditions EPwm1Regs.TZSEL.bit.OSHT1 = 0x01; //Enable TZ1 as a one-shot trip source for this ePWM module EPwm1Regs.TZCTL.bit.TZA = 0x02; //Force EPWM1A to a low state EPwm1Regs.TZCTL.bit.TZB = 0x02; //Force EPWM1B to a low state EDIS; }
I am using the software-prioritized interrupt files (for interrupt nesting) and I have configured the relevant lines as follows:
#define INT1PL 2 // Group1 Interrupts (PIEIER1) #define INT3PL 1 // Group3 Interrupts (PIEIER3) //...Some code .... #define G31PL 0 // EPWM1_INT (ePWM1 Int) #define G32PL 1 // EPWM2_INT (ePWM2 Int) #define G33PL 0 // EPWM3_INT (ePWM3 Int) #define G34PL 2 // EPWM4_INT (ePWM4 Int) ///...more code ....
In the main file, I have made the following configurations:
//.... some code which I have left out ...// InitSysCtrl(); IER = 0x0000; IFR = 0x0000; InitPieVectTable(); EALLOW; // This is needed to write to EALLOW protected registers PieVectTable.XINT1 = &xint1_isr; PieVectTable.EPWM4_INT = &epwm4_isr; PieVectTable.EPWM2_INT = &EPWM2_ISR; PieVectTable.SEQ1INT = &adc_isr; EDIS; // This is needed to disable write to EALLOW protected registers PieCtrlRegs.PIECTRL.bit.ENPIE = 1; // Enable the PIE block PieCtrlRegs.PIEIER1.bit.INTx4 = 1; // Enable PIE XINT1 PieCtrlRegs.PIEIER1.bit.INTx1 = 1; //Enable SEQ1 interrupt in PIE PieCtrlRegs.PIEIER3.bit.INTx4 = 1; // Enable EPWM INTn in the PIE: Group 3 interrupt 4 (EPWM4) PieCtrlRegs.PIEIER3.bit.INTx2 = 1; // Enable EPWM INTn in the PIE: Group 3 interrupt 2 (EPWM2) PieCtrlRegs.PIEACK.all = 0xFFFF; // Acknowledge then enable PIE interrupts IER |= M_INT1; // Enable CPU INT1 which is connected to external interrupt 1 (i.e. XINT1), to CPU-Timer 0 (TMR0), and to the ADC interrupt (ADCINT) IER |= M_INT3; // Enable CPU INT3 which is connected to EPWM4 INT and EPWM2 int: EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM ///...more code left out from this point...///
Clearly, I have disabled EPWM1_INT interrupt. However, upon running the program, it vectors in to the default EPWM1 int which appears as follows:
interrupt void EPWM1_INT_ISR(void) // EPWM-1 { // Insert ISR Code here // To receive more interrupts from this PIE group, acknowledge this interrupt // PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; // Next two lines for debug only to halt the processor here // Remove after inserting ISR Code asm (" ESTOP0"); for(;;); }
This should not be possible because the epwm1 interrupt has been disabled. How can this be? Checking the ETSEL register shows nothing wrong. Any tips here? Thanks.