Page 139 of 229 Start Back Next End ZBasic Language Reference 129 ZBasic Microcontrollers 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. 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 application’s 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 task’s stack. Based on the results of this observation, you may choose to increase or decrease the size of that task’s 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. #pragma StackUse( <stack-depth> ) An alternate syntax that can be used outside of all procedures, but not for ISRs, is shown below. #pragma StackUse( <procedure-name>, <stack-depth> ) The recommended method used to generate an estimate of the stack use is to examine the assembly listing file generated by the compiler in response to the –-list option (which also requires the –-keep-