The Propeller P8X32A supports:
Note 1: Spin or Propeller Assembly.
Note 2: Propeller Assembly only.
In Spin there are two types of variables, global and local, and each is defined differently.
All global variables are defined in VAR blocks. They can be of type byte, word, or long as shown below.
VAR long Time, Counter word Index byte State
Local variables are defined in the declaration of the PUB or PRI method that will use them. They are always of type long. X, Y, and Z (below) are local long variables, but so are the parameters Param1 and Param2.
PUB MethodName(Param1, Param2) | X, Y, Z
In Propeller Assembly, all variables are global and are usually declared immediately after the assembly code that uses them. They should always be defined as initialized longs or as reserved longs.
DAT
AsmCode org 0
{some more code here}
Delay long $80_000_000
Address res 1
ID res 1
Note that variables (symbols) defined as initialized longs in a DAT block are a special kind of global variable; they are treated differently at compile time in that only one instance exists regardless of the number of instances of that object in the application.
Global variables are declared with a VAR declaration, and are available for use by all the methods within that object. Local variables are declared in a PUB or PRI method declaration, must have unique names compared to global variables, and can only be used in the method in which they are defined. All global and local Spin variables exist in Main RAM, not in Cog RAM.
Other differences between local and global variables have to do with variable size and initialization:
In Spin, all global variables (those defined in VAR blocks) are initialized to 0. In addition, each time a method is called, its default local variable (result) is initialized to 0. Every other local variable is left uninitialized unless it is part of the parameter list, in which case it is filled by the passed parameter value.
In Propeller Assembly, all declared long symbols are initialized to whatever is specified by the declaration. All reserved (res) symbols are left uninitialized.
Though it is very rarely implemented, it is possible to update the global variable area of the application image residing in the external EEPROM so that one or more global variables are initialized to a non-zero value upon the next boot up. This can only be done via code that manually interfaces to the EEPROM.
Access time depends on variable type and order of declaration.
For global variables, the first eight long-sized variables are addressed using an optimized encoding scheme. This makes accessing them slightly faster than with the ninth, or later, long variables. Word and byte-sized variables have no optimized encoding; they take the same amount of time as the ninth, or later, global long variables.
For local variables, the first eight that make up a method's parameters, its RESULT variable, and its local variables are addressed using an optimized encoding scheme. This makes accessing them slightly faster than with the ninth, or later, local variables.
Access time for elements of an array variable is slightly slower than that of a single-element variable because the element offset is evaluated at run-time.
Direct access to main memory with BYTE[], WORD[], and LONG[] is slightly slower than with a defined symbol (ie: a symbol in a DAT block).
At compile time, a copy of the object's VAR and OBJ blocks is made for each instance of the object. These copies are inserted into the application image along with all other workspace for global variables and objects.
This way, each object instance gets its own global variable memory and subobjects, yet each always uses the same code and data (PUB, PRI, and DAT), and of course, constants (CON).
Everything in an object's DAT blocks is available to the object and every instance of that object. DAT-based symbols behave like global variables except that there is only one instance of them; every instance of an object uses the same instance of DAT symbols. This means that if an instance of an object changes the value in a DAT symbol, that value changes for all other instances of that object as well.
The DAT block's primary purpose is to hold fixed data and Propeller Assembly code for the application. Symbolic declarations can be included and used to reference this data and code.
There's nothing preventing the contents of DAT from being modified at runtime, however, which naturally leads to its use to hold symbols as "special" variables. Their special attributes relate to how they are stored in the application and how they are treated by Spin and when launching Propeller Assembly code.
DAT blocks are stored in the application image in Main RAM. Just like code (PUB and PRI), there is only one instance of each DAT block, regardless of how many instances of the containing object there are. This means that Spin-based references to DAT symbols are accessing the corresponding location and data in Main RAM, and it's the same regardless of which instance of that object is making the reference. This is handy to share memory between multiple instances of an object.
When a cog is launched with assembly code, any DAT symbols within 496 longs after the launch point are copied into Cog RAM. Unlike with Spin code, Propeller Assembly code that references those symbols is not accessing the corresponding location and data in Main RAM, but rather it is accessing the corresponding Cog RAM instead; its local copy. In addition, those symbolic references are always to longs of Cog RAM memory, regardless of how the symbol was actually declared. In Propeller Assembly, no Main RAM references can be made by simply using the declared symbolic name; instead, the address of that symbol must be passed from the Spin object and used along with instructions like RDLONG and WRLONG.
Yes (in Spin) and No (in Propeller Assembly).
The Spin Interpreter implements a call stack to facilitate Spin method calling, parameter passing, and expression evaluation. The Propeller Application's stack is located in Main RAM immediately following the application's global variable memory. It expands and collapses as needed; growing towards higher addresses and shrinking towards lower addresses. Spin methods that are manually launched into other cogs store their stack starting at the StackPointer address given by the COGNEW or COGINIT command that launched them. Their stacks expand and contract in the same manner as with the Propeller Application stack. In both cases, the capacity of the stack (method nesting-depth, parameter list length, and expression complexity) is limited only by the amount of free memory available (for the application) or memory provided (by the developer).
Propeller Assembly language does not implement a call stack since doing so would unnecessarily consume valuable memory and impose undue limitations on applications. Instead, Propeller Assembly provides a different mechanism through the JMPRET instruction (and also CALL, JMP, and RET) to maintain nested call history. This method requires more developer influence but allows the memory to be used more efficiently (optimizing for the specific application) and has a distinct advantage allowing the implementation of simple task-switching code in real-time systems using JMPRET.
To determine the amount of space required by your object, see Stack Space.
Propeller P8X32A Questions & Answers
Copyright © Parallax Inc., dba Parallax Semiconductor
Version 1.3.1
10/23/2013