Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 04:30 06 May 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Possible bug with interrupts and run

Author Message
jimbotron
Regular Member

Joined: 27/11/2013
Location: Australia
Posts: 46
Posted: 03:15am 12 Nov 2014
Copy link to clipboard 
Print this post

I found a possible bug with the MMBasic where I get a stack overflow message if I call RUN whilst the system is executing a function, but only if I do this a few times.
The following program demonstrates the bug. The program will restart a few times then get a stack overflow.
print "Starting"
A = MyFunc()

function MyFunc()
run
end function

Output...
RUN
Starting
Starting
Starting
Starting
Starting
Starting
Starting
Starting
Starting
[1] Print "Starting"
Error: Stack overflow. Expression is too complex
>

Each time RUN is called, the program restarts and prints
"Starting". It works about 10 times then crashes.

This is a more complicated example. In this case RUN is being called from an interrupt handler, Event, rather than the function, MyFunc, which is still executing.
print "Starting"
settick 100, Event

A = MyFunc()

function MyFunc()
DO:LOOP
end function

Event:
run
ireturn

It appears that if the RUN statement is executed in the middle of a function call, the execution environment is not completely cleaned up and something from the function call is left on the stack each time. I was attempting to implement a watch dog routine that had some extra smarts to so that I could get more reliable operation from the ESP8266 Wifi modules when I came across this behaviour.

I've tested it on the MKII code builds 16 and 20 and it also appears to affect the DOS version of MMBasic.

Jimmy
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3663
Posted: 03:46am 12 Nov 2014
Copy link to clipboard 
Print this post

I think RUN is only meant to be typed at the console prompt.

The only other use of RUN I've met was as RUN "program" which throws away the current program (same as NEW) and then runs whatever is in file "program" (error if it doesn't exist).

JohnEdited by JohnS 2014-11-13
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3165
Posted: 03:52am 12 Nov 2014
Copy link to clipboard 
Print this post

It is amazing the things that people find when they explore outside of the box !!!!

On the Micromite run should not work inside a program, it should throw an error... I will instruct it to behave better.

Geoff
Geoff Graham - http://geoffg.net
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 04:09am 12 Nov 2014
Copy link to clipboard 
Print this post

You could use WATCHDOG 1 instead of RUN.
This will make sure you start cleanly.

RUN is described as running the program stored in flash. No word about clearing memory, so probably the result is as expected.





Microblocks. Build with logic.
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9066
Posted: 03:44pm 12 Nov 2014
Copy link to clipboard 
Print this post

  Geoffg said  On the Micromite run should not work inside a program, it should throw an error...


...but it is OK to use RUN inside a program on MMBASIC for the Maximite series - correct?

I am currently using RUN to re-start code on a CMM unit, and it seems to work fine. In my case, I am doing this in an interrupt if a "RESET" button is pressed. The reason for NOT using a reset button on MCLR, is to make sure that if the CMM is writing to the SD card at the point someone presses reset, it can finish that writing before it resets. The RESET button is inhibited while SD card writing is going on by disabling that interrupt during card writes, in other words. Hard-resetting in the middle of SD card writing would not make you many friends in the data integrity world, I think it is fair to say.
Smoke makes things work. When the smoke gets out, it stops!
 
panky

Guru

Joined: 02/10/2012
Location: Australia
Posts: 1098
Posted: 05:57pm 12 Nov 2014
Copy link to clipboard 
Print this post

Grogster,
I am sure Geoff will correct me if I am wrong, however I think it would be wrong or at least inadvisable to use RUN inside a program. Perhaps a better/alternate way to achieve what you are trying to do would be to use the SD write signal as a holdoff for a pulse to MCLR. Maybe a 555 and a few other components, even a umite to monitor the other umite!
Doug.
... almost all of the Maximites, the MicromMites, the MM Extremes, the ArmMites, the PicoMite and loving it!
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9066
Posted: 06:32pm 12 Nov 2014
Copy link to clipboard 
Print this post

  panky said   Grogster,
I am sure Geoff will correct me if I am wrong, however I think it would be wrong or at least inadvisable to use RUN inside a program.


OK.

Why?

I am rethinking that idea myself, but still....

My thoughts are along the same lines as what you have just pointed out, and rather then issue a RUN command, I can pull MCLR low via a transistor. Just requires the use of a couple of extra components and a spare I/O pin to do it, but that would - as you say - probably be more advisable.
Smoke makes things work. When the smoke gets out, it stops!
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1328
Posted: 06:54pm 12 Nov 2014
Copy link to clipboard 
Print this post

Page 4 of the MMBasic v4.5 Manual says this.

Storage Commands and Functions
A program can be saved to either drive using the SAVE command. It can be reloaded using LOAD or merged with the current program using MERGE. A saved program can also be loaded and run using the RUN command. The RUN command can also be used within a running program, which enables one program to load and transfer control to another.

The CHAIN command allows a program to load and run another program while retaining the current state of the program (ie, the value of variables, open files, loaded fonts,
open COM ports, etc). As long as a program can be broken down into modules CHAIN allows
programs of almost unlimited size to be run, even with limited memory.

----------------
That seems to say it's OK to use RUN inside an MMBasic program.

Greg
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9066
Posted: 07:13pm 12 Nov 2014
Copy link to clipboard 
Print this post

Yeah, I think that the issue is with the MICROMITE. You can't use RUN inside a program running on the Micromite, but I THINK it is OK on the Maximite versions of MMBASIC.

I think I will still look closely at using another I/O pin to trip MCLR via a transistor buffer rather then re-runing the currently running program. Using MCLR would ensure a clean restart which might not be the case, if some odd programming bug got going somehow within the run cycles.
Smoke makes things work. When the smoke gets out, it stops!
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3165
Posted: 07:49pm 12 Nov 2014
Copy link to clipboard 
Print this post

  Grogster said   Yeah, I think that the issue is with the MICROMITE. You can't use RUN inside a program running on the Micromite, but I THINK it is OK on the Maximite versions of MMBASIC.

That is correct. On the Maximite RUN inside a program was intended to run another program on the SD card, although it could also run itself. Because of this the code took care to cleanup the stack, etc.

On the Micromite there is no other program to run so I disabled the ability to run inside a program and removed the code to cleanup the stack. BUT, the disable function was itself disabled (the bug) so when jimbotron tried RUN inside a program it executed but without the stack cleanup in the Micromite version - thus the strange effects that he saw.

Geoff
Geoff Graham - http://geoffg.net
 
jimbotron
Regular Member

Joined: 27/11/2013
Location: Australia
Posts: 46
Posted: 08:04pm 12 Nov 2014
Copy link to clipboard 
Print this post

Thanks for the responses everyone.
Geoff, rather than re-educating the little fella, any chance of teaching it to handle RUN properly instead. It seems it is very close to working. Calling RUN from a program works in most versions of BASIC I've ever used and like Grogster I've found it useful to be able have more control over when the "reset" occurs.
The other problem with using the watchdog or pulling a pin low, is that is much slower than calling RUN and of course we don't have that many pins to play with on the Micromite.

Please consider this to be a feature request rather than a bug report. Exploring outside the box is part of the fun of programming things for yourself .

Jimmy
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3165
Posted: 09:32pm 12 Nov 2014
Copy link to clipboard 
Print this post

This comes up often enough that there may be a need for a RESET command. But you can do the same thing with WATCHDOG 1.

Geoff
Geoff Graham - http://geoffg.net
 
jimbotron
Regular Member

Joined: 27/11/2013
Location: Australia
Posts: 46
Posted: 01:29pm 14 Nov 2014
Copy link to clipboard 
Print this post

Geoff,
One difference between using Watchdog 1 and the Reset, could be speed. Even at 1 ms timeout it takes about half a second to reboot. Reboot from power on is much faster.
When controlling machinery that half second could be a problem. If RESET could eliminate the delay it would be a useful addition. (I still prefer to be able to use RUN as it does not display the boot message )

Jimmy
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3165
Posted: 06:02pm 14 Nov 2014
Copy link to clipboard 
Print this post

Thanks for the excellent suggestions Jim.

I have delved into running RUN from within a program and it cannot be easily done because of the way the internal stack is handled on the Micromite. So, for the moment we are stuck with WATCHDOG 1.

I will re look at RUN or RESET in a few days to see if I can workaround the stack issue.

Geoff
Geoff Graham - http://geoffg.net
 
jimbotron
Regular Member

Joined: 27/11/2013
Location: Australia
Posts: 46
Posted: 02:04am 17 Nov 2014
Copy link to clipboard 
Print this post

The following equivalent code using CPU Restart runs indefinitely and fast!
Print "Starting"
A = MyFunc()

Function MyFunc()
CPU Restart
End Function

As good as run if not better as I now know everything is reset.
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3165
Posted: 03:42am 17 Nov 2014
Copy link to clipboard 
Print this post

Why not just use CPU RESTART on its own? Why put it in a function?
Geoff Graham - http://geoffg.net
 
jimbotron
Regular Member

Joined: 27/11/2013
Location: Australia
Posts: 46
Posted: 10:41am 17 Nov 2014
Copy link to clipboard 
Print this post

Hi Geoff,
Just showing that the overflow error does not occur if you use CPU Restart. That code snippet is what I used to demonstrate the problem using RUN whilst in a function call.
I replaced RUN with CPU RESTART then retested. The original code would loop about 10 times then crash, but using CPU RESTART gives exactly the same result without the overflow error.

JimmyEdited by jimbotron 2014-11-18
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3165
Posted: 11:46am 17 Nov 2014
Copy link to clipboard 
Print this post

Ah, OK. Thanks.
Geoff Graham - http://geoffg.net
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024