9 Replies Latest reply on Oct 24, 2018 1:11 PM by otniel.gonzalez

    ADC interrupt halts / stops itself randomly

    otniel.gonzalez

      Hi PSoC Community,

       

      I'm working with the firmware of a product we will be launching soon.  We are using PSoC 4 (CY8C4245AZI-473) with internal clock set to 48 MHz and VCC to 5V.  I have enabled the ADC as hardware triggered so I can start a conversion manually using ADC_StartConvert() function.  This is the code for ADC initializing:

       

          ADC_Start();                                               // Starts ADC

          ADC_IRQ_StartEx(ADCINT_SERVICE);   // Function assigned to ADC interrupt

          ADC_EnableInjection();                             // Enable Inj channel for microcontroller temperature reading

          ADC_SetLimitMask(0);                               // Avoids limit values interrupt

          ADC_SetSatMask(0);                                 // Avoids saturation values interrupt

          ADC_StartConvert();                                // Start ADC conversions

       

      This is the interrupt code:

       

      CY_ISR(ADCINT_SERVICE)              // Sets flag indicating end of conversion

      {

          uint32 intr_status;

       

          intr_status=ADC_SAR_INTR_REG;   // Reads interrupt flags from ADC

          if(intr_status&1)               // Masks all interrupt flags except end of conversion

          FlagAdc=1;                      // Indicates conversion ready

          ADC_SAR_INTR_REG=intr_status;   // Clear interrupt flags

      }

       

      This code goes inside main():

       

              if(FlagAdc)                     // Ha terminado una conversion del ADC?

              {

                  FlagAdc=0;

                  AdcWDT=0;

                  adc_read(Conversions);  // Procesa las medidas capturadas por el ADC

              }

       

      And this is the function to read the ADC conversions:

       

      void adc_read(uint16 *Ptr)

      {

          int16 TempAdc;        // Used to read ADC values

          uint8 AdcChannel;     //ADC channel

         

          if(Flag.MicroTempRead)      // Time to read microcontroller temperature?

          {

              Flag.MicroTempRead=0;

              Ptr[TM]=(uint16)(ADC_GetResult16(TM)/8);    // Reads microcontroller temperature

          }

         

          for(AdcChannel=0;AdcChannel<TM;AdcChannel++)   

          {  

              TempAdc=ADC_GetResult16(AdcChannel)/8;      // Gets average of each conversion

              if(TempAdc<0)                               // Negative values?

              TempAdc=0;                                  // Convert them to zero

              Ptr[AdcChannel]=(uint16)TempAdc;

          }

         

          if(Flag.MicroTempAsk)      // Ready for microcontroller temperature?

          {

              Flag.MicroTempAsk=0;

              ADC_EnableInjection();  // Enables injection channel for microcontroller temperature

              Flag.MicroTempRead=1;   // Indicates microcontroller temperature reading next time

          }

         

          ADC_StartConvert(); // Starts next conversions

      }

       

      The problem is that sometimes the conversions stops updating, like if the ADC end of conversion interrupt was suddenly disabled.  This happens randomly, the product could run nice for several hours and then the problem appears.  We have tested about ten units, but two of them shows this issue.  All of the other interrupts and functions (PWM, timer, Watchdog timer, I2C, UART, etc.) keeps running smoothly.

       

      Question: What could cause the ADC interrupt EOC to stop without user consent?

       

      Thanks for your help.

        • 1. Re: ADC interrupt halts / stops itself randomly
          bob.marlowe

          Would be of some interest where the program stops. Probably FlagAdc (which needs to be declared volatile) is not set. This can happen as far as I can see due to a race condition in the main loop and the interrupt handler.

           

          Bob

          1 of 1 people found this helpful
          • 2. Re: ADC interrupt halts / stops itself randomly
            otniel.gonzalez

            Hi Bob,

             

            Thanks for replying.  This is the declaration of FlagAdc:

             

            volatile uint8 FlagAdc=0;           // End of conversion of ADC

             

            The program behaves as if after the last conversion, the interrupt never happens again.  The strange thing is that this problem shows very random.

             

            I was wondering about maybe some stack overflow that could overwrite the value of FlagAdc. This is the memory usage:

             

            Flash used: 30474 of 32768 bytes (93.0 %). Bootloader: 5376 bytes. Application: 24970 bytes. Metadata: 128 bytes.

            SRAM used: 3028 of 4096 bytes (73.9 %). Stack: 1024 bytes. Heap: 0 bytes.

             

            At first I used to have many variables declared inside main() but the compiler did not tell me the right amount of RAM used, so I put these as globlal variables and the usage changed from near 75% to 93%.  If other functions use static variables to keep values, could this cause a stack overflow and corrupt variable FlagAdc?

            • 3. Re: ADC interrupt halts / stops itself randomly
              bob.marlowe

              Static variables are not allocated on the stack. so no overflow by those.

               

              Stack overflow: You may put an address breakpoint near top of stack

              you can check FlagAdc for being out of range (> 1)

               

              Bob

              1 of 1 people found this helpful
              • 4. Re: ADC interrupt halts / stops itself randomly
                xzng

                Did you connect any hardware signal to SOC terminal of SARADC?  If it is possible the soc signal is asserted while SARADC is busy(), then the data in the result register interprets it as incorrect and the Component will be stalled.  So when your SARADC is stopped, is the last conversion result correct? You may try to check the busy state of ADC before trigger the next scan conversion and see what happened.

                1 of 1 people found this helpful
                • 5. Re: ADC interrupt halts / stops itself randomly
                  otniel.gonzalez

                  Hi xzng,

                   

                  The SOC terminal of the ADC is tied to logic '0'.  The last result conversion is correct.  I'm using 6 channels and the injection channel. I start the conversions by software, using ADC_StartConvert(). I masked any other interrupt, except EOC. This is the sequence I use:

                   

                  1. Start conversions

                  2. Work with functions in main

                  3. (Inside ISR) ADC interrupt? If it was EOC, activate FlagADC

                  4. (Inside main) FlagADC active? Clear FlagADC, reads conversions and start conversions again

                  5. Return to step 2

                   

                  It looks like there is a moment where FlagADC is not set anymore. Unfortunately this happens very random and seldom.  I wonder, as you say, if maybe I'm triggering the start of conversion during a current conversion, the component would stop.  If so, how would be the procedure to restart the ADC normally?

                   

                  Thanks.

                  • 6. Re: ADC interrupt halts / stops itself randomly
                    otniel.gonzalez

                    Hi Bob,

                     

                    I have checked the stack usage as you said, it seems the problem is not related to stack overflow.  I'll try debugging inside the ADC interrupt to see if I can find a clue.

                     

                    Thanks.

                    • 7. Re: ADC interrupt halts / stops itself randomly
                      xzng

                      I read one note in TRM "If the injection channel is tailgating a scan (Injection channel tailgating is enabled by default), the EOS_INTR is raised in parallel to starting the injection channel conversion. The injection channel is not considered part of the scan. " This means EOS interrupt occur after completing a scan of all the enabled channels except INJ channel, INJ channel trigger INJ_EOC_INTR  interrupt when Injection channel end of conversion. So when FlagAdc=1, the INJ channel may still being in conversion.

                       

                       

                      111.JPG

                      1 of 1 people found this helpful
                      • 8. Re: ADC interrupt halts / stops itself randomly
                        otniel.gonzalez

                        Hi xzng,

                         

                        You are right, I was masking the injection EOC interrupt thinking that the EOS would do the same trick, but not.  I will modify the software to detect both interrupts separately (EOS and INJ EOC), read each conversion also separately and trigger the ADC with a timer giving enough time for total ADC conversion so the trigger does not collide with any conversion in progress.

                         

                        I'll do some tests and let you know.

                         

                        Thanks.

                        • 9. Re: ADC interrupt halts / stops itself randomly
                          otniel.gonzalez

                          Hi everybody,

                           

                          Several hours and no glitch, looks like the problem was solved.

                           

                          Thanks!