Reputation: 603
Let's say I have two functions in C, a()
and b()
.
And let's say I have two interrupts corresponding to both functions. The first interrupt should start running function a()
and stop b()
from running if it was interrupted during its run. Similarly, the second interrupt does the same thing for function b()
.
If I am currently running in a()
, and I triggered the interrupt for b()
. How can I start b()
and prevent a()
from completing after the interrupt handler finished?
The Code is as follows:
int main(void)
{
Init();
while (true)
{
if (run_A)
{
a();
run_A = false;
}
if (run_B)
{
b();
run_B = false;
}
}
void Handler(void)
{
IntClear(interruptMask);
if (INTERRUPT_FOR_A)
{
run_A = true;
}
if (INTERRUPT_FOR_B)
{
run_B = true;
}
}
Upvotes: 3
Views: 2329
Reputation: 665
Sounds like you are looking for a feature similar to coroutines. While not directly supported in C, you maybe able to implement a version good enough for your needs. As mentioned above, this will probably involve setjmp/longjmp or the mind-bending "Duff's Device" if you want to do it in portable C.
Upvotes: 0
Reputation: 12668
This is the kind of problem for which the setjmp(3)
/longjmp(3)
functions where designed in old UNIX(tm). You need to call setjmp(3)
before entering the function you want to interrupt and in case the interrupt comes (you must ensure the interrupt is handled in the context of the function you are going to interrupt) then yo make a call to longjmp(3)
and restore the stack at the point of the call.
Upvotes: 0
Reputation: 8614
I have a situation where b() calls a function that does some work that I don't need if I want to switch back to a(). I want to prevent it from happening when I call a(), and minimize the time it takes to start a()
Basically this situation will occur if INTERRUPT_FOR_B
happens and a very short time later INTERRUPT_FOR_A
happens, and if b()
has a longer run time.
You need to carefully think about this situation and find out the chance of happening before doing premature optimizations.
But, if you want to go ahead, you can have some check points in the function b()
to see if run_A
is true.
e.g.
void b(void)
{
// some code.
if (run_A == true) return;
// some code
if (run_A == true) return;
// etc
}
Note that you need to properly analyze and test b
function with all the return paths to ensure that this function runs properly in all cases.
Upvotes: 4
Reputation: 213989
Overall it isn't very meaningful to speak about this in general terms. It depends on your requirements and what kind of hardware that is generating the interrupt.
You can't/shouldn't just stop a function mid-execution. The best way to do this is either to keep the functions small and let the current one finish, or alternatively have the functions poll a flag variable repeatedly.
A more intrusive but simple method would be to simply shut off the undesired interrupt, but that might lead to loss of data. Depending on the nature of the interrupt, this may or may not be fine.
And then there are of course evil ways to set the PC manually with assembler or longjmp, but this is very bad practice and almost certainly the wrong solution to any problem.
Upvotes: 2