goto across functions/isrs?

The OP wanted something like a goto, which can be implemented by longjmp(), at the cost of some memory space for the saved state.

Setting a flag, and testing that in the main loop is also possible, but if the use_device() function is complicated, it may be necessary to test it at multiple places, which may cause a bigger overhead, both in time and space, and may clutter up the code.

For cases which are considered to be exceptional, like a surprise device removal, using the signal/longjmp() method works well. With some extra code, it's even possible to pass some arguments to the signal() function, so it can react to specific types of events.

Reply to
Arlet
Loading thread data ...

This sounds very dodgy. You're jumping out of an ISR without doing a proper return from the interrupt. A definite case for the Ministry of Dodgy Coding Practices and their Stack Abuses Police ;)

pete

--
pete@fenelon.com "he just stuck to buying beer and pointing at other stuff"
Reply to
Pete Fenelon

Your ISR could simply force a reset if there is a disconnection. Easy to understand, and no overhead (in either programming time or run time).

Reply to
David Brown

This can be done by a manipulation with the CPU context in SST-like pseudo RTOS or even without RTOS. A hack just for mental exercise. :)

You betcha. The question indicates the design or concept level problems.

Vladimir Vassilevsky

DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky

Actually, if he had decided to use an SST-like pseudo RTOS (or real time pseudo OS, to be more precise), it wouldn't be a problem because he would never stop in the middle of the loop -- the function would do one operation, change its state, and return. So checking for a disconnect would be simple.

One of the responses in this thread did make me think that you could arrange the ISR to load the stack with just the right evil combination of stuff such that when you hit the 'iret' instruction you'd be in main() right before the while loop. Once you've done this and debugged it you may as well have used an RTOS, however.

I think you are correct.

--
Tim Wescott
Wescott Design Services
 Click to see the full signature
Reply to
Tim Wescott

On 12 Dec 2006 19:47:25 -0800, "visweswara" wrote in comp.arch.embedded:

It doesn't make any difference what a compiler supports. You are jumping into the middle of foreground code that expects a particular stack frame with particular data on it, particular values in registers, and quite a few other things.

If you enter foreground code from an ISR, the context and the stack are all wrong.

--
Jack Klein
Home: http://JK-Technology.Com
 Click to see the full signature
Reply to
Jack Klein

Isn't that what setjmp and longjmp is basically supposed to do ? The only problem one probably have to take care of otherwise in this context is the fact that one is jumping from an ISR to a non ISR routine. If the architecture uses a single stack for calls and interrupts, then one probably just need to take care of the actual interrupt state.

Using an RTOS does not automatically prevent such a problem. If the program was structured incorrectly then one can still end up having to check all over the place to see if the device is still present. For me it is clear that the OP did not forsee the consequences of the device suddenly dissappearing. If he had , he would probably have changed his design so that his current ptoblem would not have had existed.

I agree as well.

Regards Anton Erasmus

Reply to
Anton Erasmus

Here is another solution: run the processing loop as the very bottom task in the SST, and run everything else as the different SST tasks. In this case, one can alter the context of main() while keepeng everything else alive. This requires hacking of the stack frame.

That would be difficult if there are any other interrupts and tasks. Also it is very position dependent.

Vladimir Vassilevsky

DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky

That's why I suggested hacking the stack frame to insert a call to a signal handler instead. The signal handler has a well defined label, so there are no position dependency issues. For maximum flexibility, the handler could even be registered at run-time.

On a multitasking system, it is possible to rewrite the stack frame of a particular task, rather than the interrupted one. You can even stack multiple signals for the same task. A bitmask in the task struct could be used to avoid duplicates.

Reply to
Arlet

Sorry, but what are the pittfalls of calling functions from ISR?

Anyway, thanks for all the help so far. A lot of this is over my head, I'm still pretty new to embedded programming. Anyway, I think I'm fine with just checking for the flag all over the place :)

Reply to
galapogos

None, provided the functions don't call the OS and other non-shareable devices. Also beware running out of stack space, and using excessive time. Also any functions called should be fully re-entrant, and return so that the ISR service routine can clean up.

--
Chuck F (cbfalconer at maineline dot net)
   Available for consulting/temporary embedded and systems.
Reply to
CBFalconer

Actually, I've encounted another case, at least once.

In the Microchip C18 C compiler, version 1.x (I can't speak to the later versions, as I didn't dig into their details as much), they used static memory for compiler temporaries. Their live variable analysis was okay and dealt with the case where code would call functions that themselves may be separately compiled and use the same temporary space

-- they pushed those statics before making a call, if live variable analysis showed them necessary. However, in the case of interrupt routines, static compile-time analysis fails completely because it's a dynamic situation. So if you call a C function from the interrupt procedure, it's quite possible that your interrupt function interrupted another C function that hadn't preserved the live, static, compiler temporaries and that if you then call a C function it might use them. Stomping on them, completely.

There was no way to access the names of these variables, at link time. They were local and not available. And their locations varied depending on compilation units, variables, etc. So no fixed locations, either.

That is another place I've seen this crop up. So I'd add the warning to be cognizant that there may be internal static variables (compiler generated or library) that one needs to preserve and which are not documented or accessible by symbol or address.

Jon

Reply to
Jonathan Kirwan

On MCUs which are not C friendly it is very seldom the case that one can asume all the properties required for calling functions from an ISR. I have had problems with low level functions not being re-entrant on and older version of IAR 8051. (IIRC V4.x) The code generated for switch statements were not re-entrant. I even had a problem where I compared 2 signed 16 bit integers. This generated a call to a low level routine which were no re-entrant. I had to write code that first checked the sign and then do unsigned compares to get the compiler to generated code that did not call a low level function. If one had XDATA space, one could switch to a different memory model, where the compiler generated a soft stack in XDATA space. This removed all these re-entrancy problem, but the code were MUCH slower and of course one had to have XDATA space.

Regards Anton Erasmus

Reply to
Anton Erasmus

I don't have an OS for my MCU. I can imagine running out of stack space and using excessive time, but I didn't think of making the called functions re-entrant. A couple of them aren't. I'll modify them so that they are.

Reply to
galapogos

I don't have an OS for my MCU. I can imagine running out of stack space and using excessive time, but I didn't think of making the called functions re-entrant. A couple of them aren't. I'll modify them so that they are.

Reply to
galapogos

You can even hit problems on C-friendly architectures like the msp430. The hardware multiplier on many small micros is handled outside the core, and its state may not be saved by the interrupt routine.

Reply to
David Brown

The re-entrancy means you don't have to worry about calling them from a higher priority interrupt that has interrupted the interrupt. But that is the precise scenario that can eat stack space. Interrupt systems that switch stack on interrupt entry can also be fatal. It is much simpler to just use a master stack at all times, but that means you don't know a-priori the stack requirements of a system.

Systems that switch stack on OS calls can cause troubles here. I always tried to design with a master stack that had access to all available memory, and checked for available stack space on every function call or heap call (the heap was always increasing upward, and the stack decreasing downward). This works when you have prior knowledge of the memory map.

--
Chuck F (cbfalconer at maineline dot net)
   Available for consulting/temporary embedded and systems.
Reply to
CBFalconer

More specifically, this sounds like a job for a state machine. Put your disconnected test at the top of the loop, before the state handlers, and force the "oops - disconnected" state, starting with any cleanup necessary.

To put it another way, one can "goto" an exceptional state without having to use gotos in code. Much cleaner, more logical, and *way* more maintainable.

Steve

formatting link

Reply to
Steve at fivetrees

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.