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.

ADC EOC ISR Stops Vectoring Intermittently

I've had a problem with the analog-to-digital converter (ADC) end-of-conversion (EOC) Interrupt not not vectoring intermittently on the F28027 controlCARD.

 

My program has an ePWM driving SOC's on the ADC and then some calculations are done and pins toggled during the subsequent EOC ISR.  When the problem occurred, the program would run flawlessly for a variable amount of time, sometimes seconds or minutes, before it failed.  When it did fail, it did not lock up, as the main loop was still running and the ePWM was still triggering SOC's because the ADC result registers were still updating.  The main loop is just a dummy loop that waits for the EOC ISR's to progress the program.

 

What did go wrong was the AdcRegs.ADCINTFLG.bit.ADCINT1 was being set but it wasn't going to the interrupt routine anymore.  This seemed to happen more quickly when the ADC input was of a low frequency below 100 Hz.  When it failed, the Pie acknowledge register didn't seem to get set anymore.

 

I seemed to track it down to one problematic line that when commented, allowed it to keep processing the EOC indefinitely:

        EPwm1Regs.CMPA.all = (Uint32) floor( (AverageBuffer(fCircularBuffer) + 100000) * ScaleFactor) << 8;

This line does some calculations on the ADC input data and then changes the HRPWM duty cycle to change the output.  I currently have changed this line to multiple lines in the hopes that the very long line might have been confusing the compiler.

        tempfloat32 = (AverageBuffer(fCircularBuffer) + 100000) * LockinToDutyCycleRatio;
        tempUint32 = (Uint32) tempfloat32 << 8;
        EPwm1Regs.CMPA.all = tempUint32;

 

At the moment, it seems to be working, but this failure has been intermittent at times, so I can't be positive it's fixed.  I'd feel more comfortable if I knew:

1. Why it has been failing to do the ADC EOC vectoring?  (even when the ADC was still receiving SOC's and updating the result registers)

2. Is there some way I can recover gracefully if this happens again?  Like resetting the PIE or ADC somehow?

  • Andrew,

    When the fail occurs can you check the state of the ADCINT Flag local in the ADC?  Also please check the state of the INT overflow flag as well.

    I suspect this is timing related to when you are clearing the ADCINT flag in your ISR.  Can you comment on if you are using revision 0 or revision A of the 28027?  You can either look in the REVID in the memory map, or the top of the device; the bottom row will have C- XXXXXX or CA-XXXX.  CA indicated revision A.

    Best,

    Matthew

     

  • You mean the AdcRegs.ADCINTFLG.bit.ADCINT1 flag?  It is set when the fail occurs.  And the overflow flag for that channel in AdcRegs.ADCINTOVF.all is being set too I see now.

     

    Continuous mode is off ( AdcRegs.INTSEL1N2.bit.INT1CONT  = 0; ) so it's starting to make sense.  When continuous mode is off, the interrupt flag and interrupt overflow flag will both be set and no new interrupt pulse will be triggered, right?

     

    So it looks like it takes to long to do the calculation for certain values, the EOC interrupt happens before I left the ADC ISR, and an overflow gets triggered.  Now if I were to turn the continuous mode on, I'm not quite sure what happens.  When the new "interrupt pulse" happens, does that mean it will vector back to the ADC ISR after it leaves?

     

    Thanks too, this is making me feel a bit more at ease.  However, it is a little disturbing to me that in a newer version of the program, I'm taking far too long in the ADC ISR when I'm doing the above periodic calculation.  I have some debug pulses I can see on my oscilloscope to show how long it spends in the ISR compared to the ePWM rate of the ADC.  Shouldn't it be overflowing under that condition too?

  • Oops, so I see now there's more to it.  I just purposefully put a software delay in the ISR to make sure it overflowed.  At the same time I commented out the problematic calculation / duty cycle update line. 

     

    In that case the overflow flag is being set, but it continues to run, it never fails to run the EOC triggered ADC ISR.  So what else could be causing the failure?

  • I forgot to say which revision too, it looks like zero?  On the F28027 chip itself the last line is "C88ACY8T."

    The silkscreen on the controlCARD says "F2802xx (Piccolo-A)" though.  As for the memory map, do you mean the mapping in the linker CMD file?  I couldn't find a "REVID."

     

    I did find a register DevEmuRegs.REVID that is reporting "0" however.

  • As an update, it failed again even though I had the calculation on multiple lines:

            tempfloat32 = (AverageBuffer(fCircularBuffer) + 100000) * Scaling;
            tempUint32 = (Uint32) tempfloat32 << 8;
            EPwm1Regs.CMPA.all = tempUint32;

  • I've maybe narrowed it down more.  I split the calculation into more lines, so there was only one operation per line.  I then started commenting from the bottom up to see when it would stop failing.

     

            tempfloat32 = (AverageBuffer(fCircularBuffer) + 100000);
            tempfloat32B = tempfloat32 * Scaling;
            tempUint32 = (Uint32) tempfloat32B; 

    It seems that the last line where I cast the float to a Uint is the problem.  So far it seems to always fail when I have the cast line in place, and doesn't when I comment it out.  I tried using implicit casting too.  The disassembly for that line is:

    0x008054:   0604        MOVL         ACC, @0x4
    0x008055:   767F6861    LCR          FS$$TOUL
    0x008057:   761F0220    MOVW         DP, #0x220
    0x008059:   1E0E        MOVL         @0xe, ACC

     

  • Andrew,

    If you place the ADCINT in continous mode does this solve the problem?  From you description I think this is all timing related, not necessarily what the instruction is doing but when it aligns the ADC Interrupt being set vs when your ISR tried to clear it. 

    I beleive there is contention on the interrupt bus when these collide; and if the INTFLG does not get cleared in the ISR, then another ISR will never be generated.  Setting the CONT interrupt mode in the ADC should handle this.

    Please let me know if this is the case.

    Matt

  • Thanks Matt, that did work.  I guess I expected that if it wasn't in continuous mode, it would always note the overflow and stop the ISR vectoring, but it was only happening under special conditions sometimes.

  • Hello Andrew,

                            I come up with the similar problem exactly you faced long time ago. This problem is uncertain, i just can't guess after how much my ADC isr will stop its working. Sometimes it takes 18 hours, sometimes 6 hours when optimization level off.  Sometimes 3 hours, and even sometimes 1 hour when I set optimization level 1.

                            In my code there are 2 ADC ISR out of which one ADC ISR(where heavy processing is performed) stop its working  intermittently and another ISR is working properly. 

                           I've disabled ADC EOC ISR continuous mode  too.

                         Do you any suggestions for such kind of problem?