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.

TMS320F28034: ADC interrupt terminate operation abnormal

Part Number: TMS320F28034

One piece of the mass production product work abnormal after 5-30mins during lab test. I found that the ADC interrupt terminate run through emulator and i need help to know why this will happen.

The program has three interrups, they are:

interrupt 1: ADC interrupt, ADC triggerd by Timer0 (50us period),ADC interrupt is triggerd by the completion of the whole sampling.

interrupt 2: Timer1(3ms period) interrupt,the interrupt task only run for about 200ns.

interrupt 3: Ecap1 interrupt,triggerd every 20ms. the interrupt task only run for about 200ns

When the ADC interrupt terminated, I found the value of the register related to the ADC interrupt as following

AdcRegs.INTSEL1N2.bit.INT1E,PieCtrlRegs.PIEIER1.bit.INTx1 , IER.INT1 , INTM, ADCINTFLG.ADCINT1, ADCINTOVF.ADCINT1are all set, but PieCtrlRegs.PIEIFR1.bit.INTx1 are unset.

After set PieCtrlRegs.PIEIFR1.bit.INTx1 manually through the emulator, the ADC interupt runs normally.

The ADC interrupt and ADC setup code is as follwoing.

interrupt void adc_isr(void)
 
 GpioDataRegs.GPADAT.bit.GPIO8 = 0x1;
 
 //Function code...
 
 
 GpioDataRegs.GPADAT.bit.GPIO8 = 0x0;
 
 //Clear ADCINT1 flag reinitialize for next SOC
    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;    
    // Acknowledge this interrupt to receive more interrupts from group 1
   PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;  
}
 
void SetupAdc(void)
{
 
 AdcOffsetSelfCal();
 
 EALLOW;
 
 AdcRegs.ADCCTL2.bit.CLKDIV2EN = 1;      //30M ADC clock.
 AdcRegs.ADCCTL1.bit.TEMPCONV = 1;
 
 AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; //ADCINT1 trips after AdcResults latch
 AdcRegs.INTSEL1N2.bit.INT1E     = 1; //Enabled ADCINT1
 AdcRegs.INTSEL1N2.bit.INT1CONT  = 0; //Disable ADCINT1 Continuous mode
 
 AdcRegs.INTSEL1N2.bit.INT1SEL = 12; //setup EOC12 to trigger ADCINT1 to fire
 
 AdcRegs.ADCSOC0CTL.bit.CHSEL = 0;       //set SOC0 channel select to ADCINA0,Vgrid1
 AdcRegs.ADCSOC1CTL.bit.CHSEL = 0;       //set SOC1 channel select to ADCINA0,Vgrid1
 AdcRegs.ADCSOC2CTL.bit.CHSEL = 1;       //set SOC2 channel select to ADCINA1,Vgrid2
 AdcRegs.ADCSOC3CTL.bit.CHSEL = 3;       //set SOC3 channel select to ADCINA3,VpvA
 AdcRegs.ADCSOC4CTL.bit.CHSEL = 5;       //set SOC4 channel select to ADCINA5,Vtemp
 AdcRegs.ADCSOC5CTL.bit.CHSEL = 7;       //set SOC5 channel select to ADCINA7,VpvB
 AdcRegs.ADCSOC6CTL.bit.CHSEL = 8;       //set SOC6 channel select to ADCINB0,IpvA
 AdcRegs.ADCSOC7CTL.bit.CHSEL = 9;       //set SOC7 channel select to ADCINB1,IpvB
 AdcRegs.ADCSOC8CTL.bit.CHSEL = 10;      //set SOC8 channel select to ADCINB2,Vdrv
 AdcRegs.ADCSOC9CTL.bit.CHSEL = 11;      //set SOC9 channel select to ADCINB3,VA33
 AdcRegs.ADCSOC10CTL.bit.CHSEL = 12;     //set SOC10 channel select to ADCINB4,VPE
 AdcRegs.ADCSOC11CTL.bit.CHSEL = 13;     //set SOC11 channel select to ADCINB5,VclampA
 AdcRegs.ADCSOC12CTL.bit.CHSEL = 15;     //set SOC12 channel select to ADCINB7,VclampB
 
 AdcRegs.ADCSOC0CTL.bit.TRIGSEL  = 0x1; //set SOC0 start trigger on TINT0
 AdcRegs.ADCSOC1CTL.bit.TRIGSEL  = 0x1;
 AdcRegs.ADCSOC2CTL.bit.TRIGSEL  = 0x1; 
 AdcRegs.ADCSOC3CTL.bit.TRIGSEL  = 0x1;
 AdcRegs.ADCSOC4CTL.bit.TRIGSEL  = 0x1;
 AdcRegs.ADCSOC5CTL.bit.TRIGSEL  = 0x1;
 AdcRegs.ADCSOC6CTL.bit.TRIGSEL  = 0x1; 
 AdcRegs.ADCSOC7CTL.bit.TRIGSEL  = 0x1;
 AdcRegs.ADCSOC8CTL.bit.TRIGSEL  = 0x1; 
 AdcRegs.ADCSOC9CTL.bit.TRIGSEL  = 0x1; 
 AdcRegs.ADCSOC10CTL.bit.TRIGSEL = 0x1;
 AdcRegs.ADCSOC11CTL.bit.TRIGSEL = 0x1; 
 AdcRegs.ADCSOC12CTL.bit.TRIGSEL = 0x1; 
 
           //Sample window 15 ADC clocks 250ns
 AdcRegs.ADCSOC0CTL.bit.ACQPS  = 9;
 AdcRegs.ADCSOC1CTL.bit.ACQPS  = 9;
 AdcRegs.ADCSOC2CTL.bit.ACQPS  = 8;
 AdcRegs.ADCSOC3CTL.bit.ACQPS  = 8;
 AdcRegs.ADCSOC4CTL.bit.ACQPS  = 8;
 AdcRegs.ADCSOC5CTL.bit.ACQPS  = 8;
 AdcRegs.ADCSOC6CTL.bit.ACQPS  = 8;
 AdcRegs.ADCSOC7CTL.bit.ACQPS  = 8;   //sample time for temperature is 600ns
 AdcRegs.ADCSOC8CTL.bit.ACQPS  = 8;
 AdcRegs.ADCSOC9CTL.bit.ACQPS  = 8;
 AdcRegs.ADCSOC10CTL.bit.ACQPS  = 8;  
 AdcRegs.ADCSOC11CTL.bit.ACQPS  = 8;
 AdcRegs.ADCSOC12CTL.bit.ACQPS  = 8;
 
 EDIS;
}

  • user4848357,

    The ADCINTOVF.ADCINT1 flag is indicating that an ADC interrupt was not serviced in time. The setting of ADCINTOVF can disrupt the normal generation of ADC interrupts. This flag should be cleared through ADCINTOVFCLR before resuming operation.

    If it is necessary to capture every ADC conversion in a series, you will need to determine and fix the task that is delaying the servicing of the normal ADCINT1. If the goal is only to analyze the most recent ADC conversions, you can set the INTSEL1N2.INT1CONT bit to ignore overflow conditions.

    -Tommy
  • Hi Tommy

    Thanks for your timely reply. It's very helpful but I still have some questions.
    1. Why the ADC interupt runs normally after PieCtrlRegs.PIEIFR1.bit.INTx1 setted manually through the emulator?
    2. The ADCINTOVF.ADCINT1 may be set after the ADC interrupt terminate running, is there any other reason causing the interrupt stop running.
  • user4848357 said:
    1. Why the ADC interupt runs normally after PieCtrlRegs.PIEIFR1.bit.INTx1 setted manually through the emulator?

    The termination of interrupts is rooted in the ADC module not generating interrupt triggers to the PIE. Setting the PIEIFR manually serves to replace the missing ADC interrupt trigger.


    user4848357 said:
    2. The ADCINTOVF.ADCINT1 may be set after the ADC interrupt terminate running, is there any other reason causing the interrupt stop running.

    I suspect that ADCINTOVF is the cause of interrupt termination.

  • I cleared the ADCINTOVF before exit the ADC interrupt as the following code, but the interrupt still terminate running. Why?

    AdcRegs.ADCINTOVFCLR.bit.ADCINT1 = 1;

      AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;  

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

      PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;  

    }

    Then I watched the waveform of GPIO8,GPIO8 set after entering the interrupt, and cleared before exit the interrupt. I found that the ADC interrupt terminate when its run time is between 49.4us - 49.5us. When ADC interrupt's run time is larger than 50us, the ADC interrupt didn't terminate. Why?

    PS: the ADC interrupt’s normal trigger time is 50us, CH2 is the waveform of GPIO8

        

    Later I write a test code as the following. The adc interrupt terminate running very quikly with this code. But I download this code into another product, the ADC interrupt didn't terminate. Why?

    interrupt void adc_isr(void)
    {
    GpioDataRegs.GPADAT.bit.GPIO8 = 0x1;

    DELAY_US(49.1);

    GpioDataRegs.GPADAT.bit.GPIO8 = 0x0;

    //Clear ADCINT1 flag reinitialize for next SOC

    AdcRegs.ADCINTOVFCLR.bit.ADCINT1 = 1;
    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;

    // Acknowledge this interrupt to receive more interrupts from group 1
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
    }

  • user4848357,

    You original post described the ADC triggering rate as 50us:

    user4848357 said:
    interrupt 1: ADC interrupt, ADC triggerd by Timer0 (50us period),ADC interrupt is triggerd by the completion of the whole sampling.

    When your ISR is near 50us long, it is almost certain that the next batch of ADC SOCs are triggered while your ISR is executing. Here are three likely outcomes:

    • If the ISR clears the ADCINT and PIE flags before the new SOCs complete, you will not encounter an overflow condition.
    • If the ISR clears the flags after the new SOCs complete, you will have an overflow condition, but the overflow state is cleared with the flags.
    • If the ISR clears some (but not all) flags after the new SOCs complete, you may have an overflow condition that is not serviced

    To avoid overflows, you should either reduce your ISR execution times so that real-time servicing requirements can be met, or configure the ADC interrupts to operate in continuous mode so that the overflows are ignored.

    -Tommy

  • Tommy

    In the following case, which instruction will clear the overflow state?
    If the ISR clears the flags after the new SOCs complete, you will have an overflow condition, but the overflow state is cleared with the flags.
    PS: The ADC interrupt will not terminate running with or without this instruction "AdcRegs.ADCINTOVFCLR.bit.ADCINT1 = 1;" when the ADC interrupt service time is over 50us.

    I tested two chips,only one has this phenomenon as I posted on the previous reply, why?
  • Robin,

    In the scenario I envisioned, the overflow state would be cleared by ADCINTOVFCLR.

    The overflow condition is likely caused by a race condition so additional system variables like clock cycle synchronization and external stimulus can contribute to the probability of failure.

    Again, please configure your ADC to continuous interrupt mode to see if the failures go away.

    -Tommy
  • Tommy
    I have tried configuring the ADC to continuous interrupt mode and the failures go away. But we have a lot of product running in the field, I need to know why this will happen and to evaluate the influence to our deliverd product. What you said is still unclear now and now I only find one with this failure.
    I doubt that when the software tries to clear the ADCINT1 flag while the hardware tries to set it at the same time, the ADCINT1 flag is not cleared at this moment. Will it be a manufacturing flaw
  • Robin,

    The overflow condition is met when the ADCINT1 flag is already asserted when the ADC INT1SEL EOC is triggered. There does not need to be write contention over the ADCINT1 flag.

    It may be useful to enable the Timer0 interrupt to toggle a GPIO pin for profiling. If Timer0 triggers the ADC conversions while the ADC ISR is still executing, there is an increased risk of overflow.

    -Tommy
  • Tommy,

    I have already tested that only when the ADC interrupt service time is between 49.3us to 49.5us,the ADC interrupt will terminate. But the other chip don't behave like this with the same code. You can see the test waveform in the previous reply.
    When the ADC interrupt service time is over 50us, there must be a overflow, but the ADC interrupt is still run with or without clearing ADCINTOVFCLR.
  • Robin,

    It sounds to me like you are seeking root cause identification rather than a workaround. Is this correct?

    I understand that you are not able to identify why the failure is occurring on some devices but not others. With the limited information available, I am also not able to identify how the failure is occurring on some devices but not others.

    Fully identifying the root cause in the system will require methodical and intentional debug. Even though we know that interrupts cease on some devices when a specific range of artificial wait time is inserted in the ISR, we have no visibility into what else is happening inside of the device at the hardware register level. This is the level of information that is needed to understand the sequence of events that lead up to the interrupt issues.

    If you wish to proceed with this level of debug, my recommendation is to begin with either GPIO profiling (or event logging in RAM) of the various background events of ADC triggering, ADC servicing, and states of interrupt flags during these critical events.

    -Tommy
  • Robin,

    It has been a while since your last update. I assume that you were able to resolve your issue.

    If not, please reply to this thread. If the thread has locked due to timeout, please create a new thread describing the current status of your issue.

    -Tommy