I'm quite new to context switch and embedded software development. I'm developing a standalone application (no OS) with aduc7026 and keil uVision3. My problem is that at the end of an uart messagge, which I must receive by interrupt, depending on the content of the messagge I've to return return in main in the state saved before entering in the ISR or I've have to return in a specified point where a funcion call is executed.
Hoping that I've been clear. Does anyone have suggestions?
Thank ìs in advance,
Matteo
depending on the content of the messagge I've to return return in main in the state saved before entering in the ISR or I've have to return in a specified point where a funcion call is executed.
Let begin with the first part: this can be solved by maintaining the status of the main loop in a variable and s state machine - no sweat. Why must you return _exactly_ to a specific call? Why not then call the function in question from within the ISR itself (taking care not allowing its execution to take too long)? Remember that interrupts are by definition asynchronous and can occur while any instruction is being executed. If you really want to return exactly to where ypu left of, you probably want to use something like a "co-routine", based on "duff's device". But that if _not_ a standard programming technique and it comes with a price tag, but this cannot be integrated with interrupt handling in the way you want to. Also consider not using interrupt based reception - that way, you poll the data source, implicitly returning to where you left off before polling!
You can also post a message into a pipe of a queue from the ISR to the main loop for later handling. Resolving the message type will invoke the correct message (the main loop will poll the queue - be careful of synchronization issues). Can you live with a slight delay in execution so that you don't have to call the function from the ISR...?
I should have posted:
"will invoke the correct function"
"Does anyone have suggestions?"
my first suggestion would be to structure your code so it doesn't do what you are trying to do - it simply sounds "un-natural" and messy.
my 2nd suggestion would be to branch your code based on where your code may jump to. in the main, disable interrupt, execute one of the branches based on a flag, and then turn on the interrupt (to process any messages), and go back to the top. you will in the isr set the flag based on the messages received.
something like this:
1) isr:
receive the message if message is x, set flag to f_x; if message is y, set flag to f_y; ...
2) main code:
disable interrupt; if flag is f_x, execute branch x; if flag is f_y, execute branch y; ... enable interrupt; loop back
the problem with this approach is that it isn't terribly good with real time response.
my 3rd suggestion would be to receive the message in the main, set a flag and then trigger a software interrupt. in the software interrupt, you process the flag (and jump to wherever you want based on the flag).
this approach requires the processing of the flag to be very fast and consumes lots of mcu cycles.
I've have to return in a specified point where a funcion call is executed.
Let me point out that for someone who's still quite new to the whole field of embedded SW, you hold some awfully firm beliefs about how you "have to" do things. That doesn't feel right.
And no, you almost certainly (a) don't have to do that, nor (b) should be be trying to at this point on your learning curve. Stick to simpler designs until you really know what you're doing.
I try to explain better. When i receive a messagge i must restart from a specifc pOint since the messagge work like a reset command but due tO strict time requirements i can not perform a reset.
So you should then use a state machine. Let the states represent the task at hand. And when you receive commands, you can decide if the commands should be queued (or may even be processed instantly) or if the received command should place the state machine back into an initial state again.
There just is no reason for trying to jump to absolute positions in the code. It is just an example of "I have a problem and want to run on the first idea I get even if it is a bad - or even nonworking - idea.
I agree with the others: this sounds like an awful way to structure a program.
I understand that it isn't the best way to structure a program but using state machine what happens if the main loop hang?
Thanks to all for the useful messages and suggestions.
And no, you almost certainly ... should [not] be be trying to at this point on your learning curve.
I would say this has nothing to do with the "point on your learning curve". I know of no technique that can do this safely, at least in C. I can visualize some "monkey code" in assembler that might make it 'work' in a non-mainatinable way.
Erik
So I should implement a context switch to a specified point in assembly and add it to the c code? In the assembly code I should save the state in the specific point where I want to retur if specific messagge is received. Then if the messagge arrives I should Pop the stack with the saved information for the state where the interrupt wants to come back and load the state saved and set the program counter to the address of the saved state? Does This work and recover main from hangs? Don't care about the manteinment and portability of the code.
but using state machine what happens if the main loop hang?
If understand this correctly, your main loop is too slow to ensure a fast enough response to a message. Use interrupts then. Structure the fast message handler as an ISR and trigger the corresponding interrupt when you receive the message. Assign interrupt priorities accordingly.
"If understand this correctly, your main loop is too slow to ensure a fast enough response to a message. "
The problem isn't the speed but the fact that receving a messagge is more important than executing other task.
" Use interrupts then. Structure the fast message handler as an ISR and trigger the corresponding interrupt when you receive the message. Assign interrupt priorities accordingly. "
This is a nice solution, however doesn't meet the requirements to restart from that function because after the interrupt the execution restart from the point where the code was executing...
So I should implement a context switch to a specified point in assembly and add it to the c code?
No, you shouldn't. And I find it really hard to see how you arrived at that conclusion from the advice you've been given here. It's a Bad Idea(no TM).
You appear to be going at this from entirely the wrong angle. The cure you're trying so very hard to administer is almost certainly worse than the possible problem you're worried about. It's quite possible that this crazy technique not only won't help if main is unstable, but it's actually going to make it unstable.
This is a nice solution, however doesn't meet the requirements to restart from that function because after the interrupt the execution restart from the point where the code was executing.
If you have this kind of a problem, then your program is a mess already. Adding another layer of mess might make it work, but the whole thing won't be pretty. A clean rewrite is not an option, is it?