Posted by SprinterSB: Sun. May 12, 2019 - 03:19 PM
1
2
3
4
5
Total votes: 0
ISR+longjmp works as expected, in particular SREG and SP are saved in jmpbuf. And longjmp is designed to jump right out of a call tree (including any level of IRQs).
.
You are trying to implement timeout like in Java where an exception is thrown when a timer triggers.
.
The alternative would be to clutter up your funcs' code with tests an returns if the condition is true, which is not very nice either.
.
Advantage of longjmp is that it keeps your funcs clean and in addition is zero overhead until actually performed, and even then it's just around 40 ticks or so.
.
Main disadvantage of longjmp is that you need cleanup of your funcs internal state which you don't know, as you don't know when exactly the IRQ triggers.
.
And longjmp is not very common, hence there might be some bias against it.
avrfreaks does not support Opera. Profile inactive.
setjmp/longjmp are often used in interactive programs to catch the interrupt key-sequence (e.g., Control-c): inside the REPL (read-eval-print-loop) one performs a setjmp(); inside the Control-c signal handler one performs a longjmp(). (By the way, the "modern" version of setjmp/longjmp is setcontext().) This mechanism can also be used to implement co-routines, exception handlers, etc.
So I can see how the OP may have come to the solution in the first post. And as odd as the code looks, I don't see why it would not work here. But this style is not usual for embedded / real-time systems.
I did look at the implementation of setjmp in avr-libc (see attached). The implementations is quite simple. It saves the stack pointer and status register. longjmp () restores the stack pointer and jmps to the setjmp() address. It looks like any other registers will get trashed.
Looking at the original post -- not having read all the follow-ups -- it seems the OP wants to do a specific computation based on the value of critical_value and abort that computation when critical_value changes. He has the choice of polling for critical value in the loop or using setjmp/longjmp.
The avr-libc routines also save/restore the call-saved registers, cf. the .irp code. setjmp behaves like a function, i.e. clobbers the call-used regs so that any local whose lifetime crosses setjmp will survive.
avrfreaks does not support Opera. Profile inactive.
The avr-libc routines also save/restore the call-saved registers, cf. the .irp code. setjmp behaves like a function, i.e. clobbers the call-used regs so that any local whose lifetime crosses setjmp will survive.
ISR+longjmp works as expected, in particular SREG and SP are saved in jmpbuf. And longjmp is designed to jump right out of a call tree (including any level of IRQs).
It might be true for the given platform, no argument here. For another example, on x86 the `setjmp/longjmp` mechanism is sometimes successfully used to implement coroutines, i.e. to pass control between two different branches of call tree (basically, it is a side-jump, not a backwards jump). If done properly, it "works", even though it is not formally legal.
However, in general, as far as C standard library specification is concerned, it is illegal to `longjmp` out of signal handlers (or interrupt handlers). The behavior is undefined. There are several underlying reasonings behind this restriction, including (but not limited to) 1. the fact that the call tree for the handler might include several platform-dependent routines that cannot be safely jumped over, 2. `longjmp` is not an "async safe" function.
You don't know where your code was when your interrupt fired. If you leave the ISR via longjmp, you are not going back where you were before it was called. You're going to where setjmp was called.
Your problem isn't some subtlety of restoring things, it's that your idea makes no sense whatsoever. The idea of an interrupt is that your code is currently doing something, and then the interrupt happens, and when it's done, it resumes what it was doing previously. If you try to use a goto, or a longjmp, you are no longer resuming what you were doing previously.
Circumstances under which this would be reasonable: Nothing your program does matters to you, at all, and you don't care whether any of the code you wrote runs.
If it is possible that you care whether your program runs, then this is an idea which is completely, totally, wrong in every way.
I guess the real solution here is to break up the long (50ms) work in main() to smaller steps that are also then conditional on some kind of "abandon because of interrupt" flag that is then set in the ISR.
(I often make this point but shouldn't all this have been captured in the design stages before implementation?)
If you leave the ISR via longjmp, you are not going back where you were before it was called. You're going to where setjmp was called.
It can get more complicated when you have preemptible tasks. The OS gets control after interrupts. It runs the highest priority task that is ready to run.
However, in general, as far as C standard library specification is concerned, it is illegal to `longjmp` out of signal handlers (or interrupt handlers). The behavior is undefined. There are several underlying reasonings behind this restriction, including (but not limited to) 1. the fact that the call tree for the handler might include several platform-dependent routines that cannot be safely jumped over, 2. `longjmp` is not an "async safe" function.
Are you sure about this? I thought the issue was repeated signal handlers. That is, if longjmp is used in signal handlers then signals must be blocked in the handlers. Extending to interrupt handlers, interrupts must be disabled.
However, in general, as far as C standard library specification is concerned, it is illegal to `longjmp` out of signal handlers (or interrupt handlers). The behavior is undefined. There are several underlying reasonings behind this restriction, including (but not limited to) 1. the fact that the call tree for the handler might include several platform-dependent routines that cannot be safely jumped over, 2. `longjmp` is not an "async safe" function.
Are you sure about this? I thought the issue was repeated signal handlers. That is, if longjmp is used in signal handlers then signals must be blocked in the handlers. Extending to interrupt handlers, interrupts must be disabled.
What you are saying is similar to what the original C standard (C89/90) was saying (and might also rely on additional guarantees made by POSIX at that time)
"As it bypasses the usual function call and return mechanisms, the longjmp function shall execute correctly in contexts of interrupts, signals and any of their associated functions. However, if the longjmp function is invoked from a nested signal handler (that is, from a function invoked as a result of a signal raised during the handling of another signal), the behavior is undefined."
"The C Standard is clear enough as is. The longjmp function shall execute correctly when called from a non-nested signal handler invoked through calls to the raise or abort functions; if longjmp is called from a signal handler invoked by other means, or from a nested signal handler, the behavior is undefined."
(and the original wording was quietly removed from C standard).
So, according to this clarification from the very beginning using `longjmp` has only been allowed in signal handlers that were invoked manually, through `raise` or `abort` functions, not by "real" signals.
The current C standard covers this issue with a more generic rule
"7.14.1.1 The signal function
5 If the signal occurs other than as the result of calling the abort or raise function, the behavior is undefined if the signal handler refers to any object with static or thread storage duration that is not a lock-free atomic object other than by assigning a value to an object declared as volatile sig_atomic_t, or the signal handler calls any function in the standard library other than the abort function, the _Exit function, the quick_exit function, or the signal function with the first argument equal to the signal number corresponding to the signal that caused the invocation of the handler."
As you can see, calling `longjmp` from asynchronous signal handlers remains illegal. Naturally, all this also applies to interrupt handlers invoked by actual interrupts.
Even if it works, calling longjmp is probably a bad idea. Not because it won't work correctly, but because it makes it harder for the maintenance programmer to understand.
In general, ISRs should just set state and return. Now, sometimes setting that state is a complicated business and makes the ISR take a bit longer than we'd hope, but it will still return to the main program.
If the main program can't handle things quickly enough (before another ISR arrives), then you can put more processing in the ISR- do the calculations etc, in there, and store the results in volatile variables, + ready flags etc. Be careful not to create race conditions, but the main code can always disable interrupts while it reads the volatile variables (copy them into locals, then re-enable).
For example, if reading serial data, you might create a buffer in ram and have the ISR just stash the byte (attiny1 USART does not have a hardware buffer of more than one byte) and move the counter on, the main program can then stay busy doing whatever it's doing until it's ready to read the serial data.
There might also be cases where calling longjmp from a ISR leaves the hardware in an unexpected state- but knowing that a ISR might do that, you can always disable interrupts while doing some hardware operations.
I found some of the RTOS code we used in 1996. I think this is how some of it worked. The maximum stack size for each task had to be specified. At startup, space was reserved on the stack for each task. Setjmp and longjmp were used to run each task in its own environment. Our code ran on a TI DSP. We could also run it on a PC for testing.
It was based on an RTOS developed by TI. If you google for TI-RTOS you will get some hits.
BTW my recollection is that the way to handle register-trashing
by longjmp is to call setjmp from a function that does nothing else
but return the value.
That wouldn't work because setjmp saves its calling environment, which includes the stack frame. If the function that calls setjmp returns, the calling environment is no longer valid. (The old vfork system call had the same constraint for similar reasons.)
That wouldn't work because setjmp saves its calling environment, which includes the stack frame. If the function that calls setjmp returns, the calling environment is no longer valid.
But the setjmp caller can call longjmp instead of return.
Here is the Scheduler we used.
/*f*****************************************************************************
*
* void Scheduler(Process_s *NextProcess)
* DESCRIPTION: Scheduler() uses ANSI setjmp macro to preserve process context.
* If NextProcess argument is NULL, it searches for the next higher
* priority ready-to-run process and switch to it Or simply returns
* to NullProcess if no ready-to-run process is found. If not NULL,
* it simply take the NextProcess agrument and switch to such
* process. Scheduler() uses ANSI longjmp macro to restore context
* and switch to scheduled process.
* RETURNS: void.
* ASSUMES: NextProcess must be a valid process or NULL.
* Interrupts are disabled. They will be enabled in Longjmp when returning
* to the next ready task.
* HISTORY: Created 03/28/96 by David Leung
* 03/28/96 DKL: Initial Start Coding.
*****************************************************************************f*/
This brings back memories. The scheduler searches the processes from highest to lowest priority. Notice the "if(process_p->awaitingResource_p" stuff. I added that code to eliminate priority inversion. If a process is waiting for a resource, the scheduler now runs the process that has the resource locked.
I never heard of "priority inversion" but I knew the original code didn't make sense. When I told the guy who downloaded this RTOS from Dr. Dobbs journal of what I did, he knew the term "priority inversion". He said that is what caused several spacecraft to be lost that NASA tried to send to mars. NASA should have hired me. Maybe NASA gets their code from Dr. Dobbs journal too.
Here are RTMK.c and RTMK.h. I also zipped up a lot of stuff that has headers that RTMK uses. 7zip creates a file that is one third the size of Microsoft's zip, but this forum won't allow the filename extension .7z. (500k vs. 1500k) If anyone wants it, should I add a .txt to the .7z extension or upload the .zip file or put it on OneDrive?
Because VxWorks contains a C language interpreter intended to allow developers to type in C expressions and functions to be executed during system debugging, it was possible to upload a short C program to the spacecraft, which when interpreted, changed the values of these variables [enable priority inheritance for 3 mutexes] from FALSE to TRUE.
So what you (the OP) have, in effect is a process/task/thread that is running, and when an interrupt occurs, you want to abort that process and then restart it.
If I had to do this, I would implement it AS SUCH (in assembly language), saving the full context needed for the process involved, and restoring that context to restart the process. This is "known science", used by various RTOS code. - no need to re-invent the wheel. I would suspect that longjump() might miss some of the needed context, since it (probably?) operates at the "C" context level. For example I wouldn't count on it restoring the "known zero" in R1, which will get trashed during a multi-byte multiply operation.
(On some architectures, it may be that longjump() does restore all necessary context to do this. But from the quoted parts of the C specifications, it certainly seems that you can't count on it.)
(I'm not sure why people are so inclined to try to twist a HLL into doing work that a few relatively obvious lines of assembly language would accomplish.)
I would suspect that longjump() might miss some of the needed context, since it (probably?) operates at the "C" context level. For example I wouldn't count on it restoring the "known zero" in R1, which will get trashed during a multi-byte multiply operation.
Easy enough to test. Just compile this and see what the .LST file looks like.
jmp_buf cpu_state;
void foo(void)
{
longjmp(cpu_state,1);
}
void main(void)
{
volatile int i;
int j = 0;
while (1)
{
if (setjmp(cpu_state) == 0)
{
foo();
} else {
//jump here from foo()
i=j;
}
}
}
#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."
Restoring R1 is not needed because it can only be non-zero during a multi-instruction pattern. You cannot call longjmp (or setjmp for that matter) from within a multi-instruction pattern.
.
If you ever have R1 non-zero between multi-instruction patterns then your program ([inline] asm) is trash.
.
The only thing that does not work as expected are global registers: they are restored but should rather behave like static storage, i.e. retain their values across longjmp.
.
Restoring RAMPx is not needed because GCC assumes they are all 0 and ISR prologue inits them with 0 (except in the case when there is RAMPZ and no RAMPD, content of RAMPZ is of no concern then). (There are some GCC issues with RAMPx handling though, but that's not anything longjmp is to be blamed for.)
.
EIND is also not restored, but that's no issue because GCC assumes that EIND never changes during program execution anyway.
avrfreaks does not support Opera. Profile inactive.
The use of longjmp etc. is timeless. 20 years ago I used an RTOS with preemptive tasks that used it. I'm still wondering if it might be a good idea.
More difficult to explain is people posting C code when C was rendered obsolete when the C++ compiler was made available. I continued using C back in 1985 although my OS9 OS came with a C++ compiler.
ISR+longjmp works as expected, in particular SREG and SP are saved in jmpbuf. And longjmp is designed to jump right out of a call tree (including any level of IRQs).
.
You are trying to implement timeout like in Java where an exception is thrown when a timer triggers.
.
The alternative would be to clutter up your funcs' code with tests an returns if the condition is true, which is not very nice either.
.
Advantage of longjmp is that it keeps your funcs clean and in addition is zero overhead until actually performed, and even then it's just around 40 ticks or so.
.
Main disadvantage of longjmp is that you need cleanup of your funcs internal state which you don't know, as you don't know when exactly the IRQ triggers.
.
And longjmp is not very common, hence there might be some bias against it.
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
Topsetjmp/longjmp are often used in interactive programs to catch the interrupt key-sequence (e.g., Control-c): inside the REPL (read-eval-print-loop) one performs a setjmp(); inside the Control-c signal handler one performs a longjmp(). (By the way, the "modern" version of setjmp/longjmp is setcontext().) This mechanism can also be used to implement co-routines, exception handlers, etc.
So I can see how the OP may have come to the solution in the first post. And as odd as the code looks, I don't see why it would not work here. But this style is not usual for embedded / real-time systems.
I did look at the implementation of setjmp in avr-libc (see attached). The implementations is quite simple. It saves the stack pointer and status register. longjmp () restores the stack pointer and jmps to the setjmp() address. It looks like any other registers will get trashed.
Looking at the original post -- not having read all the follow-ups -- it seems the OP wants to do a specific computation based on the value of critical_value and abort that computation when critical_value changes. He has the choice of polling for critical value in the loop or using setjmp/longjmp.
Attachment(s):
- Log in or register to post comments
TopThe avr-libc routines also save/restore the call-saved registers, cf. the .irp code. setjmp behaves like a function, i.e. clobbers the call-used regs so that any local whose lifetime crosses setjmp will survive.
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
Top20 years ago I used an OS with preemptable tasks that used setjmp and longjmp to save and restore contexts.
- Log in or register to post comments
TopThanks. I missed that.
- Log in or register to post comments
TopIt might be true for the given platform, no argument here. For another example, on x86 the `setjmp/longjmp` mechanism is sometimes successfully used to implement coroutines, i.e. to pass control between two different branches of call tree (basically, it is a side-jump, not a backwards jump). If done properly, it "works", even though it is not formally legal.
However, in general, as far as C standard library specification is concerned, it is illegal to `longjmp` out of signal handlers (or interrupt handlers). The behavior is undefined. There are several underlying reasonings behind this restriction, including (but not limited to) 1. the fact that the call tree for the handler might include several platform-dependent routines that cannot be safely jumped over, 2. `longjmp` is not an "async safe" function.
Dessine-moi un mouton
- Log in or register to post comments
TopNo.
Stop.
You don't know where your code was when your interrupt fired. If you leave the ISR via longjmp, you are not going back where you were before it was called. You're going to where setjmp was called.
Your problem isn't some subtlety of restoring things, it's that your idea makes no sense whatsoever. The idea of an interrupt is that your code is currently doing something, and then the interrupt happens, and when it's done, it resumes what it was doing previously. If you try to use a goto, or a longjmp, you are no longer resuming what you were doing previously.
Circumstances under which this would be reasonable: Nothing your program does matters to you, at all, and you don't care whether any of the code you wrote runs.
If it is possible that you care whether your program runs, then this is an idea which is completely, totally, wrong in every way.
- Log in or register to post comments
TopI guess the real solution here is to break up the long (50ms) work in main() to smaller steps that are also then conditional on some kind of "abandon because of interrupt" flag that is then set in the ISR.
(I often make this point but shouldn't all this have been captured in the design stages before implementation?)
- Log in or register to post comments
TopIt can get more complicated when you have preemptible tasks. The OS gets control after interrupts. It runs the highest priority task that is ready to run.
- Log in or register to post comments
TopAre you sure about this? I thought the issue was repeated signal handlers. That is, if longjmp is used in signal handlers then signals must be blocked in the handlers. Extending to interrupt handlers, interrupts must be disabled.
- Log in or register to post comments
TopSee the WG14 response to this matter: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1318.htm
What you are saying is similar to what the original C standard (C89/90) was saying (and might also rely on additional guarantees made by POSIX at that time)
"As it bypasses the usual function call and return mechanisms, the longjmp function shall execute correctly in contexts of interrupts, signals and any of their associated functions. However, if the longjmp function is invoked from a nested signal handler (that is, from a function invoked as a result of a signal raised during the handling of another signal), the behavior is undefined."
However, even this spec was challenged by Defect Report 152: http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_152.html
To which WG14 responded with
"The C Standard is clear enough as is. The longjmp function shall execute correctly when called from a non-nested signal handler invoked through calls to the raise or abort functions; if longjmp is called from a signal handler invoked by other means, or from a nested signal handler, the behavior is undefined."
(and the original wording was quietly removed from C standard).
So, according to this clarification from the very beginning using `longjmp` has only been allowed in signal handlers that were invoked manually, through `raise` or `abort` functions, not by "real" signals.
The current C standard covers this issue with a more generic rule
"7.14.1.1 The signal function
5 If the signal occurs other than as the result of calling the abort or raise function, the behavior is undefined if the signal handler refers to any object with static or thread storage duration that is not a lock-free atomic object other than by assigning a value to an object declared as volatile sig_atomic_t, or the signal handler calls any function in the standard library other than the abort function, the _Exit function, the quick_exit function, or the signal function with the first argument equal to the signal number corresponding to the signal that caused the invocation of the handler."
As you can see, calling `longjmp` from asynchronous signal handlers remains illegal. Naturally, all this also applies to interrupt handlers invoked by actual interrupts.
Dessine-moi un mouton
- Log in or register to post comments
Tophttps://sourceforge.net/p/qpc/qpn/ci/master/tree/ports/avr/qk/gnu/qfn_port.h#l54
QP-nano: QK-nano
Key Concepts - Real-Time Embedded Frameworks (RTEFs)
via QP-nano: About QP-nano™
"Dare to be naïve." - Buckminster Fuller
- Log in or register to post comments
TopWith AVRs and avr-gcc, I'd be surprised if longjump did not work almost as expected.
The lack of a RETI could be a problem, but since SREG gets restored, all should be ok.
We are not in the realm of C-standard signal-handlers.
We are closer to the realm of PINB |= 4 .
In any case, avr-gcc's ISRs are not C-standard things.
That said, ISR+longjump is not a documented avr-gcc thing either.
If ISR+longjump works for you,
my suggestion is to get the source for it.
Use said source instead of the library version.
That way you might not be affected by updates.
BTW my recollection
is that the way to handle register-trashingby longjmp is to call setjmp from a function that does nothing elsebut return the valuewas wrong.Edit: corrected BTW ....
Iluvatar is the better part of Valar.
- Log in or register to post comments
TopAndreyT, Many thanks for the detailed explanation!
- Log in or register to post comments
TopJust going to chime in and say...
Even if it works, calling longjmp is probably a bad idea. Not because it won't work correctly, but because it makes it harder for the maintenance programmer to understand.
In general, ISRs should just set state and return. Now, sometimes setting that state is a complicated business and makes the ISR take a bit longer than we'd hope, but it will still return to the main program.
If the main program can't handle things quickly enough (before another ISR arrives), then you can put more processing in the ISR- do the calculations etc, in there, and store the results in volatile variables, + ready flags etc. Be careful not to create race conditions, but the main code can always disable interrupts while it reads the volatile variables (copy them into locals, then re-enable).
For example, if reading serial data, you might create a buffer in ram and have the ISR just stash the byte (attiny1 USART does not have a hardware buffer of more than one byte) and move the counter on, the main program can then stay busy doing whatever it's doing until it's ready to read the serial data.
There might also be cases where calling longjmp from a ISR leaves the hardware in an unexpected state- but knowing that a ISR might do that, you can always disable interrupts while doing some hardware operations.
- Log in or register to post comments
TopI found some of the RTOS code we used in 1996. I think this is how some of it worked. The maximum stack size for each task had to be specified. At startup, space was reserved on the stack for each task. Setjmp and longjmp were used to run each task in its own environment. Our code ran on a TI DSP. We could also run it on a PC for testing.
It was based on an RTOS developed by TI. If you google for TI-RTOS you will get some hits.
- Log in or register to post comments
TopTI-RTOS is one of the RTOS for an event processing framework.
QP/C: TI-RTOS Kernel (SYS/BIOS)
"Dare to be naïve." - Buckminster Fuller
- Log in or register to post comments
TopThat wouldn't work because setjmp saves its calling environment, which includes the stack frame. If the function that calls setjmp returns, the calling environment is no longer valid. (The old vfork system call had the same constraint for similar reasons.)
- Log in or register to post comments
TopHere is the Scheduler we used.
This brings back memories. The scheduler searches the processes from highest to lowest priority. Notice the "if(process_p->awaitingResource_p" stuff. I added that code to eliminate priority inversion. If a process is waiting for a resource, the scheduler now runs the process that has the resource locked.
I never heard of "priority inversion" but I knew the original code didn't make sense. When I told the guy who downloaded this RTOS from Dr. Dobbs journal of what I did, he knew the term "priority inversion". He said that is what caused several spacecraft to be lost that NASA tried to send to mars. NASA should have hired me. Maybe NASA gets their code from Dr. Dobbs journal too.
Here are RTMK.c and RTMK.h. I also zipped up a lot of stuff that has headers that RTMK uses. 7zip creates a file that is one third the size of Microsoft's zip, but this forum won't allow the filename extension .7z. (500k vs. 1500k) If anyone wants it, should I add a .txt to the .7z extension or upload the .zip file or put it on OneDrive?
Attachment(s):
- Log in or register to post comments
TopWhat really happened to the software on the Mars Pathfinder spacecraft? | Rapita Systems
fyi
More than VxWorks have a C or C++ interpreter :
though the OOTB RTOS is QNX or likely the configurable real-time part of a somewhat recent Linux kernel :
"Dare to be naïve." - Buckminster Fuller
- Log in or register to post comments
TopSo what you (the OP) have, in effect is a process/task/thread that is running, and when an interrupt occurs, you want to abort that process and then restart it.
If I had to do this, I would implement it AS SUCH (in assembly language), saving the full context needed for the process involved, and restoring that context to restart the process. This is "known science", used by various RTOS code. - no need to re-invent the wheel. I would suspect that longjump() might miss some of the needed context, since it (probably?) operates at the "C" context level. For example I wouldn't count on it restoring the "known zero" in R1, which will get trashed during a multi-byte multiply operation.
(On some architectures, it may be that longjump() does restore all necessary context to do this. But from the quoted parts of the C specifications, it certainly seems that you can't count on it.)
(I'm not sure why people are so inclined to try to twist a HLL into doing work that a few relatively obvious lines of assembly language would accomplish.)
- Log in or register to post comments
TopEasy enough to test. Just compile this and see what the .LST file looks like.
#1 Hardware Problem? https://www.avrfreaks.net/forum/...
#2 Hardware Problem? Read AVR042.
#3 All grounds are not created equal
#4 Have you proved your chip is running at xxMHz?
#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."
- Log in or register to post comments
TopRestoring R1 is not needed because it can only be non-zero during a multi-instruction pattern. You cannot call longjmp (or setjmp for that matter) from within a multi-instruction pattern.
.
If you ever have R1 non-zero between multi-instruction patterns then your program ([inline] asm) is trash.
.
The only thing that does not work as expected are global registers: they are restored but should rather behave like static storage, i.e. retain their values across longjmp.
.
Restoring RAMPx is not needed because GCC assumes they are all 0 and ISR prologue inits them with 0 (except in the case when there is RAMPZ and no RAMPD, content of RAMPZ is of no concern then). (There are some GCC issues with RAMPx handling though, but that's not anything longjmp is to be blamed for.)
.
EIND is also not restored, but that's no issue because GCC assumes that EIND never changes during program execution anyway.
avrfreaks does not support Opera. Profile inactive.
- Log in or register to post comments
TopFascinating discussion, but did no one notice that this is a seven-year necromancy started by @renkitch 25 posts ago?
"Experience is what enables you to recognise a mistake the second time you make it."
"Good judgement comes from experience. Experience comes from bad judgement."
"Wisdom is always wont to arrive late, and to be a little approximate on first possession."
"When you hear hoofbeats, think horses, not unicorns."
"Fast. Cheap. Good. Pick two."
"We see a lot of arses on handlebars around here." - [J Ekdahl]
- Log in or register to post comments
TopI did but folks seemed to be having so much fun ;-)
- Log in or register to post comments
TopThe use of longjmp etc. is timeless. 20 years ago I used an RTOS with preemptive tasks that used it. I'm still wondering if it might be a good idea.
More difficult to explain is people posting C code when C was rendered obsolete when the C++ compiler was made available. I continued using C back in 1985 although my OS9 OS came with a C++ compiler.
- Log in or register to post comments
TopPages