ZBasic Language Reference
135
ZBasic Microcontrollers
are normally dynamically allocated, i.e. they exist only
while the procedure is executing.
Volatile
variable
Instructs the compiler to not make any assumptions
about the content of the variable. This should be used
when another task or an ISR may be modifying the
variable.
ByteAlign
variable
Instructs the compiler to allocate the variable so that it
begins on a byte boundary. This is useful primarily for
the sub-byte types Bit and Nibble.
Raw
variable
Applicable only to initialized Program Memory data
items, this attribute tells the compiler to interpret the data
in the initialization file as raw (binary) data rather than as
textual data.
"PortPinEncoding:<val>"
variable
Applicable only to initialized Program Memory data
items, this attribute tells the compiler how to evaluate pin
constants (e.g. A.0). The <val> may be 0, Off, ¹ or
On; the first two result in a physical pin number while the
latter two result in an encoded port/pin designator.
Example
Dim index as Integer Attribute(Volatile)
Sub foo() Attribute(Used,Inline)
End Sub
6.6 Considerations for Task Stack Size
As of v2.5.6, the ZBasic compiler produces an estimate of the minimum size for a native mode
applications tasks. The estimate is produced by performing a static analysis of the generated native
code beginning with the entry point of each task (including the default Main() task). The static analysis
determines, if possible, the maximum stack depth assuming that all possible execution paths through the
code are followed. Additionally, each ISR (both user-provided and system-provided) is analyzed using
the same technique to determine the maximum stack depth it will use.
For each task, the required minimum task stack size is the sum of a) the maximum stack depth of the task
itself, b) the size of the Task Control Block, c) the stack margin (default or user specified) and d) the
largest of 1) the multi-tasking context size and 2) the stack depths of the individual ISRs. At the time of
this writing, the Task Control block size is 13 bytes, the multi-tasking context size is 37 bytes (38 on
ZBasic devices with more than 64K of Flash memory), the maximum stack depth of the system supplied
ISRs is less than 20 bytes and the default stack margin is 10 bytes. This leads to a typical task stack size
minimum that is the stack depth of the task itself plus 60 bytes (37 + 13 + 10) or 61 bytes (38 + 13 + 10).
The compiler outputs a list of the known tasks and the minimum task stack size for each to the .map file
that is produced each time a project is compiled (unless it is explicitly requested otherwise). In most
cases, the compiler stack depth estimation algorithm can successfully compute the maximum stack depth
but there are certain situations where the stack effect cannot be deduced by examining the code. When
this situation is encountered, the map file will list ??? as the minimum stack size in the task list
contained in the .map file for the related task. In this situation, there are two possible alternative
strategies. The first is to allocate a large task stack for the task in question, run the application (ensuring
that as many of the executions paths as possible are taken) and then using the System Library function
System.TaskHeadRoom() to determine how much unused space remains in that tasks stack. Based
on the results of this observation, you may choose to increase or decrease the size of that tasks stack.
The second option is to explicitly inform the compiler of the maximum stack depth for the routine or ISR
that contains the problematic code. This is done using the #pragma StackUse directive within the
particular procedure or ISR, the syntax of which is shown below.