4 Replies Latest reply on Dec 19, 2012 9:32 PM by content.librarian

    Timer ISR

    tanisha.g

      I need to implement a Timer Terminal Count Interrupt. Since it is easy to write the code in C, I am creating the ISR in C. I need suggestions on which is a better method to call the ISR.

         

      The mapping is already done in boot.asm, should I overwrite it with the C function or should I call the C function from the Timer8_ISR? Also, should I use ljmp or LCALL to call the C function. 

         

       

         

        

        • 1. Re: Timer ISR
          user_14586677

          You can write the ISR in C or use the placeholder ISR f() call created

             

          by designer. Some references -

             

           

             

          [url]http://www.planetpsoc.com/component/content/article/43-writing-a-c-isr.html[/url]

             

          [url]http://www.planetpsoc.com/psoc1-articles-digital/13-basics-of-psoc-gpio.html?start=7[/url]

             

           

             

          Re: How do I implement an interrupt service routine in C on the PSoC1?

             


          C interrupt service routines can be implemented in the PSoC1 by making an interrupt declaration in C and adding an ljmp to an assembly language file. This article explains both steps needed. Note there is a difference in the C ISR declaration between the Imagecraft compiler and the Hi-Tech compiler. This difference is detailed below.

             


          C ISR Declaration in Imagecraft
          The Imagecraft compiler uses the #pragma interrupt_handler directive. This is documented in section 6.6 of the C Language Users Guide. The #pragma interrupt_handler will tell the C-compiler to save/restore registers and use an interrupt return at the end of execution. The Imagecraft usage is as follows for an interrupt named foo:

             

          #pragma interrupt_handler foo

             

          void foo(void)
          {
          //Place interrupt service code here
          return;

             

          }
          Make sure you are using the correct name in your #pragma statement, since the Imagecraft compiler will not give you a warning if you make a mistake with the name used in the #pragma (and your ISR will not work properly).

             


          C ISR Declaration in Hi-Tech
          For Hi-Tech, the interrupt declaration is made in the function declaration instead of a #pragma. This is documented in section 3.8.1 of the Hi-Tech User Manual:
          void interrupt foo(void)@0x00
          {
          //Place interrupt service code here
          return;
          }

          • 2. Re: Timer ISR
            user_14586677

            Do not forget (if C ISR) to place a ljmp in the boot.tpl file in root project

               

            directory. If you C ISR is named TimeISR then typing will be "ljmp   _TimeISR"

               

             

               

            Also, as a general practice try to minimize the f() calls within the ISR, this creates

               

            a lot of overhead/stack push that can really slow down machine response. Generally

               

            set a flag, leave ISR, and process in main().

               

             

               

            Lastly if GPIO ISR, all GPIO pin ISRs are aggregated into one, so you have to use a

               

            mask to test for which pin created the ISR.

               

             

               

            Regards, Dana.

            • 3. Re: Timer ISR
              content.librarian

              Difference between LJMP and  LCALL

                 

               

                 

              LJMP is a pure branching instruction. CPU jumps to location specified and doesn’t return back to location from where it branched. If ljmp instruction is called from an assembly ISR, for example as shown in the SleepTimer_Interrupt_Project, then the “reti” instruction after the ljmp instruction is not executed.    

               

                 

              org   64h   ;Sleep Timer Interrupt Vector     

               

                 

              ljmp _SleepTimer_ISR     

               

                 

              reti    

               

                 

              In order to take care of restoring the registers and PC, we need to declare the C function as an interrupt handler using #pragma as follows    

               

                 

              #pragma interrupt_handler SleepTimer_ISR_C    

               

                 

              Here, “SleepTimer_ISR_C” is the interrupt handler C function. The compiler automatically adds “reti” instruction at the end of this function and hence PC and Flag registers are automatically restored.

                 

               

                 

              LCALL is just like an interruption in normal sequential execution and after executing the called routine, the CPU gets back to place where it left. So, the “reti” already present in the assembly ISR will execute to restore the registers and PC. No need of #pragma directive declaration for the C functions.

                 

              Here, the C function is just like any other C function and you need to manually preserve and restore the virtual registers and page pointers before calling the C function from assembly routine. This can be done by using preserve and restore macros as shown below.    

               

                 

              PRESERVE_CPU_CONTEXT     

               

                 

              lcall _SleepTimer_ISR_C     

               

                 

              RESTORE_CPU_CONTEXT

                 

              The preservation and restoration of CPU_CONTEXT costs around 150 to 200 instructions cycles, 16 to 20 bytes of stack usage and 46 to 59 bytes of flash. Due to this overhead, LCALL method is not recommended for time critical ISR’s.    

              • 4. Re: Timer ISR
                content.librarian

                Hi Tanisha,

                   

                So, actually speaking you can either call the c function from the Timer ISR or map it directly in boot.asm but it is better to map it in boot.asm so that the execution is faster.

                   

                Best Regards

                   

                Anshul