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: AustraliaPosts: 46 |
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 KingdomPosts: 3663 |
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). John |
||||
Geoffg Guru Joined: 06/06/2011 Location: AustraliaPosts: 3165 |
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: ThailandPosts: 2209 |
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 ZealandPosts: 9066 |
...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: AustraliaPosts: 1098 |
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 ZealandPosts: 9066 |
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: AustraliaPosts: 1328 |
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 ZealandPosts: 9066 |
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: AustraliaPosts: 3165 |
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: AustraliaPosts: 46 |
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: AustraliaPosts: 3165 |
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: AustraliaPosts: 46 |
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: AustraliaPosts: 3165 |
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: AustraliaPosts: 46 |
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: AustraliaPosts: 3165 |
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: AustraliaPosts: 46 |
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. Jimmy |
||||
Geoffg Guru Joined: 06/06/2011 Location: AustraliaPosts: 3165 |
Ah, OK. Thanks. Geoff Graham - http://geoffg.net |
||||
Print this page |