The Propeller chip has eight processors, called cores or cogs, numbered 0 through 7. In all of our example programs, the main function automatically launches into cog 0. Many Propeller C libraries automatically launch other cogs to handle tasks for you, behind the scenes. You can also write your own function and launch it to run in another cog using cog_run.
The example below shows the simplest use of the cog_run function. Here, the main routine running in cog 0 executes the cog_run function call, causing the blink function to run in cog 1.
The cog_run function itself needs two parameters:
While learning or prototyping in multicore you should always set more stack space aside than you think you will be using. In this example we use a stackSize of 128, but our small program doesn't actually use it. This way, we have room to grow our code without worrying about running out of memory.
A function launched with cog_run:
So, let's try it!
We'll use the Activity Board's (original or WX version) built-in LEDs on P26 and P27. See the Blink a Light [1]tutorial for a schematic if you are using a different board.
After including the simpletools.h library, there is a forward declaration for the blink function. Since the blink function definition is below the main function, this lets the compiler know to expect it.
#include "simpletools.h" // Library include void blink(); // Forward declaration
Inside the main routine is just one statement: cog_run(blink, 128). This launches the function defined at address blink. It also provides a stack space of 128 32-bit memory locations used for performing calculations while executing the instructions in the blink code block.
int main() // Main function { cog_run(blink, 128); // Run blink in other cog }
Below the main routine is the blink function itself, written to be launched into another cog without any fuss. Note that it has an empty parameter list and void return type. Its code block is entirely inside a while(1) loop, so it will keep on blinking that P26 LED until the power shuts off. If those four instructions were not in a loop, they would execute just once and the cog would shut down, but without releasing its resources. This would make the cog and its stack space unavailable for other uses afterward.
void blink() // Blink function for other cog { while(1) // Endless loop for other cog { high(26); // P26 LED on pause(100); // ...for 0.1 seconds low(26); // P26 LED off pause(100); // ...for 0.1 seconds } }
Stack Size - how much? 10 is the bare minimum value you would want to use for the stackSize parameter. If you were to add more instructions to the blink function's code block, you would need to increase it. Add 1 for every local variable used, 2 for each function called, and 1 for each parameter and each return value used by the functions called.
Print from one cog at a time, please! Print, scan and other functions that interact with the SimpleIDE Terminal can only run in one cog at a time. Usually, it is most convenient to call print and other such functions from the main routine, even if they need to print values updated by other cogs, as we do in this example. But, if you want to, you can Print from a Different Cog as well, as that lesson will show you.
Let’s expand the example program so that it blinks the P27 LED at a different rate, using another cog. The process is fairly simple: just add a second function and pass it to cog_run. You will need a second forward declaration for that function, and also a second cog pointer for shutting the cog back down.
Okay, so blinking two LEDs doesn't seem so amazing. Yet, notice that one LED blinks on/off every 100 ms, and the other blinks on/off every 223 ms. Now, can you imagine writing code to do that from a single processor? Imagine that the on times were different from the off times for each LED. And then imagine adding six more LEDs, each with unique on and off times. The math would get complicated very quickly. This example is simple, but it shows how multi-processing can make a group of timing-sensitive tasks easier to do.
Just to prove that three cogs are really running different processes at the same time, let's have the original cog do something more than launch the other two cogs.
Links
[1] https://learn.parallax.com/propeller-c-simple-circuits/blink-light