The last lesson showed you how to launch a function in another core with cog_run. Now, let's use its counterpart cog_end to stop the launched function.
Circuit
We'll keep using the Activity Board's (original or WX version) built-in LEDs on P26 and P27. See the Blink a Light tutorial for a schematic if you are using a different board.
Test Code
- Click SimpleIDE’s Open Project button.
- Open Cog End Example.spin from ...Documents\SimpleIDE\Learn\Examples\Multicore.
- Click the Load RAM & Run button.
- Verify that the P26 LED blinks for 3 seconds, then stops.
How it Works
First, the simpletools library is included to give us access to cog_run and cog_end, along with other functions. Next is the forward declaration for the blink function, which is defined below the main routine.
/* Cog End Example.c */ #include "simpletools.h" // Library include void blink(); // Forward declaration
The cog_run function provides a return value. In this example, a local variable is declared with int *cog = in front of cog_run(&blink, 128); to capture it. The asterisk * indicates cog is a pointer, meaning that the value it holds is actually the address of a memory location. This is the place where the cog_run function call set aside stack space and recorded the ID number of the core it launched.
int main() // Main function { int *cog = cog_run(blink, 128); // Run blink in other cog
Next, pause(3000) makes the main routine idle for 3 seconds. Meanwhile, the P26 LED is blinking since the blink function is being executed by another core. Next comes the function call cog_end(cog); The cog_end function's parameter uses the cog_run's return value cog. Remember that cog is the memory address that stores the ID number of the core that was launched. So, cog_end can use the address get the ID number and shut the cog down.
pause(3000); // Wait while other cog blinks LED cog_end(cog); // Stop other cog }
The blink function itself is below the main routine. Even though its code block is inside a while(1) loop, it is not executed infinitely. That is because the core running blink was shut down by the cog_end function call made by the core running the main routine.
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 } }
Did You Know?
Always Recycle your Cores! — Always use cog_end to shut down a function that is no longer needed, whether or not it is using a while(1) loop. This frees up the core and stack space for re-use by another cog_run function call later in the program, and prevents unexpected results.
Keep it local, save a few bytes — The technique above, where *cog is declared locally and used by cog_end within the same function (in this case the main function), uses fewer bytes than declaring *cog globally.
Go global and delegate — Delcaring *cog globally allows it to be used with cog_end by any function in the application, including those running in other cores. It costs a few bytes more of code size, but frees the main routine from the task (a great advantage of multiprocessing).
Try This
As mentioned above, the *cog pointer can be declared globally, allowing it to be used with cog_end by any function in the application. You can put cog_end right inside the blink function, so the core running that code can shut itself down.
- Click Save Project As, rename the project, and save it to …Documents\SimpleIDE\My Projects.
- Add a line to declare *cog globally, above the main routine.
- In main, modify the cog_run call so that it stores its return value in the cog variable.. Be sure to comment out or delete the pause and cog_end function calls in the main routine.
- In the blink function, change the while(1) loop to a for loop, as shown below.
- Add the cog_end function call to blink, so the core can shut itself down when the for loop is done.
Your Turn
So far, we have tried shutting down a core from the main routine, and having a core shut itself down. Now, let's launch two cores, and have one shut down both itself and the other.
- Write a blink2 function that blinks the P27 LED on/off every 53 ms in an endless while(1) loop.
- Above the main routine, add a forward declaration for blink2, and declare a global pointer *cog2 to use with it.
- In the main routine, launch the blink2 function in a new core, and store the cog_run function's return value in cog2.
- In the blink function, add another cog_end function call to shut down the core runing the blink2 function.
- Run your code and see if it works: both the P26 and P27 LEDs should blink for about 3 seconds, and then shut down at almost the same time.
Did it work? Hint: if your P27 LED didn't stop blinking, take a look at the two cog_end calls in your blink function. Which one is executed first?