5 Replies Latest reply on Jan 10, 2016 1:31 PM by user_385799628

    Question about disabling interrupts

    user_385799628

      Hello, I am wondering if someone could help me clarify the expected behaviour when disabling interrupts as I can’t quite get my head around it at the moment. 

         

      I have setup a falling edge interrupt on a digital input pin, and have an ISR that clears the interrupt and sets a flag.  This all works as expected, however after the interrupt has  been triggered once I expect a series of falling edges so would like to disable the interrupt until these have finished.  I’ve tried using the _stop() and _disable() interrupt API commands and while these do prevent the interrupt from firing whist it is disabled, as soon as I use the _start()/ _enable() commands the ISR is triggered again.  I have tried using the _ClearInterrupt() and _ClearPending() commands just before I re-enable the interrupt but this makes no difference.  I realise that I haven’t disabled the interrupt signal from the digital pin, but would have thought that using _disable() would mean that this signal is ignored, or at the very least using the ClearInterrupt just before re-enabling the Interrupt would mean that any pending interrupts would be cancelled.  Can anyone explain why the ISR is still being triggered please?

         

      Thanks in advance.

        • 1. Re: Question about disabling interrupts
          user_1377889

          Can you please post your complete example project, so that we all can have a look at all of your settings? To do so, use
          Creator->File->Create Workspace Bundle (minimal)
          and attach the resulting file.

             

           

             

          Bob

          • 2. Re: Question about disabling interrupts
            user_385799628

            Well this is a little embarrassing, in tidying up my example code so that I could post it I managed to obtain the desired behaviour.  What I needed to do was use the _ClearInterrupt() then _ClearPending() commands in that order just before re-enabling the interrupt.  I must have tried every other combination of enabling, disabling, clearing, stopping etc. at least twice but managed to miss this one. 

               

             

               

            I guess this makes sense, the interrupt type is set to LEVEL so the GPIO interrupt needs to be cleared before clearing the pending interrupt otherwise a new interrupt will just be pended straight away. 

               

             

               

            However, one thing I am still not entirely clear on is why do I need to clear a pending interrupt?  If the interrupt has been disabled or stopped is it correct that an interrupt request is pended in the first place?

               

             

               

            Anyway I have attached the example project, hopefully someone will find it useful.  Thank you very much for your reply Bob.

            • 3. Re: Question about disabling interrupts
              user_385799628

              Sorry, I meant to mention the above code was written for a CY8CKIT-042 PSoC 4 Pioneer Kit and uses a digital output pin with an external jumper wire to the input pin to generate the interrupts.

              • 4. Re: Question about disabling interrupts
                user_1377889

                Before looking into your project:

                   

                If the interrupt has been disabled or stopped is it correct that an interrupt request is pended in the first place?

                   

                Yes: interrupts are handled by the ICU (Interrupt Controller Unit) which is part of the ARM M0 core. Interrupts have several states as handled, pending etc. Most concern is (of course) not to miss any interrupt, so a blocked (by software or by priority) interrupt becomes pending when the interrupt condition occurs.

                   

                In your project the flaw is to have a "Level" interrupt defined. Because you do not have any influence on the causing signal from inside you cannot remove the interrupt cause, so when the interrupt is handled and the program returns from the handler, the interrupt cause still exists and will at once fire immediately.

                   

                Using a "Falling edge" cause will (despite switch bouncing) occur only once, when the program flow enters the handler, the cause is already removed. No clear is needed.

                   

                The irq output of a pin "remembers" the interrupt and so it has to be cleared at the pin to enable it firing again or to remove the level.

                   

                This is similar to the "sticky bits" of an UART's status register which are used to generate interrupts for that component.

                   

                Now I'm going to look into your project....

                   

                EDIT:

                   

                Yes, as I thought: You still have enabled the interrupt signal of the pin which will be recognized as soon as the interrupt component is re-enabled.

                   

                Usually (in a "normal" project) the handling is done completely within the handler.

                   

                **** One dramatic bug ****

                   

                You have the opportunity (and sometimes you are forced to) setting the optimization level to something different from "Debug". Your

                   

                uint8 intFlag = 0 declaration might fail in constructs like

                   

                while(!intFlag) Wait(); // Wait for an interrupt

                   

                The optimization can (will) take out the invariant intFlag (it does not change within the loop) leaving the program with an infinite loop.

                   

                Declaring

                   

                volatile uint8 intFlag = 0;

                   

                will inform the compiler that intFlag may be changed from the "outside" and so may not be optimized-out.

                   

                 

                   

                Bob

                • 5. Re: Question about disabling interrupts
                  user_385799628

                  Hi Bob, again thank you for replying.

                     

                   

                     

                  In your project the flaw is to have a "Level" interrupt defined.

                     

                  I’ve chosen a level interrupt because the final target for my project is a 4000 series PSoC, which doesn’t support the rising edge setting on GPIO interrupts.  I realise that this is ‘sticky’ and needs to be cleared, but it wasn’t obvious to me that a pending interrupt should be raised if the interrupt had been disabled.

                     

                  Most concern is (of course) not to miss any interrupt, so a blocked (by software or by priority) interrupt becomes pending when the interrupt condition occurs.

                     

                  This explains why the interrupt is still pended even when disabled, thank you.  One consequence of this I have noticed that might catch some people out is that any interrupt source that occurs before the _StartEx() function is used for the very first time will be queued up and cause the ISR to run immediately afterwards.  I suspect a lot of people would think the ISR would run only for interrupt sources that occur after _StartEx() function is called.

                     

                  **** One dramatic bug ****...

                     

                  Thank you for pointing that out, I had actually originally set the flag to volatile but it was one of the things I changed when trying out different combinations and forgot to set it back.