Hi there,
I'm desperately trying to get my ePWM module to fire an interrupt but it just doesn't seem to happen. The same ePWM module is also controlling the SOCA for the ADC which has an according ISR that works perfectly fine.
Here's what I consider the relevant code:
Main.c
// Initialize device clock and peripherals
InitSysCtrl();
// Initialize GPIO
InitGpio();
GPIO_SetupPinMux(GPIO_DBG_ISR, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(GPIO_DBG_ISR, GPIO_OUTPUT, GPIO_PUSHPULL);
// Disable CPU interrupts
DINT;
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
InitPieVectTable();
adc_Init();
// Configure the ePWM
pwm_Init();
// Enable global Interrupts and higher priority real-time debug events:
IER |= M_INT1; // Enable group 1 interrupts
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
// Sync ePWM
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
while(1)
}
adc.c
__interrupt void A1ISR(void)
{
do stuff
}
void adc_Init(void)
{
// allow adjusting registers
// Enable internal 3.3V reference voltage for both ADCs
// SetVREF also loads the correct offtrim value.
SetVREF(ADC_ADCA, ADC_INTERNAL, ADC_VREF3P3);
SetVREF(ADC_ADCB, ADC_INTERNAL, ADC_VREF3P3);
SetVREF(ADC_ADCC, ADC_INTERNAL, ADC_VREF3P3);
EALLOW;
// configure ADCCLK prescale. Max according to ds is 50MHz.
AdcaRegs.ADCCTL2.bit.PRESCALE = 2;
AdcbRegs.ADCCTL2.bit.PRESCALE = 2;
// Cause the interrupt to be triggered after conversion
AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;
AdcbRegs.ADCCTL1.bit.INTPULSEPOS = 1;
AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0;
AdcaRegs.ADCSOC1CTL.bit.CHSEL = 1;
AdcaRegs.ADCSOC2CTL.bit.CHSEL = 2;
AdcaRegs.ADCSOC3CTL.bit.CHSEL = 3;
AdcaRegs.ADCSOC4CTL.bit.CHSEL = 4;
AdcaRegs.ADCSOC5CTL.bit.CHSEL = 5;
AdcaRegs.ADCSOC6CTL.bit.CHSEL = 6;
AdcaRegs.ADCSOC7CTL.bit.CHSEL = 8; // channel A7 is not bonded out.
AdcbRegs.ADCSOC0CTL.bit.CHSEL = 0;
AdcbRegs.ADCSOC1CTL.bit.CHSEL = 1;
AdcbRegs.ADCSOC2CTL.bit.CHSEL = 2;
AdcbRegs.ADCSOC3CTL.bit.CHSEL = 3;
AdcbRegs.ADCSOC4CTL.bit.CHSEL = 4;
AdcbRegs.ADCSOC5CTL.bit.CHSEL = 6; // channel B5 is not bonded out.
AdcbRegs.ADCSOC6CTL.bit.CHSEL = 8; // channel B7 is not bonded out.
AdcbRegs.ADCSOC7CTL.bit.CHSEL = 7; // channel A7 is not bonded out.
// Setup acquisition windows for ADC A and B and all required SOCs
// (register holds value - 1)
uint16_t u16Acqps = 24;
AdcaRegs.ADCSOC0CTL.bit.ACQPS = u16Acqps -1;
AdcaRegs.ADCSOC1CTL.bit.ACQPS = u16Acqps -1;
AdcaRegs.ADCSOC2CTL.bit.ACQPS = u16Acqps -1;
AdcaRegs.ADCSOC3CTL.bit.ACQPS = u16Acqps -1;
AdcaRegs.ADCSOC4CTL.bit.ACQPS = u16Acqps -1;
AdcaRegs.ADCSOC5CTL.bit.ACQPS = u16Acqps -1;
AdcaRegs.ADCSOC6CTL.bit.ACQPS = u16Acqps -1;
AdcaRegs.ADCSOC7CTL.bit.ACQPS = u16Acqps -1;
AdcbRegs.ADCSOC0CTL.bit.ACQPS = u16Acqps -1;
AdcbRegs.ADCSOC1CTL.bit.ACQPS = u16Acqps -1;
AdcbRegs.ADCSOC2CTL.bit.ACQPS = u16Acqps -1;
AdcbRegs.ADCSOC3CTL.bit.ACQPS = u16Acqps -1;
AdcbRegs.ADCSOC4CTL.bit.ACQPS = u16Acqps -1;
AdcbRegs.ADCSOC5CTL.bit.ACQPS = u16Acqps -1;
AdcbRegs.ADCSOC6CTL.bit.ACQPS = u16Acqps -1;
AdcbRegs.ADCSOC7CTL.bit.ACQPS = u16Acqps -1;
// set all SOCs to trigger on ePWM1 SOCA. Since no further
// priorization is taking place the SOCs will be triggered in a
// round robbing manner
AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5;
AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 5;
AdcaRegs.ADCSOC2CTL.bit.TRIGSEL = 5;
AdcaRegs.ADCSOC3CTL.bit.TRIGSEL = 5;
AdcaRegs.ADCSOC4CTL.bit.TRIGSEL = 5;
AdcaRegs.ADCSOC5CTL.bit.TRIGSEL = 5;
AdcaRegs.ADCSOC6CTL.bit.TRIGSEL = 5;
AdcaRegs.ADCSOC7CTL.bit.TRIGSEL = 5;
AdcbRegs.ADCSOC0CTL.bit.TRIGSEL = 5;
AdcbRegs.ADCSOC1CTL.bit.TRIGSEL = 5;
AdcbRegs.ADCSOC2CTL.bit.TRIGSEL = 5;
AdcbRegs.ADCSOC3CTL.bit.TRIGSEL = 5;
AdcbRegs.ADCSOC4CTL.bit.TRIGSEL = 5;
AdcbRegs.ADCSOC5CTL.bit.TRIGSEL = 5;
AdcbRegs.ADCSOC6CTL.bit.TRIGSEL = 5;
AdcbRegs.ADCSOC7CTL.bit.TRIGSEL = 5;
// Cause interrupt once SOC7 of ADC A is done
AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 7;
AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; // Enable INT1 flag
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // Make sure INT1 flag is cleared
AdcbRegs.ADCINTSEL1N2.bit.INT1SEL = 7;
AdcbRegs.ADCINTSEL1N2.bit.INT1E = 1; // Enable INT1 flag
AdcbRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // Make sure INT1 flag is cleared
// Enable PIE interrupt. INTx1 for ADC A INTx2 for ADC B
// see f28004x_defaultisr.h
PieCtrlRegs.PIEIER1.bit.INTx1 = 1;
// Function for ADC-A interrupt 1. Since ADC-B is setup
// identically to ADCA it should be done at the same time.
PieVectTable.ADCA1_INT = &A1ISR;
// Power up the ADC
AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;
AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 1;
// stop to allow register changes
EDIS;
// delay for 1ms so the ADC have time to power up
DELAY_US(1000);
}
pwm.c
__interrupt void pwm_ISR(void)
{
do stuff
}
static void pwm_Init(void)
{
PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
PieVectTable.EPWM1_INT = &pwm_ISR;
PieCtrlRegs.PIECTRL.bit.ENPIE = 1;
// Time-Base Control
EPwm1Regs.TBCTL.bit.CTRMODE = TB_FREEZE; // Stop - freeze counter operation
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Do not load the time-base counter (TBCTR) from the time-base phase register (TBPHS)
EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW; // The period register (TBPRD) is loaded from its shadow register when the time-base counter, TBCTR, is equal to zero.
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; // Disable EPWMxSYNCO signal
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // High Speed Time-base Clock Prescale Bits: /1
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1; // Time-base Clock Prescale Bits: /1
EPwm1Regs.TBCTL.bit.FREE_SOFT = TB_FREERUN; // Emulation Mode Bits. These bits select the behavior of the ePWM time-base counter during emulation events
EPwm1Regs.TBPRD = IVPWM_PRD; // Time-Base Period
EPwm1Regs.TBPHS.all = 0; // Time-Base Phase, not used
EPwm1Regs.TBCTR = 0; // Time-Base Counter reset
// HRPWM Configuration
// MEP control is on a CMPA-generated edge, as recommended by TI (..\Doku\HRPWM_dutycycle_limitations.doc)
EALLOW;
EPwm1Regs.HRCNFG.all = 0; // Reset HRCNF REG. Necessary for MEP on Falling Edge
EPwm1Regs.HRCNFG.bit.EDGMODE = HR_FEP; // MEP control of falling edge
EPwm1Regs.HRCNFG.bit.CTLMODE = HR_CMP; // CMPAHR(8) Register controls the edge position
EPwm1Regs.HRCNFG.bit.HRLOAD = HR_CTR_ZERO; // Shadow mode bit; set this to match CMPCTL.LOADAMODE!
EDIS;
// Counter-Compare A/B
EPwm1Regs.CMPA.all = ((uint32_t)IVPWM_MIN << 16) | (1<<8); // Counter-Compare A
EPwm1Regs.CMPB.all = 0; // Counter-Compare B, not used. Epwm out B is generated in dead-band gen as inverted outp A
//Counter-Compare Control
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Active Counter-Compare A (CMPA) Load From Shadow Select Mode: Load on CTR = Zero
//EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // CMPB not used
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // Counter-compare A (CMPA) Register Operating Mode
//EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; // CMPB not used
// Action-Qualifier
EPwm1Regs.AQCTLA.all = AQ_NO_ACTION; // Action-Qualifier Output A Control: Do nothing (all actions disabled)
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Action when the counter equals the active CMPA register and the counter is incrementing: Clear: force EPWMxA output low.
EPwm1Regs.AQCTLA.bit.CAD = AQ_SET; // Action when the counter equals the active CMPA register and the counter is decrementing: Set: force EPWMxA output high.
EPwm1Regs.AQCTLB.all = AQ_NO_ACTION; // Action-Qualifier Output B Control: Do nothing (all actions disabled)
EPwm1Regs.AQSFRC.all = AQ_NO_ACTION; // Action-Qualifier Software Force: disabled
// Action-Qualifier Continuous Software Force
EPwm1Regs.AQCSFRC.bit.CSFA = AQ_NO_ACTION; // Continuous Software Force on Output A: Forcing disabled, i.e., has no effect
EPwm1Regs.AQCSFRC.bit.CSFB = AQ_NO_ACTION; // Continuous Software Force on Output A: Forcing disabled, i.e., has no effect
// Dead-Band Generator Control
EPwm1Regs.DBCTL.bit.HALFCYCLE = 0; // counter runs on TBCLK rate (high res dead band not used)
EPwm1Regs.DBCTL.bit.DEDB_MODE = 0; // Rising Edge Delay on ePWM1A, Falling Edge Delay on ePWM1B
EPwm1Regs.DBCTL.bit.OUTSWAP = 0; // no swapping of outputs
EPwm1Regs.DBCTL.bit.SHDWDBFEDMODE = 0; // Immediate mode
EPwm1Regs.DBCTL.bit.SHDWDBREDMODE = 0; // Immediate mode
EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL; // EPWMxA In is the source for both falling-edge and rising-edge delay.
EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; // Active high complementary (AHC). EPWMxB is inverted.
EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // Dead-band is fully enabled for both rising-edge delay on output EPWMxA and falling-edge delay on output EPWMxB.
EPwm1Regs.DBRED.all = IVPWM_DBRED; // Dead-Band Generator Rising Edge Delay
EPwm1Regs.DBFED.all = IVPWM_DBFED; // Dead-Band Generator Falling Edge Delay
// PWM-Chopper, not used
EPwm1Regs.PCCTL.all = 0; // PWM-Chopper Control
// Trip-Zone Submodule, not used
EALLOW;
EPwm1Regs.TZSEL.all = 0; // Trip-Zone Select
EPwm1Regs.TZCTL.all = 0; // Trip-Zone Control
EPwm1Regs.TZEINT.all = 0; // Trip-Zone Enable Interrupt
EPwm1Regs.TZCLR.all = BIT0|BIT1|BIT2; // Trip-Zone Clear
EDIS;
// Event-Trigger Prescale
EPwm1Regs.ETPS.bit.INTPRD = ET_3RD; // Generate interrupt on third event
EPwm1Regs.ETPS.bit.SOCAPRD = ET_1ST; // Generate the EPWMxSOCA pulse on the first event
// Event-Trigger Selection
EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Enable event time-base counter equal to zero.
EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTR_ZERO | ET_CTR_PRD; // Enable event time-base counter equal to zero.
// Event-Trigger Clear
EPwm1Regs.ETCLR.bit.INT = 1; // clear INT
EPwm1Regs.ETCLR.bit.SOCA = 1; // clear SOCA
// enable Event-Trigger
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable EPWMxSOCA pulse (for ADC trigger)
EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable EPWMx_INT generation
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Finally let counter run
}
Looking at the registers I can see that the Epwm1Regs.ETFLG.INT got set. Furthermore the EPwm1Regs.ETPS.INTCNT = 3. Writing a zero in here or clearing the interrupt flag in i.e. the main while(1) loops has no effect.
Any help to debug this would be highly appreciated! Please let me know if you need any more information.
Thanks in advance!