Escape from gosub without using return

Hi all,

I am building a stroboscope,dwell and tachometer using a Picaxe 18M2. This is a tool for adjusting the ignition timing on classic motorbikes (or cars if you like them more :))
It has a power LED (RGB LED) fed by a FET transistor.
There are 4 buttons (menu,-,+,OK) and 1 8 digit starburst LCD display.

I programmed the intterrupt on for the menu-button so it's easy to jump from the running procedure back to the menu. In the menu itself, I don't need the interrupt.
So far so good... evrything works fine , but...

The setint finally causes a subroutine call

Since I need the interrupt to jump to the menu program label and never do a retrun, after 4 jumps the stack is full and the program 'crashes'
The only options I see is to abandon the setint idea and poll the menu button frequently
or
put the new 'reset' command after the interrupt labeland restart the whole picaxe.

I am looking for a more subtile solution ín between

Is there a way to flush the subroutine stack (by doing some poke command or something)?
 

hippy

Technical Support
Staff member
There's no way to flush the GOSUB-RETURN stack but you can keep GOSUB'ing without RETURN, as long as you don't subsequently RETURN too many times. The only conditions are that an interrupt must have a RETURN at the same subroutine depth in order to re-enable interrupts, and while the GOSUB without RETURN works on real chips it will create 'Stack Overflow' in the simulator.
 
Fast answer! Thanks!

In my program I only use goto's I only need to interrupt to detect when the menu button is pushed

After it's finished I'll put the project in finished projects.
 
Last edited:
Fast answer needs a fast try too.

I did the same in a simple setup.
Code:
main:
setint %00000000,%00000001
low b.2
goto main

interrupt:
high b.2
pause 1000
goto main
'return
The result is the same on the 18m2 and in the editor:

The interrupt triggers just once. I also tried setint off or setting another interrupt mask,byte in the interrupt routine to force it out but this didn't work out.

You may be right on the gosub issue but I think this is a different issue.
It seems somewhere the interrupt triggers a bit that only will be reset when the return is issued.

I am afraid I have to settle for the reset command in the interrupt routine for now


If only i could poke this bit back ...

When using return instead of the goto, it's just working as the manual describes :)
 

geoff07

Senior Member
You might consider this alternative:

Code:
symbol F_int_flag = bit0
gosub init_interrupt
do
    if F_int_flag = 1 then
         F_int_flag = 0
         high b.2
         pause 1000
     endif
     low b.2
loop
end

interrupt:
F_int_flag = 1
init_interrupt:
setint 000000,000001
return
It has some advantages:
- no gotos (code with lots of gotos is very hard to understand or debug)
- proper use of the interrupt return
- no significant delay in the interrupt routine
- no relationship between the interrupt and the main code (the flag just gets set as if by magic)
- the interrupt gets reinitialised properly
- the high/pause/low logic is all together in one place

Granted this is a trivial example, but in a longer example it could matter that in future you might be able to work out what you were doing.
 
Last edited:
Geoff, something like that might work

Maybe I need it to work the other way around

So waht you say:
when the menu button is pushed (trigger interrupt) just gosub the interrupt subroutine, just set a flag and return. Later at the end of the current routine running, detect the flag set and jump (goto) the menu-routine.

I think all above is in the manual and should work :)

I must look into the do... ...loop (while) thing you suggest...
 
Last edited:

hippy

Technical Support
Staff member
It seems somewhere the interrupt triggers a bit that only will be reset when the return is issued.
That's correct; it's the "Within interrupt" flag which is set and that can only be cleared by executing the RETURN from the interrupt routine, and whilst it thinks it's within an interrupt another interrupt won't be responded to..

Another possibility on the M2's is to use the multitasking capability which allows a task to be restarted from within the interrupt routine. That could be be a less harsh form of reset.
 
Multitasking was my first attempt in this project but, as timing is important, i could't cope with the timing 'instability' caused by the other program when it's in pause or something leaving more time for the other programs. This is why I abandoned the multitasking.

I can live with 'roughly' 4M but it is too instable for my project.
Now it's on just one thread I switch to 32M as much as possible. Pro: the menu structure is working very smooth in 32M!

Thanks for the help so far!

Erik
 
I built this structure in my 18M2 program and it works perfectly!

Code:
symbol intflag = b10
symbol menu = b11
intflag = 0

menu1:
intflag = 0                                            <= we need to reset the flag after it's triggered
...                                                      <= here the menu is run
                                                         <= from here we jump to the other routines 
goto menu1

program1:
setint %00000000,%00000001                 <= as input c.0 goes low the interrupt triggers
do while intflag = 0
                                                         <= here the the routine runs
loop                                                   <= as long the flag is 0 we stay in this routine
menu = 1                                            <= the menu symbol will send us to the richt step in the menu routine
goto menu1

interrupt:
  intflag = 1                                         <= the only thing we do is setting the flag
return                                                 <=and return to the running routine just as the manual told us to do :)
again:
Thanks all!
 
Top