Hi, this is my first post on the Arduino forums. Thanks a lot to the Arduino community. You have helped me solve a lot of bugs.
As I understand it the RP2040 chip has a dual core processor. My question is, when I start a second thread using the mbed library, will it automatically make use of the second core?
I have looked at how to explicitly run code on the second core. The earlephilhower implementation (GitHub - earlephilhower/arduino-pico: Raspberry Pi Pico Arduino core, for all RP2040 boards) seems popular for this, but I haven't tested it. I am busy with a work project, so I don't want to stray from the official arduino core. I have tried running the second core using the pi pico SDK (Raspberry Pi Pico SDK: pico_multicore). I managed to get code running on the second core that way, but for some reason I wasn't able to print to serial from that core and if I tried to access millis() the board would crash. I don't know if I was just missing something.
Just running my code in a second thread, even if it only runs on one core, should be sufficient for what I need to do. I was just trying to see if I can increase the speed of operations. I am posting this out of curiosity and some frustration because I wasn't able to run the code properly on the second core
I prefer to use the most common things and not to run off into tangled balls of barbed wires.
The official Arduino software layer for the Raspberry Pi Pico is on top of Mbed.
Arduino has a simple Scheduler for SAMD21G ARM M0+ processors: https://www.arduino.cc/en/reference/scheduler.
It can change to an other task when a task calls delay(). It works well, because it is so simple.
That Scheduler is ported to the Raspberry Pi Pico using Mbed function and then the simple Scheduler suddenly becomes a pre-emptive task switcher.
One step further is using Mbed together with Arduino code. That will work very well if the Arduino layer is used as a base. Add a import and then you can use it.
There are some notes here: https://github.com/arduino/ArduinoCore-mbed/releases/tag/2.0.0
I have used it, but I forgot where I found the right information and I forgot how the FIFO between the cores is implemented in Mbed
I have some doubts about your project and the two cores. If your code is okay, then you probably will not notice the difference with multiple tasks on a single core, or with tasks divided over two cores. The Mbed layer is that good.
What special case do you have that needs two cores ?
Tip: Did you know that the Wokwi simulation has a Raspberry Pi Pico ?
Not the full hardware is supported. Since it is simulated at hardware level, both Mbed and Arduino can be used.
I very much doubt it, as the code won't have been written to know about the multiple cores of the RP2040. However, if you have two separate tasks that need to share data then this is ideal for the RP2040 multiple cores. By way of example, I have a project that receives audio data over USB (data acquisition and management) on one core and then sends that data to the other core for signal processing (performance-critical maths).
This is done on MBED exactly as would be done in the SDK
you write a function to run on the second core (e.g. core1_worker()).
The project is a hydrofoil system with active foil angle control. I have time critical tasks, reading data from sensors then calculating and setting actuator position, then I have all my other tasks which as long as they are executed reliably it doesn't matter that much how long they take, those being bluetooth coms, getting gps data and datalogging to an sd.
The idea was to have all the time critical tasks running on one core and everything else on the other core. I'm now just running those tasks in loop() and another thread:
#include <mbed.h>
using namespace mbed;
using namespace rtos;
Thread thread;
thread.start(MyFunction);
That seems to be taking care of all my needs, but I still need to do some testing. If I do have issues with execution time there is probably a lot of optimization I can still do. The cool factor of using both cores was also very alluring.
you write a function to run on the second core (e.g. core1_worker()).
That is the method I tried using to run the second core, but I had some problems like I said. I will take a look at what you did and see where I went wrong.
Thanks for all the input and resources shared from everyone. I definitely learned some stuff
Glad to hear there is ongoing development, because I think the new range of nano boards running mbed OS are pretty cool.
It may be that many functions aren't safe to call from the second core. I would stick to pico functions in the second core as much as possible. As for serial, you may need to declare the serial object in the void core1_worker function so that that core knows about the serial object.
Hello all.
I was interested in this issue. Just for info I've done this MultipleBlink_multicore.ino from the MultipleBlink.ino using Scheduler.h library on core0 and using the MBED core 'mixed' with the pico/multicore.h just for core1.
It looks working with some (sensible) limitations:
no delay(), neither Serial.print etc.... can be called on core1. Only sleep_ms or pico sleep_... funcs on core1 for delays.
/*
Multiple Blinks
Demonstrates the use of the Scheduler library for the boards:
- Arduino Nano 33 BLE, or
- Arduino Portenta H7, or
- Arduino Nano RP2040 Connect
Hardware required :
* None (LEDs are already conencted to RGB LED)
ATTENTION: LEDs polarity is reversed (so loop3 will turn the LED off by writing 1)
created 8 Oct 2012
by Cristian Maglie
Modified by
Scott Fitzgerald 19 Oct 2012
This example code is in the public domain
http://www.arduino.cc/en/Tutorial/MultipleBlinks
*/
// Include Scheduler since we want to manage multiple tasks.
#include <Scheduler.h>
// Include pico/multicore.h to run core1 function
// NB: no delay(), neither Serial.print etc.... can be called on core1. Only sleep_ms or pico sleep_... funcs
#include "pico/multicore.h"
// On Nano RP2040 Connect, RGB leds are connected to the wifi module
// The user APIs are the same, but we can't convert to int, so use defines
#if defined(ARDUINO_NANO_RP2040_CONNECT)
#include "WiFiNINA.h"
#define led1 LEDR
#define led2 LEDG
#define led3 LEDB
// On Nicla Sense ME, RGB leds are connected via an I2C module
// The user APIs are the same, but we can't convert to int, so use defines
#elif defined(ARDUINO_NICLA)
#include "Nicla_System.h"
#define led1 LEDR
#define led2 LEDG
#define led3 LEDB
#else
int led1 = LEDR;
int led2 = LEDG;
int led3 = LEDB;
#endif
void setup() {
Serial.begin(9600);
// initialize digital pin LED_BUILTIN as an output.
// Setup the 3 pins as OUTPUT
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
// Add "loop2" and "loop3" to scheduling.
// "loop" is always started by default.
Scheduler.startLoop(loop2);
Scheduler.startLoop(loop3);
multicore_launch_core1(core1_entry);
}
void core1_entry() {
pinMode(LED_BUILTIN, OUTPUT);
while(true)
{
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
sleep_ms(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
sleep_ms(1000);
}
}
// Task no.1: blink LED with 1 second delay.
void loop() {
digitalWrite(led1, HIGH);
// IMPORTANT:
// When multiple tasks are running 'delay' passes control to
// other tasks while waiting and guarantees they get executed.
Serial.println("Red On");
delay(1000);
digitalWrite(led1, LOW);
Serial.println("Red Off");
delay(1000);
}
// Task no.2: blink LED with 0.1 second delay.
void loop2() {
digitalWrite(led2, HIGH);
delay(100);
digitalWrite(led2, LOW);
delay(100);
}
// Task no.3: accept commands from Serial port
// '0' turns off LED
// '1' turns on LED
void loop3() {
if (Serial.available()) {
char c = Serial.read();
if (c == '0') {
digitalWrite(led3, LOW);
Serial.println("Led turned off!");
}
if (c == '1') {
digitalWrite(led3, HIGH);
Serial.println("Led turned on!");
}
}
// IMPORTANT:
// We must call 'yield' at a regular basis to pass
// control to other tasks.
yield();
}
The problem is now to handle an inter-core communication with no not-atomic violation for multibyte variables. This is something to keep working on. Perhaps the pico FIFO's work. I'll try that.
Not bad anyway IMHO for the time being as a start.