Stopping Cores

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?