Multicore on Raspberry Pi Pico

Hi all,

I'm programming a Raspberry Pi Pico with the new Arudino Core and would like to be able to use the RP2040's multi-core functionality.

Has anyone had any success getting this to work? The official RP2040 C++ SDK makes it look very easy. I have followed the example code shown here:

https://datasheets.raspberrypi.org/pico/raspberry-pi-pico-c-sdk.pdf#page=194

However, because I'm compiling with the Arduino Core, a lot of the SDK is missing and this doesn't compile as it can't find the headers. I dug into the ArduinoCore folder and added the missing parts of the SDK one by one based on what the compiler said was missing after each compile attempt:

C:\Users\AlexStewart\AppData\Local\Arduino15\packages\arduino\hardware\mbed_rp2040\2.0.0\cores\arduino\mbed\targets\TARGET_RASPBERRYPI\TARGET_RP2040\pico-sdk

I also modified the following file so that the compiler can find the newly included parts of the SDK:

C:\Users\AlexStewart\AppData\Local\Arduino15\packages\arduino\hardware\mbed_rp2040\2.0.0\variants\RASPBERRY_PI_PICO\includes.txt

-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_multicore
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_multicore/include
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_multicore/include/pico

-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/hardware_divider
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/hardware_divider/include
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/hardware_divider/include/hardware

-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_stdio
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_stdio/include
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_stdio/include/pico
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_stdio/include/pico/stdio

-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_malloc
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_malloc/include
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_malloc/include/pico

-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_mem_ops
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_mem_ops/include
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_mem_ops/include/pico

-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_printf
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_printf/include
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_printf/include/pico

-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_stdio_semihosting
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_stdio_semihosting/include
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_stdio_semihosting/include/pico

-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_stdio_uart
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_stdio_uart/include
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_stdio_uart/include/pico

-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_stdio_usb
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_stdio_usb/include
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_stdio_usb/include/pico
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_stdio_usb/include/pico/stdio_usb

-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_unique_id
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_unique_id/Include
-iwithprefixbefore/mbed/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_unique_id/include/pico

-iwithprefixbefore/mbed/libs/tinyusb/src

I was hoping this would work but now I am faced with the following error:

Generating function prototypes...
"C:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\arm-none-eabi-gcc\\7-2017q4/bin/arm-none-eabi-g++" -c -w -g3 -nostdlib "@C:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\variants\\RASPBERRY_PI_PICO/defines.txt" "@C:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\variants\\RASPBERRY_PI_PICO/cxxflags.txt" -DARDUINO_ARCH_RP2040 -mcpu=cortex-m0plus -w -x c++ -E -CC -DARDUINO=10607 -DARDUINO_RASPBERRY_PI_PICO -DARDUINO_ARCH_MBED_RP2040 -DARDUINO_ARCH_MBED -DARDUINO_LIBRARY_DISCOVERY_PHASE=1 "-IC:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\cores\\arduino" "-IC:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\variants\\RASPBERRY_PI_PICO" "-IC:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\libraries\\SPI" "-IC:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\libraries\\Wire" "-IC:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\cores\\arduino/api/deprecated" "-IC:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\cores\\arduino/api/deprecated-avr-comp" "-iprefixC:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\cores\\arduino" "@C:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\variants\\RASPBERRY_PI_PICO/includes.txt" "C:\\Users\\ALEXST~1\\AppData\\Local\\Temp\\arduino-sketch-4087D06F8A8419D4493F714B6F85855D\\sketch\\2021_AURA_Front_Lamp.ino.cpp" -o "C:\\Users\\ALEXST~1\\AppData\\Local\\Temp\\arduino-sketch-4087D06F8A8419D4493F714B6F85855D\\preproc\\ctags_target_for_gcc_minus_e.cpp"
"C:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\builtin\\tools\\ctags\\5.8-arduino11/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "C:\\Users\\ALEXST~1\\AppData\\Local\\Temp\\arduino-sketch-4087D06F8A8419D4493F714B6F85855D\\preproc\\ctags_target_for_gcc_minus_e.cpp"
Compiling sketch...
"C:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\arm-none-eabi-gcc\\7-2017q4/bin/arm-none-eabi-g++" -c -Wall -Wextra -g3 -nostdlib "@C:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\variants\\RASPBERRY_PI_PICO/defines.txt" "@C:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\variants\\RASPBERRY_PI_PICO/cxxflags.txt" -DARDUINO_ARCH_RP2040 -MMD -mcpu=cortex-m0plus -DARDUINO=10607 -DARDUINO_RASPBERRY_PI_PICO -DARDUINO_ARCH_MBED_RP2040 -DARDUINO_ARCH_MBED -DARDUINO_LIBRARY_DISCOVERY_PHASE=0 "-IC:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\cores\\arduino" "-IC:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\variants\\RASPBERRY_PI_PICO" "-IC:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\libraries\\SPI" "-IC:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\libraries\\Wire" "-IC:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\cores\\arduino/api/deprecated" "-IC:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\cores\\arduino/api/deprecated-avr-comp" "-iprefixC:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\cores\\arduino" "@C:\\Users\\AlexStewart\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\mbed_rp2040\\2.0.0\\variants\\RASPBERRY_PI_PICO/includes.txt" "C:\\Users\\ALEXST~1\\AppData\\Local\\Temp\\arduino-sketch-4087D06F8A8419D4493F714B6F85855D\\sketch\\2021_AURA_Front_Lamp.ino.cpp" -o "C:\\Users\\ALEXST~1\\AppData\\Local\\Temp\\arduino-sketch-4087D06F8A8419D4493F714B6F85855D\\sketch\\2021_AURA_Front_Lamp.ino.cpp.o"
arm-none-eabi-g++: error: CreateProcess: No such file or directory

I could very well be going around this all wrong, I'm not sure. Does anyone have any ideas how I might be able to use the multicore function whilst remaining in the Arduino world? I have lots of code which is dependant on Arduino libraries so I can't easily jump to working in straight C++.

Cheers,

Has anyone managed to get multicore working using the Arduino Core?

do you realize a raspberry pico uses an ARM processor not an atmel microcontroller used on Arduinos?

is there a raspberry forum?

Hi gcjr, yes I am aware that the Pico uses a new ARM M0+ based RP2040 microprocessor, and that the new ArduinoCore supporting it is based on the Arm Mbed OS. The forums on Raspberry Pi are all focused on the standard RP2040 SDK (straight C++, no Arduino library compatibility), within which they have a multicore library which is very easy to use.

However, this part of the SDK has not yet been incorporated into the ArduinoCore (because until now no Arduino product has had multiple cores). The SDK library is there, but I'm hoping someone might have knowledge of how I can incorporate it into my Arduino sketches, because just grabbing the #includes is causing compilation errors

are you saying the Arduino IDE can support arduino-like (non-multitask) applications similar to the way it supports the esp32

Alex, as of last night I have my pico running dual core via Ardiuno IDE using Philhowers latest build of Arduino-Pico: GitHub - earlephilhower/arduino-pico: Raspberry Pi Pico Arduino core, for all RP2040 boards
Multicore Processing — Arduino-Pico 2.7.2 documentation

Here's the example he wrote in which I based my working test on:

Hi cems1, that's really interesting. I will investigate what it would take to use Philhowers core.

I was really hoping i'd be able to stay with the official Arduino core and just extend its functionality by bolting in the necissary parts of the SDK that enable multi-core, so that I can use the example code in the official SDK documentation.

The official implementation perfectly fits my requirments (full stop start control of core1, ability to load any function onto core1 based on decisions made by core0, etc).

Hi Alex,

You can try this code on Earle Philhower's arduino-pico core to see if it can fit your requirements.
I'm planning to write many new libraries (EthernetWebServer, WiFiWebServer, TimerInterrupt, WiFiManager, EthernetManager, etc.) to support RP2040, first on Philhowers core, then Arduino mbed core.

/*
  From (https://arduino-pico.readthedocs.io/en/latest/multicore.html)
  
  By adding a setup1() and loop1() function to your sketch you can make use of the second core. 
  Anything called from within the setup1() or loop1() routines will execute on the second core.

  Functions:
  1) Pausing Cores
  - void rp2040.idleOtherCore();
  - void rp2040.resumeOtherCore();

  2) Communicating Between Cores
  - void rp2040.fifo.push(uint32_t);
  - bool rp2040.fifo.push_nb(uint32_t);
  - bool rp2040.fifo.push_nb(uint32_t);
  - bool rp2040.fifo.pop_nb(uint32_t *dest);
  - int rp2040.fifo.available();
*/

#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/multicore.h"

#define FLAG_VALUE    0xDEADBEEF

void heartBeatPrint(bool isCore0 = true)
{
  static int num = 1;

  Serial.print(isCore0 ? F("C0") : F("C1") );

  if (num == 40)
  {
    Serial.println();
    num = 1;
  }
  else if (num++ % 10 == 0)
  {
    Serial.print(F(" "));
  }
}

void check_status(bool isCore0 = true)
{
  static unsigned long checkstatus_timeout = 0;

#define STATUS_CHECK_INTERVAL     10000L

  // Send status report every STATUS_REPORT_INTERVAL (60) seconds: we don't need to send updates frequently if there is no status change.
  if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0))
  {
    heartBeatPrint(isCore0);
    checkstatus_timeout = millis() + STATUS_CHECK_INTERVAL;
  }
}

//////////////////////////////////////////////

// Running on Core0

void setup()
{
  rp2040.idleOtherCore();

  Serial.begin(115200);
  while (!Serial);

  Serial.print("\nStart RPI_Pico_Multicore Core0 on ");
  Serial.println(BOARD_NAME);

  rp2040.resumeOtherCore();

  uint32_t g = rp2040.fifo.pop();

  rp2040.idleOtherCore();

  Serial.print("C0: rp2040_fifo_pop g = 0x");
  Serial.println(g, HEX);

  if (g == FLAG_VALUE)
  {
    rp2040.fifo.push(FLAG_VALUE);
    Serial.println("Core0 OK!");
  }
  else
    Serial.println("Core0 not OK!");

  rp2040.resumeOtherCore();
}

void loop()
{
  check_status(true);
}

//////////////////////////////////////////////

// Running on Core1

void core1_entry()
{
  rp2040.fifo.push(FLAG_VALUE);

  uint32_t g = rp2040.fifo.pop();

  rp2040.idleOtherCore();

  Serial.print("C1: rp2040_fifo_pop g = 0x");
  Serial.println(g, HEX);

  if (g == FLAG_VALUE)
    Serial.println("Core1 OK!");
  else
    Serial.println("Core1 not OK!");

  rp2040.resumeOtherCore();
}

void setup1()
{
  rp2040.idleOtherCore();

  Serial.begin(115200);
  while (!Serial);

  Serial.print("Start RPI_Pico_Multicore Core1 on ");
  Serial.println(BOARD_NAME);

  rp2040.resumeOtherCore();

  core1_entry();
}

void loop1()
{
  check_status(false);
}

//////////////////////////////////////////////

Terminal output

Start RPI_Pico_Multicore Core0 on RASPBERRY_PI_PICO
Start RPI_Pico_Multicore Core1 on RASPBERRY_PI_PICO
C0: rp2040_fifo_pop g = 0xDEADBEEF
Core0 OK!
C1: rp2040_fifo_pop g = 0xDEADBEEF
Core1 OK!
C1C0C1C0C1C0C1C0C0C1 C0C1C0C1C1C0C0C1C1C0 C1C0C1C0C1C0C1C0C1C0 C0C1C0C1C1C0C1C0C0C1
C1C0C1C0C1C0C0C1C1C0 C0C1C1C0C0C1C1C0C0C1 C1C0C0C1C0C1C1C0C0C1 C0C1C0C1C1C0C0C1C0C1
C0C1C1C0C1C0C1C0C1C0 C0C1C0C1C1C0C1C0C1C0 C1C0C1C0C0C1C1C0C1C0 C1C0C0C1C1C0C0C1C1C0
C1C0C1C0C0C1C1C0C1C0 C1C0C0C1C0C1C0C1C0C1 C0C1C1C0C1C0C0C1C0C1 C0C1C0C1C1C0C0C1C1C0
C1C0C1C0C1C0

How many cores does one get? Just the 2?

-jim lee

Sigh. I was hoping that "dual core support" was one of the motivations for using mBed instead of a bare-metal implementation, but it doesn't look like mBed currently supports multiple cores at all :frowning:

I always wanted an rPi that programmed like an Arduino.

void setup() {}

void loop() {}

-jim lee

Hmm: RP2040: include multicore library in build · ARMmbed/mbed-os@4f54781 · GitHub

Ah this looks promising! I put in a question into ArduinoCore Mbed yesterday, looks like
facchinm's picked up on it and put in a PR to mbedOS!

If you want really multicore totally independant running code you can use

a parallax propeller-chip 1 32 IO-Pins

or a Propeller-chip 2 (64 IO-pins

with both you can have any kind of peripheral interfaces like
I2C, SPI, onewire, UART, SD-Card in the number and combination that you want

example: 3 IC2 and five UARTS (each at 115200 baud) and 2 SPI

Huh? What? How many interfaces does this chip have?
They both have 8 independant running cores. Each core is able to build any interface you want in software.
C-compiler available. Assembler is 32bit where each and every command can be executed conditional to two flags or any combination of these two flags

The assembler-code is running in RAM which enables self-modifying code if you want without wearing out flash.

best regards Stefan

For anyone finding this thread, PICO-SDK libraries including multicore.h were added to the official ArduinoCore Mbed 2.1.0 release (17-05-2021).

Simply add #include <pico/multicore.h> at the top of your code. Run code on Core1 using:

multicore_launch_core1(myFunction);

Being able to access the second core is one thing, getting code to successfully run on it without it locking up the chip is another. Looks like most Arduino functions aren't thread safe, and will fall over when called. I'll be opening up a new thread to discuss these issues.

Cheers!

2 Likes

Not really looking for multi core. I just like massive amount of RAM and processor speed. Then being able to hook stuff to it like an Arduino. Would be fun to write code for something like that.

-jim lee

Teensy 4.1 600 MHz 1MB RAM

Been watching those. Also fits into all my 3D designs I use for the Teensy 3.2s

-jim lee

Arduino system was developed for small microcontrollers - multiprocessing was not a design requirement, most Arduino libraries will be blissfully unaware of mutexs and locking required to support it. If you treat one processor as I/O and the other as background processing you'll be most likely to succeed with existing Arduino model as the only mutexs/locking required will be for your code, not the I/O.

More to the point its fast for its clock speed (dual-issue so effectively 1.2GHz) and
has full hardware support for floats and doubles - this means its roughly 100 to 200
times faster than the Pico for floating point FFT calculations, for instance, and easily 10 times faster for integer stuff.

The principal selling point of the Pico is cost, much cheaper than Teensy LC for instance.