4 Replies Latest reply on Jul 30, 2019 6:47 AM by LaAd_4048266

    interrupt service routine running before interrupt

    LaAd_4048266

      i have four switches attached to 4 input pins with resistive pull ups in a CY8CKIT-059 PSoC 5LP

       

      pressing a switch or releasing a switch causes an interrupt that saves the time according to a

      fixed function counter, 16 bit (interrupt occurs on rising and falling edges)

       

      the interrupt routine writes a variety of information to a character LCD display

      including which pin (switch) was pushed or released, how many datum have been recorded,

      and the recorded data

       

      after programming or after reset (switch on kit-059) the display shows "release"

      but "release" is written to the display only on a rising edge (switch release) interrupt

       

      in addition, count start command (API) is supposed to happen on first switch activation (regardless of switch)

      but it appears to start immediately

      also, if one waits a while before pressing a switch, it is clear that the counter has counted (is not at max count)

       

      hence it looks like the interrupt service routine is run once before any switches are pressed

       

      why is that happening and what can i do about it?

       

      archive bundle attached

        • 1. Re: interrupt service routine running before interrupt
          BoTa_264741

          LaAd,

          I may suggest using an existing switch-button library, which handles button press and release events with debouncing

          ButtonSw32: button switch debouncer component

           

          /odissey1

          ButtonSw_basic_1a.png

          1 of 1 people found this helpful
          • 2. Re: interrupt service routine running before interrupt
            NoriakiT_91

            Please try isr_1_ClearPending(); after isr_1_StartEx(PinISRHandler);

            1 of 1 people found this helpful
            • 3. Re: interrupt service routine running before interrupt
              MoTa_728816

              Hi,

               

              I think that I'd like to call

                   isr_1_ClearPending() ;

              and

                  InPin_ClearInterrupt();

               

              before calling

                   isr_1_StartEx(PinISRHandler) ;

               

              But as far as they are before "CyGlobalIntEnable ;" it may be OK.

               

              And also I'd like to place following lines before  "for (;;) " loop

              ================

                      //Set up interrupt and set address as the ISR vector for the interrupt.

                      isr_1_StartEx(PinISRHandler);

                

                      CyGlobalIntEnable;

              ================

               

              And (sorry for being too picky), I'd suggest you not to place

              LCD_Position() and/or LCD_PrintString() inside ISR.

              In the ISR, just set flags to notify the main (or foreground) task

              to take care of such time consuming procedures.

               

              So I tried to modify your main.c like below, may be I'm mis-understanding the logic though.

              ====================

              /*******************************************************************************

              * File Name: main.c

              * Pandrol / Vortok USA

              * 5688 Tec Drive

              * Avon New York 14414

              * L M Adelson

              * July 2  2019

              *

              * Version: 1.0

              *

              * Description:

              *  This project writes text to a 4x20 LCD display

              *  The operating device is PSoC CY8CKIT-059

              *  The processor is CY8C5888LTI-LP097

              *  The operating LCD Display is a Crystalfontz America CFAH2004A-TMI-JT

              *  The processor communcates to the LCD in parallel using a 4 bit interface

              *  Two switches are operated via interrupt to change the display

              *

              *******************************************************************************/

               

              #include <project.h>

               

              /*******************************************************************************

              * Function Name: main

              ********************************************************************************

              *

              * Summary:

              *  The main program does the following

              *  1. Initializes the LCD.

              *  2. Writes text to each of 4 lines of display.

              *  3. waits for interrupt from 4 inputs indicating a change of state

              *     either a switch is pushed (pin goes low) or released (pin goes high)

              *     don't know what order push / release will be

              *     first push starts timer and records time

              *     subsequent push or release cause time to be recorded in appropriate memory

              *     after 8 data recorded, write all 8 dataum to LCD as:

              *     push switch 1       release switch 4

              *     push switch 2       release switch 4

              *     push switch 3       release switch 4

              *     push switch 4       release switch 4

              *  CAVEAT: if you write more than 20 charaters, it does a cr lf lf

              *  so the line continues with a skipped line

              *  anything on that line gets overwritten

              *

              * Parameters:

              *  None.

              *

              * Return:

              *  None.

              *

              *******************************************************************************/

               

              // initialize parameters        

                 

              uint8 pos = 0u;                  // column of LCD dispaly to wrtie in     

              uint8 row = 0u;                  // row of LCD dispaly to wrtie in        

              uint8 count = 0u;                // count how many times get an interrunpt 

              uint8 pin_stat = 0u;             // read interrupt vector value (stat for status)           

              uint8 last_pin_stat = 0u;        // pin status before present switch operation

              uint8 change_pin_stat = 0u;      // changed in pin status - i.e. which switch                   

              uint8 mode = 0u;                 // counter for how many interrupts seen   

              int counts[20];                  // variable to store counts               

              int num = 0;                     // temp variable                          

              uint8 i;                         // index variable for loops               

              uint8 press_release_flag = 0;    // 0 is false for release 1 is true for press

               

              volatile int intr_flag = 0 ;        // <-- added

              volatile int pin_changed_flag = 0 ; // <-- added

               

              // interupt prototype delcaration

              // PinISRHandler is routine when get pin interrupt

              CY_ISR_PROTO(PinISRHandler); 

               

              void report_mode(void) ;            // <-- added

               

              int main()

              {  

                  LCD_Start() ;

                 

                  /* Clear pin Interrupt */

                  InPin_ClearInterrupt();

                 

                  isr_1_ClearPending() ;

                 

                  //Set up interrupt and set address as the ISR vector for the interrupt.

                  isr_1_StartEx(PinISRHandler) ;

                 

                  CyGlobalIntEnable;

                 

                  for(;;)

                  {

                      CyDelay(2000);              //pause

               

                      mode = 0;

                     

                      {       

                          while (mode < 8)          //mode specifies number of edges detected

                          {}                        //start with 0, end after 4 switches or

                                                    //at 8 transitions

                     

                          for (i = 0; i < 4; i++)   //clear screen

                          {

                              LCD_Position(i, 0);

                              LCD_PrintString("                    ");

                          }

                 

                          for (i = 0; i < 19; i++)

                          {

                              if (counts[i] == 0) counts[i] = 65535;

                          }

                         

                          if (intr_flag) {

                              intr_flag = 0 ;

                              if (press_release_flag) {

                                  LCD_Position(0, 0);

                                  LCD_PrintString(" push     ");

                              } else {

                                  LCD_Position(0, 0);

                                  LCD_PrintString(" release     ");

                              }

                              if (pin_changed_flag) {

                                  pin_changed_flag = 0 ;

                                  report_mode() ;

                              }

                          }

                     

                          //write output to LCD

                          LCD_Position(0, 0);

                          LCD_PrintU32Number(counts[1]);

                          LCD_Position(0, 8);

                          LCD_PrintU32Number(counts[11]);

                 

                          LCD_Position(1, 0);

                          LCD_PrintU32Number(counts[2]);

                          LCD_Position(1, 8);

                          LCD_PrintU32Number(counts[12]);

                 

                          LCD_Position(2, 0);

                          LCD_PrintU32Number(counts[4]);

                          LCD_Position(2, 8);

                          LCD_PrintU32Number(counts[14]);

                     

                          LCD_Position(3, 0);

                          LCD_PrintU32Number(counts[8]);

                          LCD_Position(3, 8);

                          LCD_PrintU32Number(counts[18]);

                 

                          mode = 0;

               

                          Counter_Stop();

                          Counter_WriteCounter(0);   //reset to full count via rollover

                      }

                  }

                 

              }

               

               

              /*******************************************************************************

              * Function Name: PinISRHandler

              ********************************************************************************

              *

              * Summary:

              *  This subroutine handles the interrupts

                 1. Initializes the LCD.

              *  2. Writes text to each of 4 lines of display.

              *  CAVEAT: if you write more than 20 charaters, it does a cr lf lf

              *  so the line continues with a skipped line

              *  anything on that line gets overwritten

              *

              * Parameters:

              *  None.

              *

              * Return:

              *  None.

              *

              *******************************************************************************/

               

              CY_ISR(PinISRHandler)

                 

                  num = Counter_ReadCounter();

                  pin_stat = InPin_Read();

                 

                  if (mode == 0)

                  {

                      Counter_Start();

                      last_pin_stat = 0;

                  }

                 

                  if (pin_stat > last_pin_stat)

                  {

                      change_pin_stat = pin_stat - last_pin_stat;

                      press_release_flag = 1;  // 0 is false for release 1 is true for press    

                  }

                  else

                  {

                      change_pin_stat = last_pin_stat - pin_stat;

                      press_release_flag = 0;  // 0 is false for release 1 is true for press

                  }

                 

                   /* Clear pending Interrupt */

                  isr_1_ClearPending();

                    

                  /* Clear pin Interrupt */

                  InPin_ClearInterrupt();

                 

                  /* what changed?      */

                 

                  if (press_release_flag)          //here for switch pushed // 0 is false for release 1 is true for press

                  {

                      counts[change_pin_stat] = num;

              //        LCD_Position(0, 0);

              //        LCD_PrintString(" push     ");

                  }

               

               

                  if (! press_release_flag)          //here for switch released // 0 is false for release 1 is true for press

                  {

                      counts[change_pin_stat + 10] = num;

              //        LCD_Position(0, 0);

              //        LCD_PrintString(" release     ");

                  }

                 

                  if (last_pin_stat != pin_stat)            // take care of change condition

                  {

                      pin_changed_flag = 1 ;

              /*

                      LCD_Position(1, 0);

                      LCD_PrintString("mode     ");

                      LCD_PrintNumber(mode);

                      LCD_PrintString("   ");

                 

                      LCD_PrintString("pin ");

                      LCD_PrintNumber(pin_stat);

                      LCD_PrintString(" ");

                 

                      LCD_Position(2,0);

                      LCD_PrintString("last ");

                      LCD_PrintNumber(last_pin_stat);

                      LCD_PrintString("  ");

                      LCD_PrintString("change ");

                      LCD_PrintNumber(change_pin_stat);

                      LCD_PrintString(" ");

                    

                      LCD_Position(3, 0);

                      LCD_PrintString(" counts   ");

                      LCD_PrintNumber(num);

                      LCD_PrintString("   ");

              */   

                      mode = mode + 1;

                      last_pin_stat = pin_stat;

                  }

                    

                  if (mode > 8)

                  {

                      Counter_Stop();

                      Counter_Init();

                  }

               

               

              }

               

              void report_mode(void)

              {

                  LCD_Position(1, 0);

                  LCD_PrintString("mode     ");

                  LCD_PrintNumber(mode);

                  LCD_PrintString("   ");

                 

                  LCD_PrintString("pin ");

                  LCD_PrintNumber(pin_stat);

                  LCD_PrintString(" ");

                 

                  LCD_Position(2,0);

                  LCD_PrintString("last ");

                  LCD_PrintNumber(last_pin_stat);

                  LCD_PrintString("  ");

                  LCD_PrintString("change ");

                  LCD_PrintNumber(change_pin_stat);

                  LCD_PrintString(" ");

                    

                  LCD_Position(3, 0);

                  LCD_PrintString(" counts   ");

                  LCD_PrintNumber(num);

                  LCD_PrintString("   ");

              }

               

               

              /* [] END OF FILE */

              ====================

               

              moto

              1 of 1 people found this helpful
              • 4. Re: interrupt service routine running before interrupt
                LaAd_4048266

                to BoTa: I will look into ButtonSw32

                 

                to Noriaki Tanaka and Motoo Tanaka:

                I tried your suggestions

                I ended up with

                isr_1_ClearPending();

                InPin_ClearInterrupt(); 

                 

                isr_1_StartEx(PinISRHandler);

                 

                isr_1_ClearPending();  

                removing any of the clear statements did not solve my issue

                Ii appears I need all three

                 

                to Motoo Tanaka:

                Thank you for the re-write. I will follow your suggestion