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

Forcing subroutine to premature termination.

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







Forcing subroutine to premature termination.
PostPosted: Thu Nov 15, 2007 5:04 am     Reply with quote

Hi all,

am wondering how to force a subroutine to premature termination. Imagine yourself there is an interrupt coming whilst a subroutine is being executed. When this happens I need to cancel further execution of this subroutine immediately (cannot check internally this in the subroutine all the time) and get back to another point of the code. This means I don't want to return to the point at which the subroutine had been paused before the interrupt arrived. I want to clean after it using some "destructor" subroutine and jump to the code that actually called this subroutine at first place.

Am sure this sort of things are viable whilst one plays with Program Counter registers and assembler or so, though do you know an easy way of doing this on PIC16F family?

Kind regards,
Peter.
Ttelmah
Guest







PostPosted: Thu Nov 15, 2007 6:09 am     Reply with quote

Generally, doing this, would be considered a sign of very poor programming....
It may be possible, but is potentially very dangerous.
There are a lot of questions, and things that must be done to make it possible.
First, the 'subroutine', must be declared as separate, so that a call is made to it.
Second, can the interrupt occur outside the subroutine, or only inside?. If the former, can you ensure that interrupts are _disabled_, when the subroutine is called?. Does the routine return any data?.
Third, does the subroutine itself, call any other routines (remember things like arithmetic, time delays etc., will all involve calling 'system' routines)?.
Finally, is the chip a '18' family chip?.
If you cannot ensure that interrupts are disabled when you enter the routine, or that the interrupts only occur in the routine, then it becomes very hard.
On a 16 chip, it may well be impossible.
If this is OK, and the routine returns no data, then what you do, is set a global flag in the routine, before saving the STKPTR register to a global variable, and enabling the interrupts. Then in the interrupt handler, check this flag, which is then saying that the interrupt is occurring inside this routine. If this is set, you load the saved STKPTR value. Clear the flag (here,and also at the end of the subroutine).
There is still a danger, that the invalid entries in the system scratch area, will result in latter data problems.
Doing this, is a little like a person who insists on stopping a car, by driving it into a brick wall, rather than braking gently, and steering round it. Though it is possible, with suitable padding, to do it, unless you control everything (writ in assembler, and know what every routine is doing), you must be prepared for problems to result...

Best Wishes
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Thu Nov 15, 2007 9:54 am     Reply with quote

I would not recommend this but,
When the interrupt routine is called the return address is stored not sure where on a pic but a little research should find it.
The return address for the subroutine is stored on the stack.
So it should be possible to remove any unwanted data that the subroutine is using from the stack by altering the stack pointer, retreive the return address for the subroutine, alter the return address for the interrup routine and the as they say bobs your uncle or in this case up the creak without a paddle Smile

You do however need to know alot of information to be able to do this.
How much stack has been used for your subroutine.
If you want to start execution from a completely different part of the code then you need to clear the stack down to the correct place for this part of the code to return from.

A flag would be better!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Nov 15, 2007 10:06 am     Reply with quote

Tell us about your project, and tell us why you believe you must
structure the program in this way. Tell us your goal.

There may be a better way to do it, that uses conventional programming
techniques.
Peter
Guest







Forcing subroutine to premature termination.
PostPosted: Thu Nov 15, 2007 6:40 pm     Reply with quote

Hi guys.

Am not finding the sought technique as proof of poor programming ;) There are just too many actions to handle at once. Anyhow, here's what this all is about. There is a PIC16Fxxx based device that collects data from a small keypad at any time pressed. There a few of such devices. So interrupt on pin change is used here. In order to debounce and collect possible combination of multiple pressed buttons with delays, execution of the interrupt takes some time (multiple probing, etc.). Devices can be queried at any time as well by an external master module. While keypad interrupt is being executed, querying interrupt is disabled. When device is queried and keep replying in a strictly designed time slot that is short, a key press may occur. Shall this happened, the reply is delayed - such disrupted transmission collides with time slots meant for the remaining devices to reply. Now, this is not a big deal coz retransmission can happen, though I wanted to minimize unnecessary collisions stemming from described above keypad interrupt occurrence. BTW, transmission relies on a software based modulation where there is no time for checking a flag determining whether the keypad interrupt has occurred or not (the real bottleneck). Also, I cannot handle keypad data with a separate chip like flip-flops or so forth coz there is also time measurement involved. Thus, every external component increases price. So, ..., the mechanism of leaving subroutine would be perfect to tackle the issue. In C++ there are exceptions that are meant for tackling similar problems. Here, in CCS C, ..., am not sure how to improve this. If I based the project on assembler, I would go about stack, program counter, etc. I just though that some of you already have some neat ideas for such an exceptional termination. Hope this clarifies well enough.

Cheers,
Peter.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Nov 15, 2007 11:38 pm     Reply with quote

To summarize:

1. You have several Slave PICs (16F876) connected to a Master PIC.

2. Each slave PIC has a keypad connected to it on Port B, and uses
INT_RB interrupts to detect a keypress. The keypad is scanned by
code that runs inside the INT_RB isr.

3. Each slave PIC is connected to the Master by a proprietary serial
interface (not SPI, i2c, or RS232). The slave detects an incoming
transmission from the Master by using the INT_EXT interrupt.
While inside the INT_EXT isr, the slave sends back a response to the
master by using the proprietary serial interface.

4. The Master sends out a command to each slave, one at a time,
at regular intervals. When the slave receives a command, it sends
back a response to the master. The response consists of any
information that it recently got from the keypad being pressed.

---------------

You have two software processes, keypad scanning and serial
communications, both of which are initiated by interrupts. Each
software process is performed entirely inside its respective isr.

The keypad has priority. You don't ever want to lose a keypress.
The serial communications can be aborted in mid-transmission with
no problem. The master will detect that it got an incomplete message
from the slave and throw it away.
Peter
Guest







Forcing subroutine to premature termination.
PostPosted: Fri Nov 16, 2007 3:14 am     Reply with quote

Just to clarify, INT_EXT collects request from the master device, reads requested token ids, checks whether its id is on the list, and then sets up a ready_to_transmit flag if requested. Subsequently, somewhere in the main loop this request is processed. A few of devices send data as a response (bespoke serial protocol) to one request from master device within time slots. When this happen, subroutine that does it modulates data with high carrier frequency that can be generated on the software side only for reasons I won't be elaborating right now. All this is expected to be send as quick as possible. Shall keypad interrupt happen, pause sending subroutine and return after 10 ms, this will revive sending subroutine which will continue transmitting, though violating next time slot meant for another device. This is what I want to avoid somehow. The issue is there is no time for checking flag while modulating signal - again no point talking why - there are reasons for this. Further, as I said this isn't a big issue, but I want to tidy up any transmission problems and think how to jump out of sending subroutine without checking stop_flag while modulating.

Cheers,
Peter.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Nov 16, 2007 3:26 pm     Reply with quote

For the 16F PICs, the consenus is to do it as Libor says here:
http://www.ccsinfo.com/forum/viewtopic.php?t=28057
RIC says the same thing here:
http://forum.microchip.com/tm.aspx?m=103633
Unfortunately, you said you can't do any polling in your modulation
routine. So, I'm not sure what to suggest.
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