How to perform timer interrupt service routine in PSoC1?

A catchall for PSoC Mixed-Signal Array (microcontroller) discussions not captured by the other forums.

Moderator: ericb

How to perform timer interrupt service routine in PSoC1?

Postby jhyap on Mon Oct 31, 2011 1:20 am

Hi I am totally new to PSoC. I am using CY8C27443-24PXI.

My objective is to set a timer to toggle a LED for every 1 second. But the problem is, I do not know how to configure the hardware setting in PSoC designer and how to code using the existing features available in PSoC. I would like to get some help on the coding part and the configuration part.

Below is some of my idea to toggle a LED for every 1 second.


int main(void)
{
unsigned char 1secFlag = 0;

setup_timer16(); // set timer to interrupt every 10ms (But how to set this? Do I need to edit the assembly code in boot.tpl?)
M8C_EnableGInt;
Timer16_EnableInt();
Timer16_Start();
LED_Start();

while(1)
{
if(1secFlag == 1){
LED_Switch(); //Turn ON LED
1secFlag = 0;
}
}
return 0;
}

void timer_isr(void) //timer interrupt service routine
{
unsigned int counter;

counter++;
if(counter == 100) // 10ms x 100 = 1s
{
counter = 0;
1secFlag = 1;
}
}
jhyap
Newbie
Newbie
 
Posts: 6
Joined: Mon Oct 31, 2011 12:16 am

Re: How to perform timer interrupt service routine in PSoC1?

Postby michaz on Mon Oct 31, 2011 7:03 am

the best way I remember for doing things like this is implemented in CYFISNP user module.
The sleep timer (global resource) is used.
In sleep timer ISR, the 2-byte variable is incremented (see _CYFISNP_SLEEP_ISR in lib\CYFISNPINT.asm).
Then you have 2 APIs in CYFISNP_Time.c and use them like:
Code: Select all
...
#define LED_GRN_TOG     (GreenLED_Data_ADDR ^=  GreenLED_MASK)
...
CYFISNP_TimeSet(&ledTimer, LED_BLINK_TIME);
...
while(1){
if (CYFISNP_TimeExpired(&ledTimer)) {
  LED_GRN_TOG;
  CYFISNP_TimeSet(&ledTimer, LED_BLINK_TIME);
}
}

where ledTimer is
Code: Select all
WORD ledTimer;

and LED_BLINK_TIME is
Code: Select all
#define LED_BLINK_TIME  (1000 / CYFISNP_TIMER_UNITS)

Assuming the sleep timer is 64Hz, CYFISNP_TIMER_UNITS is 16.
User avatar
michaz
Cheese Wheel
Cheese Wheel
 
Posts: 82
Joined: Sat Aug 27, 2005 3:19 am
Location: Ukraine

Re: How to perform timer interrupt service routine in PSoC1?

Postby danadak on Mon Oct 31, 2011 7:37 am

Some general thoughts -

1) C interrupts -

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

2) If you write ISR into the API file created by Designer, don't forget to declare any variable
looked at as external { if that variable is in another file, like main() }. The API file is created
if you enable ISR in Timer settings. For example if you place a timer named "Timer16_1" then
Designer generates a file named Timer16_1INT.asm, and inside that file if shows where to place
your ISR code.

3) Generally speaking minimize the work you do inside ISR, generally speaking just set a flag
and process the rest in main(). Reason for doing this is multifold, a lot of stuff gets saved by
compiler if you do calls inside an ISR, and generally in demanding designs too much code inside
ISR can potentially screwup other ISR functions. And you save code space and MIPS wasted.
Also stack overflow problems, difficult to debug.

4) In your specifc case just set the flag inside ISR, then handle counter inside main().

Regards, Dana.
Field Application Engineer
KB1RHB Mostly listen :)
Semi Retired
User avatar
danadak
The Big Cheese
The Big Cheese
 
Posts: 2008
Joined: Thu Dec 27, 2007 8:42 am
Location: New Hampshire

Re: How to perform timer interrupt service routine in PSoC1?

Postby slandrum on Mon Oct 31, 2011 6:14 pm

Unless clocked from an external source, the sleep timer is extremely imprecise. -50% to +100%. For many things that's acceptable. If that's not acceptable, use a user module timer or PWM.
slandrum
The Big Cheese
The Big Cheese
 
Posts: 453
Joined: Fri Feb 29, 2008 11:38 am
Location: California

Re: How to perform timer interrupt service routine in PSoC1?

Postby jhyap on Mon Oct 31, 2011 11:00 pm

michaz: Unfortunately, I did not see any CYFISNP in user module for my PSoC1, CY8C27443-24PXI

Dana: Your information is extremely useful.

Slandrum: Thanks for your information.

I had attached some useful timer information for the configuration of counter\timer in PSoC designer.

I will try it out out again and comeback to you guys soon :D
Attachments
Timers.ppt
configuration of counter\timer in PSoC designer
(606.5 KiB) Downloaded 246 times
jhyap
Newbie
Newbie
 
Posts: 6
Joined: Mon Oct 31, 2011 12:16 am

Re: How to perform timer interrupt service routine in PSoC1?

Postby jhyap on Mon Nov 21, 2011 3:48 am

Hi all,

I had successfully created an ISR to toggle a LED for every 1 second. (I was dragged into other work before I come back to this.)

Configuration for Timer8:
CPU Clock= 24MHz
VC1=16
VC2=15
VC3=VC2
VC3 Divider=100

Configuration for LED:
Port 2; Pin 2_0; Active Low

Source Code:
#include <m8c.h> // part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules

void Timer8_ISR(void);
void LED_On(void);

#pragma interrupt_handler Timer8_ISR

void Timer8_ISR(void)
{
int counter;
counter++;

if(counter == 100)
{
counter = 0;
LED_On();
}
}

void LED_On(void)
{
LED_1_Invert();
}

void main (void)
{
Timer8_WritePeriod(10);
Timer8_WriteCompareValue(0x00);
M8C_EnableGInt;
Timer8_EnableInt();
Timer8_Start();
}

Really thanks for your help and I will have more source to come ^^

Regards,
Newbie to PSoC
jhyap
Newbie
Newbie
 
Posts: 6
Joined: Mon Oct 31, 2011 12:16 am

Re: How to perform timer interrupt service routine in PSoC1?

Postby danadak on Mon Nov 21, 2011 5:46 am

The problem with your approach is processor does nothing until counter expires, and
you are making f() calls inside ISR, generally not a good practice.

Here is one approach -

Code: Select all
#include <m8c.h> // part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules

void Timer8_ISR(void);
void LED_On(void);

#pragma interrupt_handler Timer8_ISR
unsigned char tflag     = 0;
unsigned char counter    = 0;

void Timer8_ISR(void)
{
tflag = 1;
return;
}

int counter;
counter++;

void LED_On(void)
{
         LED_1_Invert();
}

void main (void)
{
      Timer8_WritePeriod(10);
    Timer8_WriteCompareValue(0x00);
    M8C_EnableGInt;
    Timer8_EnableInt();
    Timer8_Start();

                for (;;) {

    if ( tflag) {

       counter++;
       if ( counter == 100 ) {

          LED_On();
          counter = 0;
       }
      tflag = 0;
    }
                }
}


Regards, Dana.
Field Application Engineer
KB1RHB Mostly listen :)
Semi Retired
User avatar
danadak
The Big Cheese
The Big Cheese
 
Posts: 2008
Joined: Thu Dec 27, 2007 8:42 am
Location: New Hampshire

Re: How to perform timer interrupt service routine in PSoC1?

Postby jhyap on Mon Nov 21, 2011 5:48 pm

Dana,

I tried on your approach and it was better :)
jhyap
Newbie
Newbie
 
Posts: 6
Joined: Mon Oct 31, 2011 12:16 am

Re: How to perform timer interrupt service routine in PSoC1?

Postby Sidharth on Tue Apr 17, 2012 2:50 am

SysClk - 24MHz
VC1 - 16
VC2 - 15
VC3 - VC2
VC3 Divider - 100

Timer8_1 settings:
Clock - VC3
Capture - Low
TerminalCountOut - None
CompareOut - None
Period - 100
Compare Value -0
Compare Type - Less than or equal
Interrupt type - Terminal Count
ClockSync - Sync to SysClk
TC_PulseWidth - Full Clock
InterruptAPI - Enable
IntDispatchMode - Active Status
InvertCapture - Normal

Source Code :

//----------------------------------------------------------------------------
// C main line
//----------------------------------------------------------------------------

#include <m8c.h> // part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules

void Timer8_ISR(void);


#pragma interrupt_handler Timer8_ISR
int tflag = 0;
int counter =1;

void Timer8_ISR(void)
{

tflag = 1;
return;
}


void main (void)
{
LCD_1_Start(); /* Init the LCD */
LCD_1_InitBG(LCD_1_SOLID_BG);

Timer8_1_WritePeriod(0xA);
Timer8_1_WriteCompareValue(0x00);
M8C_EnableGInt;
Timer8_1_EnableInt();
Timer8_1_Start();

while(1) {

if (tflag)
{
LCD_1_Position(0,0);
LCD_1_PrCString("count 100");
counter++;
if ( counter == 100 )
{
LCD_1_Position(0,0);
LCD_1_PrCString(" ");
LED_1_Invert();
counter = 0;
}
tflag = 0;
}
}
}
------------------------------------------------------------

I donot know why but this code is not working on PSoCEVAL1 - CY8C29466-24PXI
LED is not blinking and LCD is not showing anything either.
If you could please help me out with this ...
Thankyou :)
Sidharth
Sidharth
Newbie
Newbie
 
Posts: 7
Joined: Sun Apr 15, 2012 4:41 am

Re: How to perform timer interrupt service routine in PSoC1?

Postby danadak on Tue Apr 17, 2012 3:28 am

Some thoughts -

1) Generally easier if you post whole project to be examined.

2) You might want to keep name of ISR consistant with module generating
ISR, so change "Timer8_ISR" to "Timer8_1_ISR". This may or may not make
a difference, but caught my eye.

3) Did you modify boot.tpl with an "ljmp Timer8_1_ISR" ? For the digital
block interrupt Timer8 is placed in.

4) Your code, you init bargraph, but are using LCD as apha numeric display,
eliminate "LCD_1_InitBG(LCD_1_SOLID_BG);" code line.

5) When count == 100 you write a single blank to line 0,0, that would only
erase the first char of the line, did you mean to erase entire line, if so
write a " ...." complete line of blanks to LCD.

6) You do not show the LED_1_Invert() API, or the HW routing, so I cannot tell
what LED functionality is doing.

7) Are you trying to write real time "count" to the LCD ? If so you would do the
following ( note to dress up display of counter you would write a routine to left justify it) -

Code: Select all
//----------------------------------------------------------------------------
// C main line
//----------------------------------------------------------------------------

#include <m8c.h>        // part specific constants and macros
#include "PSoCAPI.h"    // PSoC API definitions for all User Modules
#include <stdlib.h>

 void Timer8_ISR(void);
 void LED_1_Invert( void );
 
 int tflag       = 0;
 int counter    = 1;

 #pragma interrupt_handler Timer8_ISR

 void Timer8_ISR(void)
 {

    tflag = 1;
    return;
 }

 unsigned char prString[21];

 void main (void) {
 
   LCD_1_Start(); /* Init the LCD */
 
   Timer8_1_WritePeriod(0xA);
    Timer8_1_WriteCompareValue(0x00);
    M8C_EnableGInt;
    Timer8_1_EnableInt();
    Timer8_1_Start();

   LCD_1_Position( 0,0 );
   LCD_1_PrCString( "Count" );

   while(1) {
   
      if ( tflag ) {
      
         counter++;
         itoa( prString, counter, 10 );            // Convert count to a char string
         LCD_1_Position( 0,6 );
         LCD_1_PrString( prString );
         
         if ( counter == 100 ) {
         
            LCD_1_Position( 0,0 );
            LCD_1_PrCString( "      " );         // Len of string should be # chars in LCD line
            LED_1_Invert();
            counter = 0;
         }
         
         tflag = 0;
      }
   }
 }



Regards, Dana.
Last edited by danadak on Tue Apr 17, 2012 4:06 am, edited 3 times in total.
Field Application Engineer
KB1RHB Mostly listen :)
Semi Retired
User avatar
danadak
The Big Cheese
The Big Cheese
 
Posts: 2008
Joined: Thu Dec 27, 2007 8:42 am
Location: New Hampshire

Re: How to perform timer interrupt service routine in PSoC1?

Postby Sidharth on Tue Apr 17, 2012 3:57 am

2nd and 4th point done. You are right about the 5th point as well I wanted to clear the LCD screen's 1st row. I haven't done any modification in boot.tpl , please tell me how to do it. I am sending the whole project as an attachement a little modified on from the former one that i posted . I thought if I could solve this easier one then i would be able to solve the former one as well. It would be very king if you could help me. I am novice in working with PSoC.

Thank you,
Sidharth
Attachments
learning_timer_module.rar
(255.68 KiB) Downloaded 156 times
Sidharth
Newbie
Newbie
 
Posts: 7
Joined: Sun Apr 15, 2012 4:41 am

Re: How to perform timer interrupt service routine in PSoC1?

Postby danadak on Tue Apr 17, 2012 4:12 am

I will look at your project.

boot.tpl is in root directory of project, its where you modify
interrupt vector jump table.

Regards, Dana.
Field Application Engineer
KB1RHB Mostly listen :)
Semi Retired
User avatar
danadak
The Big Cheese
The Big Cheese
 
Posts: 2008
Joined: Thu Dec 27, 2007 8:42 am
Location: New Hampshire

Re: How to perform timer interrupt service routine in PSoC1?

Postby Sidharth on Tue Apr 17, 2012 4:30 am

The code you posted is running just fine. Thank you. I will now proceed towards my objective and will ask for your favor if required.

Regards
Sidharth
Sidharth
Newbie
Newbie
 
Posts: 7
Joined: Sun Apr 15, 2012 4:41 am

Re: How to perform timer interrupt service routine in PSoC1?

Postby danadak on Tue Apr 17, 2012 4:40 am

Some thoughts -

1) You had forgot to start LED_1

2) I left out real time display of counter

3) boot.tpl modified, take a look at it, look for "ljmp _Timer8_1_ISR" entry close
to beginning of file.

4) Your clock chain is 6 Mhz / ( VC1 x VC2 x VC3 x Timer8 period) which is ~ 1 count
every 3 seconds, is that what you wanted ?

Regards, Dana.
Attachments
learning_timer_module.zip
(337.13 KiB) Downloaded 152 times
Field Application Engineer
KB1RHB Mostly listen :)
Semi Retired
User avatar
danadak
The Big Cheese
The Big Cheese
 
Posts: 2008
Joined: Thu Dec 27, 2007 8:42 am
Location: New Hampshire

Re: How to perform timer interrupt service routine in PSoC1?

Postby moxbox on Sun Apr 22, 2012 9:57 am

In general, I like to put the ljmp/lcall into the _INT.asm routine and NOT into the boot.tpl.
While putting it into the boot.tpl will work just fine, the next time you do a PSoC Creator update
and it modifies your boot.tpl, you will wonder why your project just stopped working...

for example, using the SleepTimer interrupt, I would do the following :

Code: Select all
SleepTimer_1_SLEEP_ISR_END:

   ;@PSoC_UserCode_BODY_1@ (Do not change this line.)
   ;---------------------------------------------------
   ; Insert your custom assembly code below this banner
   ;---------------------------------------------------
   ;   NOTE: interrupt service routines must preserve
   ;   the values of the A and X CPU registers.
   
   ;---------------------------------------------------
   ; Insert your custom assembly code above this banner
   ;---------------------------------------------------
   
   ;---------------------------------------------------
   ; Insert a lcall to a C function below this banner
   ; and un-comment the lines between these banners
   ;---------------------------------------------------
   
   ;PRESERVE_CPU_CONTEXT
   ;lcall _My_C_Function
   ;RESTORE_CPU_CONTEXT

   ; if not saving/restoring context, use the ljmp...
   ;
   ljmp _SleepTimer_1_ISRV 
   ;---------------------------------------------------
   ; Insert a lcall to a C function above this banner
   ; and un-comment the lines between these banners
   ;---------------------------------------------------
   ;@PSoC_UserCode_END@ (Do not change this line.)

   reti

; end of file SleepTimer_1INT.asm


This insures that you won't be scratching your head in a few months,
wonmdering why nothing works anymore. Been there, done that...

cheers,
mox
If we knew what we were doing, it wouldn't be called research, would it?
-- Albert Einstein
moxbox
Cheese Cube
Cheese Cube
 
Posts: 41
Joined: Thu Oct 15, 2009 9:59 am
Location: Portland, OR

Re: How to perform timer interrupt service routine in PSoC1?

Postby bobmarlowe on Sun Apr 22, 2012 10:04 am

I prefer this way of doing for the interrups as well.
Do not forget to declare your interrupt-routine with
#pragma interrupt_handler SleepTimer_1_ISRV
It has the advantage, that the c-compiler "knows" which registers must be saved on stack as long as you do not call another function().

Happy (uninterrupted) coding
Bob
User avatar
bobmarlowe
The Big Cheese
The Big Cheese
 
Posts: 1490
Joined: Thu Oct 06, 2011 2:03 am
Location: Germany

Re: How to perform timer interrupt service routine in PSoC1?

Postby moxbox on Sun Apr 22, 2012 10:21 am

Good point Bob!

I think that is now the preferred method for handling interrupts, IMHO...

cheers,
moxbox
If we knew what we were doing, it wouldn't be called research, would it?
-- Albert Einstein
moxbox
Cheese Cube
Cheese Cube
 
Posts: 41
Joined: Thu Oct 15, 2009 9:59 am
Location: Portland, OR

Re: How to perform timer interrupt service routine in PSoC1?

Postby danadak on Mon Apr 23, 2012 2:21 am

FYI, if I am not mistaken Designer now asks you if you want to over write
boot.tpl, as part of its module update dialog. But that would require one
remember if he/she modified it in the first place :mrgreen:

Regards, Dana.
Field Application Engineer
KB1RHB Mostly listen :)
Semi Retired
User avatar
danadak
The Big Cheese
The Big Cheese
 
Posts: 2008
Joined: Thu Dec 27, 2007 8:42 am
Location: New Hampshire

Re: How to perform timer interrupt service routine in PSoC1?

Postby bobmarlowe on Mon Apr 23, 2012 2:58 am

Hi Dana,
Boot.tpl is project specific, so when you open my project it should be OK. or am I misunderstand something?
The LJMP to the interrupt-routine is inserted at TimerINT.asm, in Boot.asm it is inserted automatically

Bob

(FYI = Fort Your Information??)
User avatar
bobmarlowe
The Big Cheese
The Big Cheese
 
Posts: 1490
Joined: Thu Oct 06, 2011 2:03 am
Location: Germany

Re: How to perform timer interrupt service routine in PSoC1?

Postby danadak on Mon Apr 23, 2012 3:20 am

boot.asm is created from boot.tpl. But if I am not mistaken boot.tpl from one upgrade
to another, may change, and when you open project for first time under new upgrade
boot.tpl is dialoged for permission to upgrade.

FYI = For Your Information.

http://www.cypress.com/?docID=33577

Regards, Dana.
Field Application Engineer
KB1RHB Mostly listen :)
Semi Retired
User avatar
danadak
The Big Cheese
The Big Cheese
 
Posts: 2008
Joined: Thu Dec 27, 2007 8:42 am
Location: New Hampshire

Next

Return to PSoC1 General

Who is online

Users browsing this forum: Google [Bot] and 1 guest

cron