3 Replies Latest reply on Jun 4, 2019 5:54 PM by MoTa_728816

    sprintf failure in ISR

    jotic_1250681

      I need to put a few lines of code in an interrupt service routine (ISR) to print the value in a variable at the time of the interrupt.  Timing is not critical, this is just a test to check an operation.  I have a CY8CKIT-059 board and use a counter (Counter_3X) to create the interrupt.  Here is the ISR

       

      *  Place your includes, defines and code here

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

      /* `#START Counter_3X_Done_intc` */

         

          extern void Counter_3X_Stop();      //Stop Counter_3X

          extern uint16 charindex;            //Value from main program

          char strMsg3X[30];                  //Set up array for characters to print   

          sprintf(strMsg3X,"CharIndex = %u\r\n",charindex);      //Line 34

          int UART_1_PutString(strMsg3X);                        //Line 35

         

      /* `#END` */

       

      The first line (Line 34 in boldface) produces the Build error, "expected ')' before string constant" and when I hover over the string, the cursor shows "expected identifier".

       

      When I hover over Line 35, I read the following, "a parameter list without types is only allowed in a function definition."  I have no idea what this means.

       

      I have attached an image of the error and warning messages.  All I need is a way to display a value on a terminal for tests.  No printing will occur in the finished code.  If you can suggest an alternate way to accomplish my testing goal, I welcome your ideas.  Thank you. --Jon

        • 1. Re: sprintf failure in ISR
          MoTa_728816

          Hi,

           

          In general, using print type function in an isr is not recommended.

           

          Having said that, what I could notice was

          >     int UART_1_PutString(strMsg3X);                        //Line 35

          should be

          <    UART_1_PutString(strMsg3X);                        //Line 35

           

          Would you let me know, what kind of error(s) you will get after modifying the above?

           

          moto

          • 2. Re: sprintf failure in ISR
            LePo_1062026

            Jon,

             

            Moto is correct.  The general principle I learned long ago is to only perform the bare minimum in ISRs.  Basically just gather the data and/or turn on something quickly.  What ever the ISR was truly intended for.  All other time intensive operations should be done at the higher-level Application SW.  sprintf()s and PutString() functions are time intensive and will probably use quite a bit of stack.  Inside an ISR, you've already used a bit a stack to get there.

             

            If more processing is needed after executing an ISR, then set a signal (RAM flag for example) so that the Application task level can pick up the signal can execute the additional operations.

             

            Len

             

            PS:  I recommend using snprintf() instead of sprintf().  snprintf() is an ANSI-safe function.  It prevents string buffer overruns.

            • 3. Re: sprintf failure in ISR
              MoTa_728816

              Hi,

               

              So I tested it by myself using CY8CKIT-059.

               

              I emulated your project with following schematic.

              002-schematic.JPG

               

              To make it work, I needed to modify the ISR as

              (part of Counter_3X_Done.c)

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

              CY_ISR(Counter_3X_Done_Interrupt)

              {

                  #ifdef Counter_3X_Done_INTERRUPT_INTERRUPT_CALLBACK

                      Counter_3X_Done_Interrupt_InterruptCallback();

                  #endif /* Counter_3X_Done_INTERRUPT_INTERRUPT_CALLBACK */

               

                  /*  Place your Interrupt code here. */

                  /* `#START Counter_3X_Done_Interrupt` */

              //    #include "project.h"

              //    #include "stdio.h"

                  extern void Counter_3X_Stop() ;

                  extern void Counter_3X_ReadStatusRegister(void) ;

                  extern uint16 charindex ;

                  char strMsg3X[30] ;

                

                  Counter_3X_Done_ClearPending() ;

                  Counter_3X_ReadStatusRegister() ;

                

                  sprintf(strMsg3X, "CharIndex = %u\r\n", charindex) ;

                  UART_1_PutString(strMsg3X) ;

                  /* `#END` */

              }

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

               

              and the main.c

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

              #include "project.h"

              #include "stdio.h"

               

              uint16 charindex = 0 ;

               

              char str[128] ; /* print buffer */

              void print(char *str)

              {

                  UART_1_PutString(str) ;

              }

               

              void init_hardware(void)

              {

                  UART_1_Start() ;

                

                  Counter_3X_Done_ClearPending() ;

                  Counter_3X_Done_Start() ;

               

                  Counter_3X_WriteCounter(0) ;

                  Counter_3X_Init() ;

                  Counter_3X_Enable() ;

                

                  CyGlobalIntEnable; /* Enable global interrupts. */

              }

               

              void splash(void)

              {

                  sprintf(str, "PSoC LP5 Interrupt Test A (%s %s)\r\n", __DATE__, __TIME__) ;

                  print(str) ;

              }

               

              int main(void)

              {

                  init_hardware() ;

                

                  splash() ;

               

                  for(;;) {

                      charindex++ ;

                      CyDelay(100) ;

                  }

              }

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

               

              And the Tera Term log was

              000-TeraTerm-LogA.JPG

              So anyway, the project seems to be working.

               

              But as I wrote earlier, having sprintf(), PutString() in ISR is not recommend because of a couple of reasons (IMHO)

              (1) They usually take rather long time, where an ISR is expected return as soon as possible.

              (2) They tend to allocate and/or move memory, which is also not good for an ISR, in some MCU it causes hang.

               

              Meantime, in general, I don't want touch "system generated source/header", for example

              "Counter_3X_Done.c" in this case.

               

              I'd rather use Counter_3X_Done_StartEx() instead of Counter_3X_Done_Start() 

              so that I can prepare the ISR in my source files.

              In the following example, "counter_done_isr()".

               

              I rewrote the program as below.

              I used Counter_3X_Done_StartEx(),

              and in the ISR I only saved charindex to a variable "value_at_int"

              and print it in the main loop.

              Note: Please forgive me for using sprintf() instead of snprintf() ;-P

               

              main.c

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

              #include "project.h"

              #include "stdio.h"

               

              volatile uint16_t value_at_int = 0 ;

              volatile int counter_done_flag = 0 ;

              uint16_t charindex = 0 ;

               

              char str[128] ; /* print buffer */

              void print(char *str)

              {

                  UART_1_PutString(str) ;

              }

               

              CY_ISR(counter_done_isr)

              {

                  Counter_3X_ReadStatusRegister() ;

                  Counter_3X_Done_ClearPending() ;

                 

                  counter_done_flag = 1 ;

                  value_at_int = charindex ;

              }

               

              void init_hardware(void)

              {

                  UART_1_Start() ;

                 

                  Counter_3X_Done_ClearPending() ;

                  Counter_3X_Done_StartEx(counter_done_isr) ;

               

                  Counter_3X_WriteCounter(0) ;

                  Counter_3X_Init() ;

                  Counter_3X_Enable() ;

                 

                  CyGlobalIntEnable; /* Enable global interrupts. */

              }

               

              void splash(void)

              {

                  sprintf(str, "PSoC LP5 Interrupt Test B (%s %s)\r\n", __DATE__, __TIME__) ;

                  print(str) ;

              }

               

              int main(void)

              {

                  init_hardware() ;

                 

                  splash() ;

               

                  for(;;) {

                      charindex++ ;

                     

                      if (counter_done_flag) {

                          counter_done_flag = 0 ;

                          sprintf(str, "charindex = %d\n", value_at_int) ;

                          print(str) ;

                      }

                      CyDelay(100) ;

                  }

              }

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

               

              The Tera Term Log was

              001-TeraTerm-logB.JPG

               

              moto

               

              P.S. Attached are

              int_test_190605A printing in the ISR

              int_test_190605B printing in the main loop