EmbeddedRelated.com
Forums
Memfault Beyond the Launch

goto across functions/isrs?

Started by galapogos December 12, 2006
Data wrote:
> Neither goto nor longjmp() will do what you want. They don't work like > you think they do. > > I can think of two options: > > 1 - check 'connected' at every opportunity > 2 - rewrite the saved PC from main() in the stack >
There's always option 3 - jump, call, return to or otherwise get to the power on reset vector handler. Feel free to trash anything you want in the process of getting there, becuase it's going to set up everything from scratch again anyway ;-)
galapogos wrote:

> I'd have to check the state of the connection at > multiple locations within the loop(basically at every > instruction/command that I try to send to the device), which is quite a > hassle I think.
That's generally the way to do it. One method is to have only one (or at least very few) functions which actually talk to the device, and make everything else use them. Then those functions can check and make sure it's still there.
Data wrote:
> Neither goto nor longjmp() will do what you want. They don't work like > you think they do. > > I can think of two options: > > 1 - check 'connected' at every opportunity > 2 - rewrite the saved PC from main() in the stack > > Option 2 is really dangerous and desperate. Don't do it. > > Option 1 is, indeed, a PITA, but you probably won't find an easy way > round it. If you do, though, by all means post it here!
Thanks for all the suggestions guys. I now the use of goto is frowned upon and hence I generally would avoid it as well. In fact, I've never used gotos since gw-basic :) In any case, I've found out a simple way of accomplishing what I want. I basically scaled down my requirement such that the system only gracefully detects sudden disconnection before the actual communication takes place. Basically, the system behavior is as such: 1) user connects device to system 2) user enters a number on the keypad 3) system communicates to the device Since it's much more likely that the device is disconnected in step 2(user decides to switch device or abort the whole transaction) and the actual communication is pretty fast(a few ms) I decided to only detect sudden disconnections in step 2. Since the interrupt polls the device connection pin every 20ms, I simply inserted a 20ms delay after step 2 to provide the state flags enough time to change state, and then check the connection status at that time. It's a compromise, but it's a simpler solution I think.
Vladimir Vassilevsky wrote:
> > > galapogos wrote: > >>>> I have an ISR that triggers when I detect an event, and based on that >>>> event I want to unconditionally goto a label that's in main(). Is that >>>> possible? If so what's the syntax? >>> >>> >>> longjmp() >>> >>> However what are you trying to do does not make much sense. >> >> >> >> OK what I'm trying to do is as follows. >> >> I have an isr that is called every 20ms that checks if something is >> connected. If so it changes a global state variable to "connected". In >> my main() I have a loop that checks if the device is connected. If it's >> not it keeps looping doing nothing. If it is, then it will start to >> talk to the device. This works fine if the device is connected and >> stays connected, but it doesn't work so well if a stupid user decides >> to suddenly disconnect the device halfway. What I'm trying to do is >> that on disconnection detection in my ISR, I can unconditionally jump >> to the beginning of the main() loop where it does the state checking so >> that my main() doesn't continue to try and talk to the device only to >> suddenly find it not there and getting all sorts of weird errors. If I >> don't use goto, I'd have to check the state of the connection at >> multiple locations within the loop(basically at every >> instruction/command that I try to send to the device), which is quite a >> hassle I think. >> > > Implement the processing function as a thread. Kill the thread if the > device gets disconnected. >
That assumes that the OP is using an OS. If he's got a task loop in main() that kind of implies no OS. He should just bite the bullet and test all over the place, or pay some $$ for an RTOS. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com Posting from Google? See http://cfaj.freeshell.org/google/ "Applied Control Theory for Embedded Systems" came out in April. See details at http://www.wescottdesign.com/actfes/actfes.html
Tim Wescott wrote:

> Vladimir Vassilevsky wrote: > > > > > > galapogos wrote: > > > >>>> I have an ISR that triggers when I detect an event, and based on that > >>>> event I want to unconditionally goto a label that's in main(). Is that > >>>> possible? If so what's the syntax? > >>> > >>> > >>> longjmp() > >>> > >>> However what are you trying to do does not make much sense. > >> > >> > >> > >> OK what I'm trying to do is as follows. > >> > >> I have an isr that is called every 20ms that checks if something is > >> connected. If so it changes a global state variable to "connected". In > >> my main() I have a loop that checks if the device is connected. If it's > >> not it keeps looping doing nothing. If it is, then it will start to > >> talk to the device. This works fine if the device is connected and > >> stays connected, but it doesn't work so well if a stupid user decides > >> to suddenly disconnect the device halfway. What I'm trying to do is > >> that on disconnection detection in my ISR, I can unconditionally jump > >> to the beginning of the main() loop where it does the state checking so > >> that my main() doesn't continue to try and talk to the device only to > >> suddenly find it not there and getting all sorts of weird errors. If I > >> don't use goto, I'd have to check the state of the connection at > >> multiple locations within the loop(basically at every > >> instruction/command that I try to send to the device), which is quite a > >> hassle I think. > >> > > > > Implement the processing function as a thread. Kill the thread if the > > device gets disconnected. > > > That assumes that the OP is using an OS. If he's got a task loop in > main() that kind of implies no OS. > > He should just bite the bullet and test all over the place, or pay some > $$ for an RTOS.
It is possible to implement the effect without an OS, as long as the CPU has an accessible stack. When the ISR notices that the device has been disconnected, it can fix up the main stack. A relatively clean way to do this, is by inserting the address of a special function on the stack, so that when the ISR finished, you return to that special function, where you can decide what to do (e.g. have a longjmp()). Something like this: signal( ) { // device disconnected, take action clean_up( ); longjmp( disconnect, 1 ); } main( ) { setjmp( disconnect ); while( 1 ) { wait_for_connect( ); use_device(); } } In the ISR, the stack will look something like this 1. ISR saved registers 2. CPU flags 3. return address to somewhere in main If you notice a disconnect in the ISR, fix up the stack like this: 1. ISR saved registers 2. CPU flags 3. signal <--- insert this one 4. return address to somewhere in main
galapogos wrote:
> Data wrote: >> Neither goto nor longjmp() will do what you want. They don't work like >> you think they do. >> >> I can think of two options: >> >> 1 - check 'connected' at every opportunity >> 2 - rewrite the saved PC from main() in the stack >> >> Option 2 is really dangerous and desperate. Don't do it. >> >> Option 1 is, indeed, a PITA, but you probably won't find an easy way >> round it. If you do, though, by all means post it here! > > Thanks for all the suggestions guys. I now the use of goto is frowned > upon and hence I generally would avoid it as well. In fact, I've never > used gotos since gw-basic :) > > In any case, I've found out a simple way of accomplishing what I want. > I basically scaled down my requirement such that the system only > gracefully detects sudden disconnection before the actual communication > takes place. Basically, the system behavior is as such: > 1) user connects device to system > 2) user enters a number on the keypad > 3) system communicates to the device > > Since it's much more likely that the device is disconnected in step > 2(user decides to switch device or abort the whole transaction) and the > actual communication is pretty fast(a few ms) I decided to only detect > sudden disconnections in step 2. Since the interrupt polls the device > connection pin every 20ms, I simply inserted a 20ms delay after step 2 > to provide the state flags enough time to change state, and then check > the connection status at that time. It's a compromise, but it's a > simpler solution I think. >
You are missing the point. You want to goto main line code from an interrupt. The interrupt return address is still on the stack. A couple more gotos and you run out of stack space. Any other calls still on the stack are also stranded The interrupt is not dispatched. does your CPU use ret or reti to return from an interrupt. You could play with the stack but it is not easy or recommended.
On 12 Dec 2006 18:45:05 -0800, "galapogos" <goister@gmail.com> wrote:

> >Vladimir Vassilevsky wrote: >> galapogos wrote: >> >> > Hi, >> > Is it possible to goto a label that's not in the same functions? >> >> Yes. >> >> I've >> > always been taught that gotos are evil >> >> No. >> >> so I don't have much experience >> > with it, >> >> I can see that. >> >> but I'm currently in a situation where I think I might have to >> > use it. >> >> No. >> >> >> > I have an ISR that triggers when I detect an event, and based on that >> > event I want to unconditionally goto a label that's in main(). Is that >> > possible? If so what's the syntax? >> >> longjmp() >> >> However what are you trying to do does not make much sense. > >OK what I'm trying to do is as follows. > >I have an isr that is called every 20ms that checks if something is >connected. If so it changes a global state variable to "connected". In >my main() I have a loop that checks if the device is connected. If it's >not it keeps looping doing nothing. If it is, then it will start to >talk to the device. This works fine if the device is connected and >stays connected, but it doesn't work so well if a stupid user decides >to suddenly disconnect the device halfway. What I'm trying to do is >that on disconnection detection in my ISR, I can unconditionally jump >to the beginning of the main() loop where it does the state checking so >that my main() doesn't continue to try and talk to the device only to >suddenly find it not there and getting all sorts of weird errors. If I >don't use goto, I'd have to check the state of the connection at >multiple locations within the loop(basically at every >instruction/command that I try to send to the device), which is quite a >hassle I think.
If you want to basically restart your application when the device is unplugged, then just stop kicking the watchdog. This wil reset your MCU. This will of course re-initialise everything which might cause problems with other peripherals. Regards Anton Erasmus
"galapogos" <goister@gmail.com> wrote in message 
news:1165975298.329026.144630@n67g2000cwd.googlegroups.com...
> Hi, > Is it possible to goto a label that's not in the same functions? I've > always been taught that gotos are evil so I don't have much experience > with it, but I'm currently in a situation where I think I might have to > use it.
No, you don't. Really, you don't. Instead you need to reconsider your program structure to make such evilness unnecessary. Steve http://www.fivetrees.com
Arlet wrote:

> It is possible to implement the effect without an OS, as long as the > CPU has an accessible stack. When the ISR notices that the device has > been disconnected, it can fix up the main stack. A relatively clean way > to do this, is by inserting the address of a special function on the > stack, so that when the ISR finished, you return to that special > function, where you can decide what to do (e.g. have a longjmp()). > > Something like this: > > signal( ) > { > // device disconnected, take action > clean_up( ); > longjmp( disconnect, 1 ); > } > > main( ) > { > setjmp( disconnect ); > while( 1 ) > { > wait_for_connect( ); > use_device(); > } > } > > In the ISR, the stack will look something like this > > 1. ISR saved registers > 2. CPU flags > 3. return address to somewhere in main > > If you notice a disconnect in the ISR, fix up the stack like this: > > 1. ISR saved registers > 2. CPU flags > 3. signal <--- insert this one > 4. return address to somewhere in main
Forgot to mention that the signal handler may corrupt CPU state, so it must end in the longjmp(), or alternatively, declare it as an interrupt routine so it will preserve all necessary state.
Arlet wrote:
> Arlet wrote: > > > It is possible to implement the effect without an OS, as long as the > > CPU has an accessible stack. When the ISR notices that the device has > > been disconnected, it can fix up the main stack. A relatively clean way > > to do this, is by inserting the address of a special function on the > > stack, so that when the ISR finished, you return to that special > > function, where you can decide what to do (e.g. have a longjmp()). > > > > Something like this: > > > > signal( ) > > { > > // device disconnected, take action > > clean_up( ); > > longjmp( disconnect, 1 ); > > } > > > > main( ) > > { > > setjmp( disconnect ); > > while( 1 ) > > { > > wait_for_connect( ); > > use_device(); > > } > > } > > > > In the ISR, the stack will look something like this > > > > 1. ISR saved registers > > 2. CPU flags > > 3. return address to somewhere in main > > > > If you notice a disconnect in the ISR, fix up the stack like this: > > > > 1. ISR saved registers > > 2. CPU flags > > 3. signal <--- insert this one > > 4. return address to somewhere in main > > Forgot to mention that the signal handler may corrupt CPU state, so it > must end in the longjmp(), or alternatively, declare it as an interrupt > routine so it will preserve all necessary state.
Design looks quite good but kind of overhead for saving and cleaning. Why not use a label at the start of main routine while setting some flag in ISR (which will be pooled in main wild loop)? ali

Memfault Beyond the Launch