CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Fast interrupts

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Mortenc



Joined: 22 Feb 2007
Posts: 55

View user's profile Send private message

Fast interrupts
PostPosted: Thu Feb 26, 2009 5:47 am     Reply with quote

Hello superforum,

I'm polling the RTCC timer to have a fixed program turn around time.
I'm also having 2 interrupt to be handled. CCP1 with high priority and EXT (RB0) with low priority.
Processor is PIC18F4520, Clock is 16 MHz.
Code:
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32|RTCC_8_BIT);
 // Internal osc and timeroverflow for every 2.048mS by 16 MHz

This means that the RTCC is incremented every 8 uSec.

I want to disable the interrupt when the RTCC is close to rollover for not distubing my fix program turn around so my question is:

How fast can I make these interrupts?

(my ISR code is predictable and short , but I can see that the compiler add both some hidden runtime code and a lot of other code lines. I have measured the time of the int_ext interrupt and this take about 11 uS, which then is 44 program cycles. Only the 4 of cycles is my ISR code.)
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Feb 26, 2009 3:04 pm     Reply with quote

Read this explanation:
http://www.ccsinfo.com/forum/viewtopic.php?t=36612&highlight=fast+high
Mortenc



Joined: 22 Feb 2007
Posts: 55

View user's profile Send private message

PostPosted: Thu Feb 26, 2009 3:41 pm     Reply with quote

Thanks, but I all ready have read this and this is good, but I'm an old ASM-programmer and wonder why this interrupt take so long.

Normally in ASM I use to save W, status and pclatch registers (PIC16F873) and I could put in some code just before RETFIE to adjust some register parameter if I want to. In the C-programming I have no control over the last code lines and can't make such adjustments.
In ASM programming I can see how long the interrupt takes by counting the ASM, but in C programming something is hidden for me with the runtime "*" mark.
However I like the C-programming and I don't want to put in ASM lines in the interrupt code to make it faster. (I know it can be dangerous).
I only want to learn to be a good C-programmer so:

Is it right that the shortest interrupt, including saving the important registers like W, STATUS, BSR, will be about 40 cycles?
Guest








PostPosted: Thu Feb 26, 2009 11:11 pm     Reply with quote

Have you looked at the .lst file to see what assembly is being generated? You may find your answers there.
Mortenc



Joined: 22 Feb 2007
Posts: 55

View user's profile Send private message

PostPosted: Fri Feb 27, 2009 1:49 am     Reply with quote

Yes, I have read the lst-file, but something is marked with "*" which is hidden from me and some of the last instructions I don't understand. Some of the last instructions is like this and it seems to be some modifications in the "@ interrupt area"
Code:

0064:  MOVFF  0F,00
0068:  MOVFF  10,01
006C:  MOVFF  11,02
0070:  MOVFF  12,03
0074:  MOVFF  13,04
0078:  BSF    0E.7
007A:  MOVFF  0D,FE9
007E:  MOVFF  08,FEA
0082:  MOVFF  09,FE1
0086:  MOVFF  0A,FE2
008A:  MOVFF  0B,FD9
008E:  MOVFF  0C,FDA
0092:  MOVFF  14,FF3
0096:  MOVFF  15,FF4
009A:  MOVFF  16,FFA
009E:  MOVF   05,W
00A0:  MOVFF  07,FE0
00A4:  MOVFF  06,FD8
00A8:  RETFIE 0

However I can't remove this lines - so I must live with them.
Mortenc



Joined: 22 Feb 2007
Posts: 55

View user's profile Send private message

PostPosted: Fri Feb 27, 2009 2:54 am     Reply with quote

I solve the problem.
In the start of my code I put in:
Code:
#device high_ints=true //  activate high priority for not missing ext1

In my interrupt routines I put in some timer0 control:
Code:
#INT_CCP1 HIGH
void speed_isr()
{
TMR0_temp = get_timer0();
if ((TMR0_temp == 0) || (TMR0_temp == 1) || (TMR0_temp > 253)) set_timer0(253); // dont miss tmr0 overflow
// user code
// user code
// user code
}   
#INT_EXT1
void opt_isr() // EXT1 is the RB1 interrupt
{
TMR0_temp = get_timer0();
if ((TMR0_temp == 0) || (TMR0_temp == 1) || (TMR0_temp > 253)) set_timer0(253); // dont mis tmr0 overflow
// user code
// user code
}   

Now I don't miss the timer0 rollover in the main program and the the main timer of 2.048 mS is only affected a litthe when interrupt is comming when timer0 is 0, 1, 254 and 255. This mean the possiblity of affection is 4/256. Because the main program timing of 2.048 mS is used for long time timers in seconds area it's not critical.
Ttelmah
Guest







PostPosted: Fri Feb 27, 2009 3:10 am     Reply with quote

As some further comments.
If you look at the thread that PCM pointed you to,you will see that using the _FAST_ keyword, rather than the 'HIGH' keyword, will tell the compiler _not_ to add it's handler, and get rid of the extra code. However, just as when using INT_GLOBAL, you will then have to add your own code to do the minimum saving necessary.
To see the extra code, that is missing from your listing, 'remark out', the line 'nolist', near the top of the processor include file. By default, CCS, does not show things like the code for it's own maths routines, and some of the handler stuff for interrupts and timings. Removing this, makes these visible.
Third comment, why are you woried about missing the timer rollover?. It sounds rather as if you are polling this timer in the main code?. Instead, just read it's interrupt flag (and clear it when you have seen it trigger). This is set by the hardware, when the rollover takes place, and will happen, whether or not you are in interrupts at the time. You don't then need to fiddle around with changing the timer value. Remember you can use the interrupt flags themselves, without haviong to have an interrupt handler. Take advantage of the hardware, and let it avoid your problem for you. Smile

Best Wishes
Mortenc



Joined: 22 Feb 2007
Posts: 55

View user's profile Send private message

PostPosted: Fri Feb 27, 2009 5:07 am     Reply with quote

Ohh I like this super forum.

I haven't thought of polling the timer0 overflow bit instead. I have just made this and it work fine. Many thanks to you.
About using FAST interrupt, if I understand this correct:
Using #INT_CCP1 FAST and #INT_EXT1 as normal.
CCP1 will still save W, STATUS and BSR because the RETFIE 1 restore these.
More critical is that the #INT_EXT1 is missed if this come when the #INT_CCP1 is running.
Am I right?
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Mar 01, 2009 4:32 pm     Reply with quote

Quote:
More critical is that the #INT_EXT1 is missed if this come when the #INT_CCP1 is running.
Am I right?
No. Each interrupt has its own interrupt flag and the interrupts will be handled sequential.
Mortenc



Joined: 22 Feb 2007
Posts: 55

View user's profile Send private message

PostPosted: Wed Mar 04, 2009 1:07 am     Reply with quote

I don't think I understand your answer right.

If I use #INT_CCP1 FAST and #INT_EXT1 as normal.

What is lost comparred to using #INT_CCP1 HIGH?
Ttelmah
Guest







PostPosted: Wed Mar 04, 2009 3:20 am     Reply with quote

'Lost', nothing, but _you_ will have to add the code to your 'FAST' function, to save any registers this function uses. Using 'HIGH', the compiler does this for you, but at the cost of bulkier code.

Best Wishes
Mortenc



Joined: 22 Feb 2007
Posts: 55

View user's profile Send private message

PostPosted: Wed Mar 04, 2009 7:41 am     Reply with quote

If I use FAST my code will be:
Code:
#INT_CCP1 FAST
void speed_isr()
{
a_speed = CCP_1;
set_timer1(0);
speed_con_1 = 1;
}   

#INT_EXT1
void pulse_isr()
{
pulse = 1; // pulse is observed
}   

What need to be saved or done?
Ttelmah
Guest







PostPosted: Wed Mar 04, 2009 10:21 am     Reply with quote

You need to look at the listing code generated (the assembler), see what registers are used. Verify if any are used that are not automatically saved, and if so, save them at the start of the interrupt, and restore them at the end.
Look at the global interrupt example, for how to do this.

Best Wishes
Mortenc



Joined: 22 Feb 2007
Posts: 55

View user's profile Send private message

PostPosted: Thu Mar 05, 2009 4:26 am     Reply with quote

Well, I have tried to used the CCP1 FAST and the ASM list file looks like this:
--------------------------------------------------------------
.................... #INT_CCP1 FAST
.................... void speed_isr()
.................... {
.................... a_speed = CCP_1;
*
00AE: MOVFF FBF,7D
00B2: MOVFF FBE,7C
.................... set_timer1(0);
00B6: CLRF FCF
00B8: CLRF FCE
.................... speed_con_1 = 1;
00BA: BSF 25.4
.................... }
00BC: BCF F9E.2
00BE: RETFIE 1
.................... #INT_EXT1
.................... void pulse_isr() //
.................... {
.................... pulse = 1; // pulse is observed
00C0: BSF 21.2
.................... test_timer = 5; //
00C2: MOVLW 05
00C4: MOVWF 61
.................... }
....................
.................... //**********************************************************
.................... //
00C6: BCF FF0.0
00C8: GOTO 0068
---------------------------------------------------------

When someone look at this they should know that all FAST and HIGH priority interupt goes to interrupt vector 0008 and low priority interrupt goes to 0018.
If I take a look on interrupt vector 0008 I can see a GOTO 00AE which is just back to my code so nothing is done. However the "RETFIE 1" is used at the end of the CCP1 lines which is a special processor routine which restores the W, STATUS and BSR.
It's strange to see that that a runtime "*" symbol is shown at the CCP1 interrupt, but nothing is shown at the EXT1 interrupt. So you have to know that this interupt goes to vector 0018 because you can't see this. In this vector we can see that e.g. the W register is saved first.
However this was some explanation I hope someone else could use (and I hope I'm right about this).

Still I'm not 100% sure and I'm afraid to use the CCP1 FAST.
I can see that W, STATUS and BSR is saved and this is the most important registers to save and restore. What other I still don't know.
Is it the register used in the EXT1 routine you mean I must take care of, because the CCP1 FAST will disturb the EXT1 if it comes when the EXT1 is runing?

I have also tried to mark out the "nolist" in the 18F4520.h file as you told. I thought then get the code inline, but nothing seems to happen.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group