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.
Hello all!
I am trying to implement the following very basic function:
I would like to run two interrupts, one of which runs at 10kHz, whilst the other one runs at 0.1ms. The two interrupts basically do the same thing: they switch on the onboard led for one second than they switch it off for an other 1 second. So what I would like to test, is the nested interrupt capabilities of the C2000 MCU, focusing on the interrupts occurs at the same time, coming from the same group.
My problem, that the nested interrupt configuration seems to be not working, because there is way to much time between the switch on of the LEDs.
As you can see on the first figure, this time delay between the switchings is about 2.67ms after powering the board. On the top of that, this time is increasing during the run.
This is my code for the EPWM setup:
void EPWM_setup(void) { DINT; EALLOW; //SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Stop all the TB clocks EDIS; /************** EPWM1 Setup **************/ EPwm1Regs.TBCTR = 0x0000; EPwm1Regs.TBPRD = 4500; // Equals 10Khz EPwm1Regs.TBPHS.half.TBPHS = 0; // Set Phase register to zero EPwm1Regs.TBCTL.bit.PHSDIR = TB_UP; // Up counting after SYNCH event EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1; // div = 1 EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // div = 1 EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Master module EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW; // If TBPRD is changed, than the // new value is loaded after the counter reaches 0 EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // Synchronization output select. // EPWM1 module sends out a synchronization pulse, when its TBPRD equals 0 EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Symmetrical mode EPwm1Regs.CMPA.half.CMPA = 2251; EPwm1Regs.CMPB = 2251; EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // load on CTR=Zero EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // load on CTR=Zero EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // set actions for EPWM1A EPwm1Regs.AQCTLA.bit.CAD = AQ_SET; EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // enable Dead-band module EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; // Active Hi complementary EPwm1Regs.DBFED = 0; // FED = 20 TBCLKs EPwm1Regs.DBRED = 0; // RED = 20 TBCLKs /************** EPWM2 Setup **************/ EPwm2Regs.TBCTR = 0x0000; EPwm2Regs.TBPRD = 45000; // Equals 1Khz EPwm2Regs.TBPHS.half.TBPHS = 0; // Set Phase register to zero EPwm2Regs.TBCTL.bit.PHSDIR = TB_UP; // Up counting after SYNCH event // In a 3Ph inverter application this PWM module should be the source of the // Synch signal, so this could be unnecessary EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1; // div = 1 EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // div = 1 EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Master module EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW; // If TBPRD is changed, than the // new value is loaded after the counter reaches 0 EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE; // Synchronization output select. // EPWM2 is synchronized to EPWM1 EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Symmetrical mode EPwm2Regs.CMPA.half.CMPA = 2251; EPwm2Regs.CMPB = 2251; EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // load on CTR=Zero EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // load on CTR=Zero EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR; // set actions for EPWM1A EPwm2Regs.AQCTLA.bit.CAD = AQ_SET; EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // enable Dead-band module EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; // Active Hi complementary EPwm2Regs.DBFED = 0; // FED = 0 TBCLKs EPwm2Regs.DBRED = 0; // RED = 0 TBCLKs EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Start all the TB clocks EDIS; PieCtrlRegs.PIEIFR3.bit.INTx1 = 0; PieCtrlRegs.PIEIFR3.bit.INTx2 = 0; IFR &= ~4; EPwm1Regs.ETSEL.bit.INTEN = 1; // EPWM1INTn Enable EPwm1Regs.ETSEL.bit.INTSEL = 1; // EPWM1INTn Select EPwm1Regs.ETPS.bit.INTPRD = 1; // EPWM1INTn Period Select EPwm2Regs.ETSEL.bit.INTEN = 1; // EPWM2INTn Enable EPwm2Regs.ETSEL.bit.INTSEL = 1; // EPWM1INTn Select EPwm2Regs.ETPS.bit.INTPRD = 1; // EPWM1INTn Period Select EINT; }
This is my EPWM interrupt handling code:
Uint32 redLed = 0; Uint32 blueLed = 0; void EPWM1_interrupt_func(void) { redLed++; if(redLed > 10000U) { GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1; GpioDataRegs.GPATOGGLE.bit.GPIO2 = 1; redLed = 0U; } } void EPWM2_interrupt_func(void) { blueLed++; if(blueLed > 1000U) { GpioDataRegs.GPBTOGGLE.bit.GPIO39 = 1; GpioDataRegs.GPATOGGLE.bit.GPIO3 = 1; blueLed = 0; } } interrupt void EPWM1_interrupt(void) { /*Serving EPWM1 Interrupt*/ EPWM1_interrupt_func(); EALLOW; EPwm1Regs.ETCLR.bit.INT = 1; EDIS; PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;/* Acknowledge to receive more interrupts*/ } interrupt void EPWM2_interrupt(void) { volatile unsigned int PIEIER3_stack_save = PieCtrlRegs.PIEIER3.all; PieCtrlRegs.PIEIER3.all &= ~2; /*disable group3 lower/equal priority interrupts*/ asm(" RPT #5 || NOP"); /*wait 5 cycles */ //IFR &= ~4; /*eventually disable lower/equal priority pending interrupts*/ PieCtrlRegs.PIEACK.all = 4; /*ACK to allow other interrupts from the same group to fire*/ IER |= 4; EINT; /*global interrupt enable*/ EPWM2_interrupt_func(); DINT; /* disable global interrupts during context switch, CPU will enable global interrupts after exiting ISR */ PieCtrlRegs.PIEIER3.all = PIEIER3_stack_save;/*restore PIEIER register that was modified*/ EALLOW; EPwm2Regs.ETCLR.bit.INT = 1; EDIS; PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;/* Acknowledge to receive more interrupts*/ } void enable_interrupts() { EALLOW; PieVectTable.EPWM1_INT = &EPWM1_interrupt;/* Hook interrupt to the ISR*/ EDIS; PieCtrlRegs.PIEIER3.bit.INTx1 = 1; /* Enable interrupt EPWM1_INT*/ IER |= M_INT3; EALLOW; PieVectTable.EPWM2_INT = &EPWM2_interrupt;/* Hook interrupt to the ISR*/ EDIS; PieCtrlRegs.PIEIER3.bit.INTx2 = 1; /* Enable interrupt EPWM2_INT*/ IER |= M_INT3; /* Enable global Interrupts and higher priority real-time debug events:*/ EINT; /* Enable Global interrupt INTM*/ ERTM; /* Enable Global realtime interrupt DBGM*/ }
And the main function:
int main(void) { InitSysCtrl(); EALLOW; /* Configure low speed peripheral clocks */ SysCtrlRegs.LOSPCP.all = 0U; EDIS; /* Disable and clear all CPU interrupts */ DINT; IER = 0x0000; IFR = 0x0000; InitPieCtrl(); InitPieVectTable(); InitFlash(); GPIO_setup(); EPWM_setup(); enable_interrupts(); while(1) { // asm(" NOP"); } }