_stack space
O.K.,
I have what my be a stupid question, but I thought I can ask it because I am somewhat confused about declaring memory for stack space.
Here is the question?
I have written a small spin. program.
It check's the heath of the propeller, blinking so I know the processor is working.
The next cog is for servo rotation, when I declare long stack0[noparse][[/noparse]10]. The program works.
When I declare ·long stack0[noparse][[/noparse]5], The program will not function. I looked up stack in the propeller manual but I still do not have a full understanding of short and long mem. for stack space ?
I pasted the program below and the spin program.
Any info would clear this up for me, I cannot seem to grasp the min and max. memory requirments for _stack.
Thank's
·Rob7
'' Written for Spin Stamp
'' Testing two cogs with the spin stamp(running in parallel.)
'' One continuous rotation Servo and CPU health test with four servo directional commands.
'' Led on P13
'' Servo on P12
'' My first program, Rob7. 8/15/2007
CON
· _clkmode = xtal1 + pll8x
· _xinfreq = 10_000_000
· out·· =······ %1
· on··· =······ %1
· off·· =······ %0
VAR
· byte counter
· long Pause, Pulsout·
· long stack0[noparse][[/noparse]10]
· long stack1[noparse][[/noparse]10]
OBJ
··
· Debug: "FullDuplexSerialPlus"·
PUB Start
· cognew(Run(13),@stack0)
· cognew(servoP12Clockwise,@stack1)
PRI Run(led)
· dira[noparse][[/noparse]13] := out
· outa[noparse][[/noparse]13] := off
· repeat
··· outa[noparse][[/noparse]13] := on
··· waitcnt(clkfreq / 3 + cnt)
··· outa[noparse][[/noparse]13] := off
··· waitcnt(clkfreq / 5 + cnt)
··· outa[noparse][[/noparse]13] := on
··· waitcnt(clkfreq / 5 + cnt)
··· outa[noparse][[/noparse]13] := off
··· waitcnt(clkfreq + cnt)
PRI ServoP12Clockwise
···
· Pause := clkfreq/1_000
· Pulsout := clkfreq/500_000
·························································
· dira[noparse][[/noparse]12]~~
· outa[noparse][[/noparse]12]~
·
· repeat counter from 1 to 75······················· ' Loop for three seconds
··· outa[noparse][[/noparse]12]~~
··· waitcnt(Pulsout * 850 + cnt)····················· ' P12 servo counterclockwise
··· outa[noparse][[/noparse]12]~
··· waitcnt(Pause * 30 + cnt)
· repeat counter from 1 to 75························ ' Loop for three seconds
··· outa[noparse][[/noparse]12]~~
··· waitcnt(Pulsout * 650 + cnt)····················· ' P12 srvo clockwise
··· outa[noparse][[/noparse]12]~
··· waitcnt(Pause * 30 + cnt)
· repeat counter from 1 to 75························ ' Loop for three seconds
··· outa[noparse][[/noparse]12]~~
··· waitcnt(Pulsout * 850 + cnt)····················· ' P12 servo counterclockwise
··· outa[noparse][[/noparse]12]~
··· waitcnt(Pause * 30 + cnt)
·····················································
· repeat counter from 1 to 75························ ' Loop for three seconds
··· outa[noparse][[/noparse]12]~~
··· waitcnt(Pulsout * 650 + cnt)····················· ' P12 servo clockwise
··· outa[noparse][[/noparse]12]~
··· waitcnt(Pause * 30 + cnt)
· repeat counter from 75 to 1························ ' Ramp down from three seconds
··· outa[noparse][[/noparse]12]~~
··· waitcnt(Pulsout * 650 + cnt)
··· outa[noparse][[/noparse]12]~
··· waitcnt(Pause * 5 + cnt)
···
· '********************************************************************************************
I have what my be a stupid question, but I thought I can ask it because I am somewhat confused about declaring memory for stack space.
Here is the question?
I have written a small spin. program.
It check's the heath of the propeller, blinking so I know the processor is working.
The next cog is for servo rotation, when I declare long stack0[noparse][[/noparse]10]. The program works.
When I declare ·long stack0[noparse][[/noparse]5], The program will not function. I looked up stack in the propeller manual but I still do not have a full understanding of short and long mem. for stack space ?
I pasted the program below and the spin program.
Any info would clear this up for me, I cannot seem to grasp the min and max. memory requirments for _stack.
Thank's
·Rob7
'' Written for Spin Stamp
'' Testing two cogs with the spin stamp(running in parallel.)
'' One continuous rotation Servo and CPU health test with four servo directional commands.
'' Led on P13
'' Servo on P12
'' My first program, Rob7. 8/15/2007
CON
· _clkmode = xtal1 + pll8x
· _xinfreq = 10_000_000
· out·· =······ %1
· on··· =······ %1
· off·· =······ %0
VAR
· byte counter
· long Pause, Pulsout·
· long stack0[noparse][[/noparse]10]
· long stack1[noparse][[/noparse]10]
OBJ
··
· Debug: "FullDuplexSerialPlus"·
PUB Start
· cognew(Run(13),@stack0)
· cognew(servoP12Clockwise,@stack1)
PRI Run(led)
· dira[noparse][[/noparse]13] := out
· outa[noparse][[/noparse]13] := off
· repeat
··· outa[noparse][[/noparse]13] := on
··· waitcnt(clkfreq / 3 + cnt)
··· outa[noparse][[/noparse]13] := off
··· waitcnt(clkfreq / 5 + cnt)
··· outa[noparse][[/noparse]13] := on
··· waitcnt(clkfreq / 5 + cnt)
··· outa[noparse][[/noparse]13] := off
··· waitcnt(clkfreq + cnt)
PRI ServoP12Clockwise
···
· Pause := clkfreq/1_000
· Pulsout := clkfreq/500_000
·························································
· dira[noparse][[/noparse]12]~~
· outa[noparse][[/noparse]12]~
·
· repeat counter from 1 to 75······················· ' Loop for three seconds
··· outa[noparse][[/noparse]12]~~
··· waitcnt(Pulsout * 850 + cnt)····················· ' P12 servo counterclockwise
··· outa[noparse][[/noparse]12]~
··· waitcnt(Pause * 30 + cnt)
· repeat counter from 1 to 75························ ' Loop for three seconds
··· outa[noparse][[/noparse]12]~~
··· waitcnt(Pulsout * 650 + cnt)····················· ' P12 srvo clockwise
··· outa[noparse][[/noparse]12]~
··· waitcnt(Pause * 30 + cnt)
· repeat counter from 1 to 75························ ' Loop for three seconds
··· outa[noparse][[/noparse]12]~~
··· waitcnt(Pulsout * 850 + cnt)····················· ' P12 servo counterclockwise
··· outa[noparse][[/noparse]12]~
··· waitcnt(Pause * 30 + cnt)
·····················································
· repeat counter from 1 to 75························ ' Loop for three seconds
··· outa[noparse][[/noparse]12]~~
··· waitcnt(Pulsout * 650 + cnt)····················· ' P12 servo clockwise
··· outa[noparse][[/noparse]12]~
··· waitcnt(Pause * 30 + cnt)
· repeat counter from 75 to 1························ ' Ramp down from three seconds
··· outa[noparse][[/noparse]12]~~
··· waitcnt(Pulsout * 650 + cnt)
··· outa[noparse][[/noparse]12]~
··· waitcnt(Pause * 5 + cnt)
···
· '********************************************************************************************
Comments
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Paul Baker
Propeller Applications Engineer
Parallax, Inc.
There are three reasons:
(a) When computing nested constructs (loops, ifs,...) or expressions (a*(b/(c+d))) there exists a very simple compiler strategy to "push" intermediate results. This need not neccessarily be done that way, but it is very convenient.
(b) When calling routines it is usual to use a stack for parameters and the return address, though strictly this is also not necessary, if you avoid re-entrant (or recursive) use.
(c) When using re-entrant routines, each routine must make a copy of all it's local (!) variables; there is no other known technique for this that a "stack".
So, you have to give the SPIN a hint, to what amount you use this feature: consider all the nesting according to your internal knowledge of the program.
This is what you set with _STACK for your "main COG" #0
If you have more COGs with SPIN interpreters running inside, each of them will need its own stack; where you have to allocate some LONGS for (according to the same considerations as for the main COG).
10 is a somewhat small number; generally 100 will be on the much safer side.
What you're seeing is that the stack space you've allocated is not enough. I don't know exactly how much is needed as a minimum. Any method call needs about 4 longs plus whatever parameters and local variables are defined. There are also temporaries needed to calculate expressions and this depends on the complexity of the expression. Anything that the cog's main method calls takes additional stack levels. I would allocate a minimum of 20 longs for all but the simplest cog program. If there are calls to other objects or methods, I would increase this to at least 30 and as much as 50.
There is a program in the Propeller Object Exchange that fills the stack area with a known value and watches to see what gets overwritten. This can help give you some idea of what's needed.
DeSilva. Yes, to your question.
Paul, Thank you very much for that Info, I thought I read somewhere, in the propeller education labs a section on determining stack space. Always allow extra room.
I'll find it .
Mike, Thanks!
It is always easy for me to understand when you write a reply, at least for me.
Mike wrote:
Any method call needs about 4 longs plus whatever parameters and local variables are defined. There are also temporaries needed to calculate expressions and this depends on the complexity of the expression. Anything that the cog's main method calls takes additional stack levels. I would allocate a minimum of 20 longs for all but the simplest cog program. If there are calls to other objects or methods, I would increase this to at least 30 and as much as 50.
"I will to keep this in mind as a baseline when allocating stack space."
"I think", I may not have described the question correctly.
I was wondering if there was a way to see how much space was needed. "Before you declare that space in stack", rather than just giving the space a number and having a large number of bytes in the stack wasted or not used in memory.
Just thought I woud ask?
·Rob7
It's difficult to even estimate the number of levels involved. As Paul and deSilva implied, the minimum number of long required is determined by the worst case call depth including the numbers of parameters and local variables. If these calls are in expressions, the number of temporary stack locations to calculate the expression have to be factored in. Some optimizing compilers can do this kind of worst case analysis, but it's very complicated and imperfect because the exact path taken in a program may depend on the data and most programming languages don't even have a way to specify the range of allowed data values to the compiler so it can do some pruning of the possible paths.
Your right !
I did find what I was looking for in Methods and Cogs, The propeller education lab. Page 7, referring to "How much stack space for a method launched into a cog ?"
It looks like, "I will always have to declare way more memory than I think I will need."
I can also look in the stack Length.spin to find out how many variables the method actually used and allocate the correct memory size.
Thanks guys.
Rob7