Introduction #
Code for the Propeller 2 (whether written in the native SPIN2, C or other high level language), can usually benefit from a bit of PASM2 (assembly code) to help create super-fast drivers for real world interfacing!
That PASM2 code can be inserted "inline" within a regular block of SPIN2 code, running in one cog together. Or... we can start some super fast PASM2 code in it's own cog, and give it full real-time performance.
The Propeller 2 has 8 independent cogs (processor cores); each with access to the same hub (global memory). We often want to share values stored in that memory between the independent cogs.
This tip presents a simple way to share global hub variables between both (or multiple) cogs that are running in real-time!
SPIN2 Code Explanation #
The important configuration is achieved within these two blocks.
VAR { global variable definitions }
long PARAM[PARAM_COUNT]
CON { index constants }
#0, ID, AGE, AUTHCODE, PARAM_COUNT
The VAR block defines the name of the global variable, and whilst I've called it "PARAM", that name is your choice! As your projects grow you'll probably want to exchange data with more cogs, and so here you can define multiple PARAM blocks; however many you need.
The CON block defines the elements in your PARAM array. In this example we have "ID", "AGE", and "AUTHCODE". You can use names that are appropriate for your project, and you can have as many, or as few, as you need.
The one important condition, is to have the "PARAM_COUNT" element last on the list. This is essential for the VAR block to know how many elements you have, and ensure the VAR block can reserve enough memory for them. The name "PARAM_COUNT" should match your VAR name that is holding the values for these elements, plus the _COUNT suffix. Hence in this example, PARAM_COUNT.
coginit(COGEXEC_NEW, @ENTRY, @PARAM)
Within the SPIN2 code "Main()" function, you will find the coginit command. This starts the PASM2 code in it's own cog, and passes it a reference to the global variable @PARAM. (The @ symbol is included so that the code passes the memory address of PARAM).
repeat
debug( udec(PARAM[ID]), udec(PARAM[AGE]), udec(PARAM[AUTHCODE]) )
After setting up the code, a repeat loop simply displays the values of each PARAM element in the debug console. This shows that as the PASM2 Cog changes the values, that the SPIN2 Cog sees the changes.
PARAM[AGE]++
As we have demonstrated here by incrementing the AGE value periodically, you could also write to any of the PARAM variables from your SPIN2 Cog, and the PASM2 Cog would also see the changes. It's two way communication !
PASM2 Code Explanation #
rdlong i, ptra[ID] ' Read the ID value (from HUB memory)
add i, #1 ' Increment by 1
wrlong i, ptra[ID] ' Save the value (to HUB memory)
Within the PASM2 Cog you will see it uses a special assembly language command "ptra" to address the global memory. We can use the same CONstant keywords previously defined, so it's really easy to be sure you are reading and writing from the correct element!
To read a value from global hub memory we use the rdlong command. To write back to global hub memory we use the wrlong command. The address given in the example above is ptra[ID], so in this case we are reading the global ID value, adding a 1 to the number, and then writing it back again.
The debug console shows the result of this operation, both in the SPIN2 Cog0 and the PASM2 Cog1.
A complete demo can be found at the OBEX link below.