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

Evoking interupt's subroutine.

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







Evoking interupt's subroutine.
PostPosted: Mon Oct 15, 2007 7:12 pm     Reply with quote

Hi all.

Let's say I'm having the following code:

#int_rtcc
void rtccSub(void)
{
... do sth
}

Now let's say that I fancy calling this subroutine or whatever else that is currently set up as an int_rtcc interrupt from another code. How to do this? I don't want to call rtccSub() but would prefer to refer to the pointer from the interrupt vector table, store context, call the code, restore context and return safely. Any simple way of doing this in CCS that you can think of?

Cheers,
Peter.
Ttelmah
Guest







PostPosted: Tue Oct 16, 2007 2:57 am     Reply with quote

Normally, you don't.
Given that interrupt routines should be as short as possible, and built to handle the hardware 'event' that triggered the interrupt, it is not normally a good idea to do this. However, there is a 'trick' way to do this, which is simply to set the interrupt bit yourself.
So:
Code:

#byte INTCON=0xFF2  //This for a '18' chip
#bit TMR0IF=INTCON.2

TMR0IF=TRUE;  //Will cause the interrupt to trigger if it is enabled


Best Wishes
ckielstra



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

View user's profile Send private message

PostPosted: Tue Oct 16, 2007 3:07 am     Reply with quote

What you want to do is kind of unusual, especially your requirement to include all interrupt overhead of saving and restoring the context seems like a waste of processing power.
Depending on your chip and interrupt you could try to manually set the Peripheral Interrupt Request (PIR) flag. Many interrupt require a manual clear of the PIR flag, allowing you to write to this register. There is a good chance you can generate an interrupt by setting the PIR flag from software.

Not tested, but you might try this:
Code:
#byte PIR1 =  0xF9E  // this is for a PIC18, change to 0x0C for a PIC16
#bit CCP1IF = PIR1.2

void main()
{
  enable_interrupts(INT_CCP1);
  enable_interrupts(GLOBAL);

  // Manually fire interrupt
  CCP1IF = 1;
 
  while(1);
}
Peter
Guest







Evoking interupt's subroutine.
PostPosted: Tue Oct 16, 2007 5:28 am     Reply with quote

Hi.

Setting up an interrupt flag is what I normally do at the moment. The vice is that the int_rtcc interrupt could arrive when I'm setting the flag and therefore I couldn't distinguish amongst them. One of them wouldn't be processed/counted.

Cheers,
Peter.
ckielstra



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

View user's profile Send private message

PostPosted: Tue Oct 16, 2007 5:56 am     Reply with quote

In order to avoid me explaining things you already know apparently, it really helps if you give a bit more background information.
Why do you want to call the subroutine in this difficult way?
Is the context saving important?
What is the purpose of your application?
etc.

The better the info you provide, the better resonses you will get.
Ken Johnson



Joined: 23 Mar 2006
Posts: 197
Location: Lewisburg, WV

View user's profile Send private message

PostPosted: Tue Oct 16, 2007 6:28 am     Reply with quote

Not sure what you're trying to accomplish, but would this do it:

[code]
void yourfunc (void)
{
whatever;
}

#int_rtcc
void yourisr (void)
{
yourfunc ();
}

void othercode (void)
{
yourfunc ();
}
[code]

Does this meet your objective ?

Oh, and the compiler will disable interrupts to avoid re-entrancy.

Tell us more . . .

Ken
[/code]
Peter
Guest







Evoking interupt's subroutine.
PostPosted: Tue Oct 16, 2007 6:32 am     Reply with quote

Sure, will elaborate a bit on the problem itself. THough, this is going to be a bit chaotic. Sorry in advance Smile

There is a timer running at 16bit (single tick every 0.5us, overflow 32ms). The above parameters are vital and must run at this speed/resolution. Also, no additional timers are available. Though, I have extra 8bit variable that increments on the int_rtcc interrupt. Occasionally, I call a subroutine A that runs up to 300ms but cannot be sliced by interrupts too much (very time-sensitive transmission). Then, I'm just queuing occurrences of overflows in the one part of implementation of the interrupt, and process the remaining part of the service n times when A finished. I cannot process remaining part of the service from the level of main subroutine b/c another things already are done like this and it would take too much time to return from different subroutines to process this service there. The bottom line is that I could call interrupt subroutine immediately after subroutine A. Then code may either generate interrupt so to achieve this (by flag and loose track if another arrives at the same time - very unlikely but could happen) or call this as a method (additional memory is then taken). I battle for the memory though! So, the bottom line is again to go for interrupt flag triggering, but cope with situation when actually timer sets up this flag exactly at the same time as me. Hope this draws the general conception.

Let's give the following skeleton of the code:

#int_rtcc
void intRtcc(void)
{
intRtccCtr++;

if (intRtccProcAllowed)
while (intRtccCtr)
{
intRtccCtr--;
intRtccMSBTime++;

... do another overflow sensitive operations here,
they take a few of time to execute
}
}

void subrA()
{
intRtccProcAllowed=false;
modulate, send data, etc // cannot be disrupted too much by interrupts
intRtccProcAllowed=true;

intRtccCtr--; intRtccFlag=1; // or intRtccCtr--; intRtcc(); // need disabling interrupt or so

}

main()
{
while(1)
{
do sth that at some point will call subroutine A, but this subroutine doesn't return directly here, but another subroutine ...
}
}
ckielstra



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

View user's profile Send private message

PostPosted: Tue Oct 16, 2007 7:06 am     Reply with quote

Let me guess, you are using a PIC16? With a PIC18 you could do something with the two different interrupt priorities.

How much time and money can you afford to spend on a processor that has memory limitations before it becomes cheaper to upgrade the exisiting hardware to a (pin compatible) processor with more memory?

I don't have the time right now to think of an inventive solution. Maybe later.
Peter
Guest







Evoking interupt's subroutine.
PostPosted: Tue Oct 16, 2007 7:12 am     Reply with quote

Yep, haven't told although should have done it. This is PIC16F688 and actually it is already too expensive for the solution .... And, time of development doesn't matter this much, price of chips does in this case.

Cheers,
Peter.
Peter
Guest







Evoking interupt's subroutine.
PostPosted: Tue Oct 16, 2007 8:12 am     Reply with quote

Hi all,

Ok, I've figured out where I lose the program memory.

Let's consider the following:

void intRtcc(void);

void subA(void)
{
intRtcc();
}

#int_rtcc
void intRtcc(void)
{
...
}

Compiler takes suddenly nearly 10% of the program memory just because of "void intRtcc(void);" pre-definition. How to deal with this? I cannot have subA occurring underneaf intRtcc in the code due to some other dependences.

Cheers,
P.
Ttelmah
Guest







PostPosted: Tue Oct 16, 2007 8:41 am     Reply with quote

There are several problems here. The first is that the predefinition, must _match_ the real definition (you need to add the #int declaration to this as well). The second is that what you do here, will _not_ result in the interrupt routine being called with all the registers saved (which was part of your original spec). Instead the routine itself will just be called as a normal subroutine - the register saving, is part of the 'int_global' declarations, _not_ part of the individual interrupt routine. Doing this, will also now result in the interrupts being disabled in the routine calling the interrupt sub.
What you appear to want to do, can be done tidily, without problems, by testing the value in the timer1 counter, before triggering the 'extra' interrupt. If the value is above a critical number, then just loop, and wait till it is below this number. The number allowable, will depend on the counting rate of the timer, and how long your routine takes to operate.

Best Wishes
Peter
Guest







Evoking interupt's subroutine.
PostPosted: Tue Oct 16, 2007 9:00 am     Reply with quote

Hi. You've just caught what I wanted precisely. Re-defining pre-declaration in exact manner doesn't change this fuss about the program memory unluckily.

Also, I'm happy calling this "extra" interrupt as a normal subroutine. Then I can allow myself to disable this interrupt for a while. The int_rtcc flag will arrive anyway if overflow happens so it would catch up on time with processing it when enabling int_rtcc again.

The reason why I asked for context, etc. was that I thought there is an easy way to call the method serving as the interrupt by its address in the memory. Then one has to save context to return safely to the block of code that called another subroutine (that's the usual case with uC, here might be different).

I had the idea with checking the time so to decide whether to generate this spare interrupt flag or not. This is the best idea so far, though I wanted having these subroutines portable - this means - as you say - additional variables holding preconditions when to generate/avoid this and comparing with get_rtcc(). Also, this needs to be set up differently in different projects. But as I say that's the best approach that I'm aware so far.
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