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.

LAUNCHXL-F28069M: F28069M EPWM same group nested interrupt seems to be not working

Part Number: LAUNCHXL-F28069M

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");
    }
}