Question about Stack-Size

Started by itisnt April 10, 2004
Hi

Does anybody know if the amount of Bytes used by a
given Task is always the same ?
Or can it change from Run to Run ?

My Test-Prog initializes the Task-Stack Memory with hex "FF",
starts the Task and when i press Button 1, it prints out the
hole Stack.

Now i see that this Task seems to use 25 Bytes of the given Stack
and i'am not sure if i can limit the Stack Size to let's say 26 Bytes.

Thanks Output:

*** Finished Downloading
Init Task_Stack Mem
Button Task starten...
Stack: 1 Value: 01
Stack: 2 Value: 16
Stack: 3 Value: 00
Stack: 4 Value: 00
Stack: 5 Value: 00
Stack: 6 Value: DD
Stack: 7 Value: 00
Stack: 8 Value: E8
Stack: 9 Value: 00
Stack: 10 Value: 7E
Stack: 11 Value: 03
Stack: 12 Value: 00
Stack: 13 Value: FF
Stack: 14 Value: FF
Stack: 15 Value: FF
Stack: 16 Value: 09
Stack: 17 Value: 0A
Stack: 18 Value: 32
Stack: 19 Value: 00
Stack: 20 Value: 09
Stack: 21 Value: 00
Stack: 22 Value: 01
Stack: 23 Value: 00
Stack: 24 Value: 06
Stack: 25 Value: 00
Stack: 26 Value: FF
Stack: 27 Value: FF
Stack: 28 Value: FF
Stack: 29 Value: FF
Stack: 30 Value: FF
Stack: 31 Value: FF
Stack: 32 Value: FF
Stack: 33 Value: FF
Stack: 34 Value: FF
Stack: 35 Value: FF
Stack: 36 Value: FF
Stack: 37 Value: FF
Stack: 38 Value: FF
Stack: 39 Value: FF
Stack: 40 Value: FF
Stack: 41 Value: FF
Stack: 42 Value: FF
Stack: 43 Value: FF
Stack: 44 Value: FF
Stack: 45 Value: FF
Stack: 46 Value: FF
Stack: 47 Value: FF
Stack: 48 Value: FF
Stack: 49 Value: FF
Stack: 50 Value: FF

--------> Program:

Option Explicit

Public Button(0 to 3) As Byte

' Stack for the Button Task

Public Button_Stack(1 to 50) As Byte

' -----[ Constants ]

' Buttons on the BX24 Development Board

Const Button1 As Byte = 6
Const Button2 As Byte = 7
Const Button3 As Byte = 8
Const Button4 As Byte = 9

Public Const FF As Byte = &HFF
Const ASCIIzero As integer = 48

' -----[ ButtonTask ]-

Public Sub ButtonTask()

Dim Button_Pins As Byte

' Setup internal pullup Resistor for each Button

Call PutPin(Button1,bxInputPullup)
Call PutPin(Button2,bxInputPullup)
Call PutPin(Button3,bxInputPullup)
Call PutPin(Button4,bxInputPullup)

Do
For Button_Pins = 6 to 9
If GetPin(Button_Pins) = 0 Then
Do While GetPin(Button_Pins) = 0
Loop
Button(Button_Pins - 6) = 1
End If
Next
Call Sleep(50)
Loop
End Sub

' -----[ MainProg ]-

Public Sub Main()

Dim x As Byte

Button(0) = 0
Button(1) = 0

debug.print "Init Task_Stack Mem"

For x = 1 to 50
Button_Stack(x) = FF
Next

debug.print "Button Task starten..."

CallTask "ButtonTask", Button_Stack

Do While Button(0) = 0
If (Button(1) = 1) Then
Button(1) = 0
For x = 1 to 50
debug.print "Stack: ";cstr(x); " Value: "; cHexStrB(Button_Stack(x))
Next
End If
Call Delay(1.0)
Loop
Button(0) = 0

debug.print "Stop..."

End Sub

' -----[ Function ]-
' Converts a Byte to the Hex-Value in a String

Function cHexStrB( ByVal Value As byte) as String
Dim Digit(1 To 2) As integer
Dim D as integer
Dim i As Integer, NDigits As Integer
Const Base As Integer = 16
Const ASCIIhexBias As integer = 55
Dim resultString as String

NDigits = 0
resultString = ""

for i = 1 to 2
digit(i) = ASCIIZero
next

Do
NDigits = NDigits + 1

D = cInt(Value) Mod Base
If (D < 10) Then
D = D + ASCIIzero
Else
D = D + ASCIIhexBias
End If

Digit(NDigits) = D

Value = Value \ cByte(Base)
Loop Until (Value = 0)

For i = 2 to 1 step -1
resultString = resultString & chr(Digit(i))
Next

cHexStrB = resultString
End Function



--- In , "itisnt" <itisnt@y...> wrote:
> Does anybody know if the amount of Bytes used by a
> given Task is always the same ?
> Or can it change from Run to Run ?
>

If the execution path is the same the stack usage should be the
same. If you have any conditionals, the execution path may be
different from time to time. This may affect stack usage if, in some
conditional cases, subroutines or functions are invoked that aren't
in other cases. If you are using recursion, the recursion depth also
affects stack usage.

I wrote a program to statically analyze maximum usage. It calculates
total ram use, both stack and statically allocated. You can read
about and download the RamAlyzer on this page:
http://www.kinzers.com/don/BX24. For analysis of task RAM usage, you
could use the value calculated for the task sub-tree and then add the
task invocation overhead plus a safety margin.



Hi Don,

just wanted to say that your RamAlyzer is really good. How hard would it
be to add a summary where it tells you the minimum for each task?

ie.

The Bottom Line
=============
Main Task - Main must have at least 60 bytes allocated and currently has XX
bytes
Task 1 must have at least xx bytes allocated and currently has xx bytes
Task 2 must have at least xx bytes allocated and currently has xx bytes
Task 3 must have at least xx bytes allocated and currently has xx bytes

-Trevor

At 11:24 AM 4/10/2004, Don Kinzer wrote:
>--- In , "itisnt" <itisnt@y...> wrote:
> > Does anybody know if the amount of Bytes used by a
> > given Task is always the same ?
> > Or can it change from Run to Run ?
> >
>
>If the execution path is the same the stack usage should be the
>same. If you have any conditionals, the execution path may be
>different from time to time. This may affect stack usage if, in some
>conditional cases, subroutines or functions are invoked that aren't
>in other cases. If you are using recursion, the recursion depth also
>affects stack usage.
>
>I wrote a program to statically analyze maximum usage. It calculates
>total ram use, both stack and statically allocated. You can read
>about and download the RamAlyzer on this page:
>http://www.kinzers.com/don/BX24. For analysis of task RAM usage, you
>could use the value calculated for the task sub-tree and then add the
>task invocation overhead plus a safety margin. >
>Yahoo! Groups Links >
>





--- In , Trevor Pinkney <tpinkney@s...> wrote:
> How hard would it be to add a summary where [the RamAlyzer output]
> tells you the minimum for each task?

SMOP (simple matter of programming).

It shouldn't be too difficult. I'll take a look at it if I can
allocate some time.


<tpinkney@s...> wrote:
> How hard would it be to add a summary where [the RamAlyzer] tells
> you the minimum for each task?

I added code to analyze the stack requirements for tasks. I hadn't
thought about the fact that task subroutines would likely not be
otherwise invoked so they were being reported as unused - not very
useful.

I didn't add code to compare the current stack allocation with the
computed minimum. It would take quite a bit more work to do that due
to the global/local, public/private, static/dynamic issues related to
data stores.

Anyway, I think that this will give you more information than you had
before.

You can download the new version (v0.6) via a link at the bottom of
this page:
http://www.kinzers.com/don/BX24



Hi Don,

I downloaded and executed the latest program. The summary is nice. I can
just take the number at the bottom and add a 20 byte cushion to it when
declaring my stack variables. It will be a lot faster then writing a stack
use function.

-Trevor
At 11:22 PM 4/10/2004, you wrote:
><tpinkney@s...> wrote:
> > How hard would it be to add a summary where [the RamAlyzer] tells
> > you the minimum for each task?
>
>I added code to analyze the stack requirements for tasks. I hadn't
>thought about the fact that task subroutines would likely not be
>otherwise invoked so they were being reported as unused - not very
>useful.
>
>I didn't add code to compare the current stack allocation with the
>computed minimum. It would take quite a bit more work to do that due
>to the global/local, public/private, static/dynamic issues related to
>data stores.
>
>Anyway, I think that this will give you more information than you had
>before.
>
>You can download the new version (v0.6) via a link at the bottom of
>this page:
>http://www.kinzers.com/don/BX24 >
>Yahoo! Groups Links >
>




Don,

I'am not sure if i understand your Output right. For my
Program (see below), your analyzer tells me to use 41 Bytes
at minimum for the "ButtonTask", but i gave 26 Bytes to the
Stack for these Task and it runs fine.
When i start also the "SonarTask" in the Program, then your
Analyzer will change its Output to 26 Bytes for the "ButtonTask"
and 53 Bytes for the SonarTask and this seems to be ok.

Daniel

-------> Analyzer Output with "SonarTask" disabled

E:\HexCrawler\Code>ramalyze -d tst1
Ramalyzer v0.6 Copyright 2003 Donald Kinzer

Analyzing project "tst1.bxp", Sun Apr 11 14:13:21 2004
Module: "Tst1.bas"
found CallTask "ButtonTask"
setting task flag

Estimate of application RAM use:
Invocation overhead: 15
Passed parameters: 0
Local variables: 8
Invoked functions/subs: 0
Static variables: 158
----
Total: 181

Detailed Analysis
(N.B. invocation overhead is 9 bytes)
Sub/Function Params Locals Callees Total
----------------------------------- ------ ------ ------- ------
Tst1.ButtonTask 0 2 24 35
Tst1.ButtonTask 35
Tst1.Center_S3 24
Tst1.Get_Distance 15
Tst1.WriteSSC 15
Tst1.InitSSC 9

Tst1.Center_S3 0 0 15 24
Tst1.WriteSSC 15

Tst1.Get_Distance 0 6 0 15

Tst1.InitSSC 0 0 0 9

Tst1.Main 0 8 0 23

Tst1.WriteSSC 4 2 0 15 Stack requirements for tasks:
----------------------------------
Tst1.ButtonTask 41 bytes

-----> Analyzer Output with SonarTask enabled

E:\HexCrawler\Code>ramalyze -d tst1
Ramalyzer v0.6 Copyright 2003 Donald Kinzer

Analyzing project "tst1.bxp", Sun Apr 11 14:26:41 2004
Module: "Tst1.bas"
found CallTask "ButtonTask"
setting task flag
found CallTask "SonarTask"
setting task flag

Estimate of application RAM use:
Invocation overhead: 15
Passed parameters: 0
Local variables: 8
Invoked functions/subs: 0
Static variables: 162
----
Total: 185

Detailed Analysis
(N.B. invocation overhead is 9 bytes)
Sub/Function Params Locals Callees Total
----------------------------------- ------ ------ ------- ------
Tst1.ButtonTask 0 2 9 20
Tst1.ButtonTask 20
Tst1.InitSSC 9

Tst1.Center_S3 0 0 15 24
Tst1.WriteSSC 15

Tst1.Get_Distance 0 6 0 15

Tst1.InitSSC 0 0 0 9

Tst1.Main 0 8 0 23

Tst1.SonarTask 0 4 24 37
Tst1.SonarTask 37
Tst1.Center_S3 24
Tst1.Get_Distance 15
Tst1.WriteSSC 15

Tst1.WriteSSC 4 2 0 15 Stack requirements for tasks:
----------------------------------
Tst1.ButtonTask 26 bytes
Tst1.SonarTask 43 bytes

-----------> Program

Option Explicit

Public Button(0 to 3) As Byte

' Stack for the Button Task

Public Button_Stack(1 to 30) As Byte

' Stack for the Sonar Task

Public Sonar_Stack(1 to 100) As Byte
Public Dist As Integer

' Buffer for the Mini SSC Servo Controller
' There is only Traffic to the SSC, so the In-Buffer is small

Public SSC_Out(1 To 13) As Byte
Public SSC_In(1 To 9) As Byte ' -----[ Constants
]-------------------

' Buttons on the BX24 Development Board

Const Button1 As Byte = 6
Const Button2 As Byte = 7
Const Button3 As Byte = 8
Const Button4 As Byte = 9

Public Const FF As Byte = &HFF
Const ASCIIzero As integer = 48

Const EchoPin As Byte = 13
Const TrigPin As Byte = 14
Const RefreshPeriod As Single = 0.02

Const Sync As Byte = 255
Const S3_XCenter As Byte = 122
Const S3_YCenter As Byte = 118
Const S3_XServo As Byte = 14
Const S3_YServo As Byte = 15 ' -----[ MainTask ]-------------------

Public Sub ButtonTask()

Dim Button_Pins As Byte

' Setup internal pullup Resistor for each Button

Call PutPin(Button1,bxInputPullup)
Call PutPin(Button2,bxInputPullup)
Call PutPin(Button3,bxInputPullup)
Call PutPin(Button4,bxInputPullup)

Do
For Button_Pins = 6 to 9
If GetPin(Button_Pins) = 0 Then
Do While GetPin(Button_Pins) = 0
Loop
Button(Button_Pins - 6) = 1
End If
Next
Call Sleep(50)
Loop
End Sub

Sub SonarTask()
Dim x As Byte
Dim y As Byte

Call PutPin(EchoPin, bxInputTristate)
Call PutPin(TrigPin, bxOutputLow)

' Look straight ahead

debug.print "In SonarTask"
Call Center_S3()

Call Delay(3.0)

Do
x = 50
y = 90
Do While y < 150
Call WriteSSC(S3_YServo,y)
Do While x < 190
Call WriteSSC(S3_XServo,x)
Call Get_Distance()
x = x + 5
Call Sleep(0.25)
Loop
y = y + 5
Do While x > 50
Call WriteSSC(S3_XServo,x)
Call Get_Distance()
x = x - 5
Call Sleep(0.25)
Loop
y = y + 5
Loop
Loop
End Sub

Sub Get_Distance()

Dim I As Byte
Dim rawDist As Integer
Dim pWidth As Integer

rawDist = 0
For I=1 to 5
Call PulseOut(TrigPin, 10, 1) ' 10us Trigger Puls
pWidth = PulseIn(EchoPin, 1) \ 54 ' 54 for cm, 137 for Inches
rawDist = rawDist + (pWidth \ 5) ' Small digital Filter
Next
Dist = rawDist
End Sub Public Sub Main()

Dim i As Byte
Dim XServo As Byte
Dim YServo As Byte
Dim x As Byte
Dim y As Byte

Button(0) = 0
Button(1) = 0
Button(2) = 0

debug.print "Init Task_Stack Mem"

For i = 1 to 26
Button_Stack(1) = FF
Next

For i = 1 to 100
Sonar_Stack(1) = FF
Next

Call PutPin(EchoPin, bxInputTristate)
Call PutPin(TrigPin, bxOutputLow)

debug.print "Tasks starten..."

CallTask "ButtonTask", Button_Stack

debug.print "Button 1 to start"
Do While Button(0) = 0
Loop

Call InitSSC()
CallTask "SonarTask", Sonar_Stack

Call Center_S3()
Call Delay(5.0)

x = 50
y = 90
Call WriteSSC(S3_XServo,x)
Call WriteSSC(S3_YServo,y)

Do While y < 120
Do While x < 190
x = x + 5
Call WriteSSC(S3_XServo,x)
Call Sleep(0.5)
Call Get_Distance()
debug.print "Dist: " & Cstr(Dist)
Loop
y = y + 5
Call WriteSSC(S3_YServo,y)
Do While x > 50
x = x - 5
Call WriteSSC(S3_XServo,x)
Call Sleep(0.5)
Call Get_Distance()
debug.print "Dist: " & Cstr(Dist)
Loop
y = y + 5
Call WriteSSC(S3_YServo,y)
Loop

' Do While y < 150
' ' Call WriteSSC(S3_YServo,y)
' debug.print "Y: " & CStr(y)
' Do While x < 190
' Call WriteSSC(S3_XServo,x)
' debug.print "X: " & CStr(x)
' Call Get_Distance()
' x = x + 5
' Call Sleep(0.25)
' Loop
' y = y + 5
' ' Call WriteSSC(S3_YServo,y)
' debug.print "Y: " & CStr(y)
' Do While x > 50
' Call WriteSSC(S3_XServo,x)
' debug.print "X: " & CStr(x)
' Call Get_Distance()
' x = x - 5
' Call Sleep(0.25)
' Loop
' y = y + 5
' Loop

' Do
' If (Button(1) = 1) Then
' Button(1) = 0
' Call LockTask()
' For i = 1 to 26
' debug.print "Stack: ";cstr(x); " Value: "; cHexStrB(Button_Stack(x))
' Next
' Call UnlockTask()
' End If
' If (Button(2) = 1) Then
' Button(2) = 0
' Call LockTask()
' For i = 1 to 100
' debug.print "Sonar Stack: ";cstr(x); " Value: ";
cHexStrB(Sonar_Stack(x))
' Next
' Call UnlockTask()
' End If
' Loop
End Sub

Public Sub InitSSC()

' Open Mini-SSC Channel to Servo Controler
Call OpenQueue(SSC_Out,13)
Call OpenQueue(SSC_In,9)
Call DefineCom3(0,10,bx1000_1000) ' 8-N-1
Call OpenCom(3,9600,SSC_In, SSC_Out)

End Sub

Public Sub WriteSSC(ByVal Servo As Byte, ByVal Pos As Byte)
Call PutQueueStr(SSC_Out, Chr(Sync) & Chr(Servo) & Chr(Pos))
End Sub

Public Sub Center_S3()
Call WriteSSC(S3_XServo,S3_XCenter)
Call WriteSSC(S3_YServo,S3_YCenter)
End Sub

Function cHexStrB( ByVal Value As byte) as String
Dim Digit(1 To 2) As integer
Dim D as integer
Dim i As Integer, NDigits As Integer
Const Base As Integer = 16
Const ASCIIhexBias As integer = 55
Dim resultString as String

NDigits = 0
resultString = ""

for i = 1 to 2
digit(i) = ASCIIZero
next

Do
NDigits = NDigits + 1

D = cInt(Value) Mod Base
If (D < 10) Then
D = D + ASCIIzero
Else
D = D + ASCIIhexBias
End If

Digit(NDigits) = D

Value = Value \ cByte(Base)
Loop Until (Value = 0)

For i = 2 to 1 step -1
resultString = resultString & chr(Digit(i))
Next

cHexStrB = resultString
End Function




--- In , "itisnt" <itisnt@y...> wrote:
> I'm not sure if i understand your Output right. For my
> Program (see below), your analyzer tells me to use 41 Bytes
> at minimum for the "ButtonTask", but i gave 26 Bytes to the
> Stack for these Task and it runs fine.

That's interesting. The difference is 15 which happens to be the
task stack overhead. I don't know yet what the significance of that
is. I'll look into it; I may get some time this evening to do that.

Oops. I see that I left a couple of debugging messages in the code.


--- In , "itisnt" <itisnt@y...> wrote:
> I'm not sure if I understand your Output right.

Well, it was wrong. The code that I added to detect the CallTask
caused the program to lose track of which routine it was analyzing.
I believe that I have fixed it. I had to add a more comprehensive
tokenizer to resolve the issue.

The analysis now indicates 17 bytes for ButtonTask and 43 bytes for
SonarTask.

There is a new revision available at:
http://www.kinzers.com/don/BX24