The previous lesson showed you how to make functions share global variables. Now, let's try making two functions run in different Propeller cores, also called cogs, and exchange information through those global variables.
This next example program launches the adder function into another cog. The adder function has been modified so that it keeps on adding 1 to the global n variable every 20th of a second.
The main function monitors the adder activity in that other cog by repeatedly displaying the value of the global n variable. The adder function changes n 20 times-per-second, so the main function will display a new value each time through its loop even though it doesn't actually do anything to n.
/* Multicore Example.c Launch a function into another cog (processor) and display what it does to the global n variable over time. */ #include "simpletools.h" // Include simpletools void adder(void *par); // Forward declaration static volatile int t, n; // Global vars for cogs to share unsigned int stack[40 + 25]; // Stack vars for other cog int main() // main function { t = 50; // Set values of t & n n = 5000; // Launch adder function into another cog (processor). cogstart(adder, NULL, stack, sizeof(stack)); // Watch what the other cog is doing to the value of n. while(1) { print("n = %d\n", n); // Display result pause(100); // Wait 1/10 of a second } } // Function that can continue on its // own if launched into another cog. void adder(void *par) // adder keeps going on its own { while(1) // Endless loop { n = n + 1; // n + 1 each time loop repeats pause(t); // Wait for t ms between updates } }
Cog 0 starts at the beginning of main, setting the values of t and n.
Next, cog 0 passes the memory address of the adder function along with some other details, to a function called cogstart. (It's part of the propeller library, which simpletools includes.) cogstart uses that information to make the next available cog (cog 1) start executing code in the adder function.
At this point, two cogs are executing different parts of the program. Cog 0 moves on to start repeating the while(1) loop in the main function and cog 1 starts executing the while loop in the adder function. Cog 1 updates the value of n every 50 ms because t = 50 and adder's while loop has pause(t). Meanwhile, cog 0 checks the value of n every 100 ms and displays the value with print. Since cog 0 is checking more slowly than cog 1 is updating, the value of n it displays increases by about 2 every time.
After the cogstart call, the adder function starts running in another cog. Meanwhile, the code in the first cog continues onward into the main function's while(1) loop.
From this example, we can see the general steps for setting up multicore code, for large or compact memory models (LMM or CMM):
NOTE: You can get the address of either a function or an array by just using its name. So, adder( ) calls the function, but adder returns the function's address in memory. Likewise, stack[0] returns the value of the stack array's zeroth element, but stack returns the array's address in memory.
LMM & CMM — This is an example of launching either large memory model (LMM) or compact memory model (CMM) code into another cog. These memory models fetch machine codes (numbers that represent your program) from the Propeller chip's 32 KB main RAM, and code running in the cog processes them.
COGC & PASM — (memory models) There are other, higher performance options such as COGC (C that fits entirely inside a cog) and PASM (Propeller Assembly Language). Code for both of these types of programs get loaded into a cog's 2 KB of memory, which increases execution speed because the cog doesn't have to wait for its turn to access main RAM and grab machine codes.
More on Memory Models — Additional examples and more memory model options can be found in the Propeller GCC Demos folder.
Let's find out which cog the cogstart function launches the adder function into.
Add a subtracter function to the project and launch it into a third cog. Make subtracter decrement a new global variable with the same initial value as n, repeating every t ms. Display the changing values of both variables.