cancel
Showing results for 
Search instead for 
Did you mean: 

PSoC 5, 3 & 1 MCU

Anonymous
Not applicable

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. 

   

 

   

  

0 Likes
Reply
4 Replies
Esteemed Contributor

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

   

by designer. Some references -

   

   

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

   

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

   

   

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;
}

0 Likes
Reply
Esteemed Contributor

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.

0 Likes
Reply
Anonymous
Not applicable

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.    

0 Likes
Reply
Anonymous
Not applicable

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

0 Likes
Reply