When the Raspberry Pi Pico runs with two cores, vital resources must be protected by semaphores (Mutual Exclusion). This examples uses Peterson’s algorithm, which is rather simple for two threads / cores.
Note: The semaphore variables and the housekeeping variables are set up as ‘volatile’. This turned out to be necessary for the code to work.
References:
[1] https://wiki2.org/en/Peterson%27s_algorithm
[2] https://stackoverflow.com/questions/3896952/testing-a-semaphore-by-counting/a>
/* * Implementation of Peterson's Algorithm * See: https://wiki2.org/en/Peterson%27s_algorithm */ /* * Semaphore variables */ volatile uint8_t flags[2] = {false, false}; volatile uint8_t turn = 0; /* * Housekeeping variables */ volatile uint8_t core0 = 0; volatile uint8_t core1 = 0; long errors = 0L; /* * Test variable */ volatile long shared = 0L; void inc() { shared++; } void dec() { shared--; } void setup() { uint8_t i; Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } } void setup1() { delay(1); } void loop() { long i; Serial.println( "Starting Peterson test loop ..." ); for (i = 0L; i < 10000000L; i++) { flags[0] = true; turn = 1; while( (flags[1] == true) && (turn == 1) ) { // busy wait ; } /* Critical Section Code of the Process */ // prevent compiler from doing optimizations inc(); dec(); /* End of Critical Section */ flags[0] = false; //Serial.print( "." ); } // wait until core 1 is finished while (core1 != 1) { Serial.println("Waiting for core 1 to finish ..."); delay(100); } if (core1 == 1) { Serial.println("core 1 finished!"); delay(1000); } if (shared != 0L) { errors++; } Serial.print( "shared = " ); Serial.print( shared ); Serial.print( " (errors = " ); Serial.print( errors ); Serial.println( ")" ); // start all over shared = 0L; // indicate core 0 has finished the main loop and check core0 = 1; delay(1000); core0 = 0; } void loop1() { long i; for (i = 0L; i < 10000000L; i++) { flags[1] = true; turn = 0; while( (flags[0] == true) && (turn == 0) ) { // busy wait ; } /* Critical Section Code of the Process */ // prevent compiler from doing optimizations inc(); dec(); /* End of Critical Section */ flags[1] = false; } // indicate core 1 has finished the main loop core1 = 1; // wait until core 0 has finished the main loop plus check while (core0 != 1) { delay(1); } // start all over core1 = 0; } // start all over shared = 0L; // indicate core 0 has finished the main loop and check core0 = 1; delay(1000); core0 = 0; }