Here a queue is used to send a random int from loop0 which is running on core 1 to loop1 which is running on core 0. The blink routine runs on core 0 blinking the on board led and displaying free memory. You can modify the tasks to run on any core you desire, status is displayed on the serial monitor so you don't neccessarily need to connect the led's but they are nice to have. The main point is the demonstration of using a queue.
TaskHandle_t Task0;
TaskHandle_t Task1;
TaskHandle_t flash;
QueueHandle_t queue;
#define LED0 27
#define LED1 25
#define LED2 2
size_t xx=0;
size_t xPortGetFreeHeapSize( void );
void loop0(void * parameter) {
for (;;) {
// Use Arduino implementation for a number between limits
int rndNumber = random(1, 9);
Serial.print("\t\t\t\t\t\t\t\tLoop 0 - Running on core: ");
Serial.println(xPortGetCoreID());
// Add to the queue - wait forever until space is available
Serial.println("\t\t\t\t\tMgr 0 - Adding " + String(rndNumber) + " to queue");
xQueueSend(queue, &rndNumber, portMAX_DELAY);
// Artificial wait here
digitalWrite(LED0, HIGH);
delay(200);
digitalWrite(LED0, LOW);
delay(500);
}
}
void loop1(void * parameter) {
for (;;) {
// Get the number of flashes required
int flashTotal;
xQueueReceive(queue, &flashTotal, portMAX_DELAY);
Serial.print("\t\t\t\t\t\t\t\tLoop 1 - Running on core: ");
Serial.println(xPortGetCoreID());
Serial.println("Worker - reading " + String(flashTotal));
// Flash that number
for (int cnt = 0; cnt < flashTotal; cnt++) {
digitalWrite(LED1, HIGH);
delay(150);
digitalWrite(LED1, LOW);
delay(150);
}
}
}
void blink(void * parameter) {
for (;;) {
xx=xPortGetFreeHeapSize( );
Serial.println(xx);
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}
}
void setup()
{
Serial.begin(115200);
delay(1000);
Serial.println("Setup started.");
Serial.print("###");
int cpuSpeed = getCpuFrequencyMhz();
Serial.println(cpuSpeed);
pinMode(LED0, OUTPUT);
pinMode(LED1, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED2, HIGH);
// Create the queue with 5 slots of 2 bytes
queue = xQueueCreate(5, sizeof(int));
xTaskCreatePinnedToCore(
loop0, /* Function to implement the task */
"Task0", /* Name of the task */
1000, /* Stack size in words */
NULL, /* Task input parameter */
0, /* Priority of the task */
&Task0, /* Task handle. */
1); /* Core where the task should run */
xTaskCreatePinnedToCore(
loop1, /* Function to implement the task */
"Task1", /* Name of the task */
1000, /* Stack size in words */
NULL, /* Task input parameter */
0, /* Priority of the task */
&Task1, /* Task handle. */
0); /* Core where the task should run */
xTaskCreatePinnedToCore(
blink, /* Function to implement the task */
"flash", /* Name of the task */
1000, /* Stack size in words */
NULL, /* Task input parameter */
0, /* Priority of the task */
&flash, /* Task handle. */
0); /* Core where the task should run */
Serial.println("Setup completed.");
}
void loop()
{
Serial.println("Setup completed.");
vTaskDelete (NULL);
}
I don't recall where I got this from if I could I would credit the original programmer, I believe it was from a YouTube article
EDIT. I included the blink routine to see what effect "delay" had on the other tasks, from what I had read a delay in RTOS is automatically treated as a "millis" delay in other words you can use "delay" as non blocking code. If anyone can confirm or deny please let us know.