freertos4core - FreeRTOS/Multithreading on the Core

Hey all!

If you’ve been following our recent releases, you’ll know that with the 0.4.6 release the Photon got multithreading support.

We didn’t want our Core users to feel left out of the Party, so we’ve started taking inroads to making the same available on the core.

The first step is to get FreeRTOS that we use on the Photon running on the Core. FreeRTOS is the Real Time Operating System which makes multithreading possible. With the 0.4.6 release on the Core, we put in some hooks to allow FreeRTOS to be added.

Since FreeRTOS does consume some flash memory and RAM, FreeRTOS support is provided as an optional library so you only pay for what you use. The library is called freertos4core - you’ll find it in the frozen section of your local IDE delicatessen. :smiley:

With FreeRTOS available, you can use all of the FreeRTOS API for creating threads, timers and other multithreading goodies.

Here’s a timer example to tempt you in:

#pragma SPARK_NO_PREPROCESSOR
/* Includes ------------------------------------------------------------------*/
#include "freertos4core/freertos4core.h"

TimerHandle_t timer;

void timerCallback(TimerHandle_t handle)
{
    static int count = 0;
    digitalWrite(D7, !digitalRead(D7));
    Serial.println(count++);
}

void createTimer()
{
    timer = xTimerCreate("timer", 500, true, NULL, timerCallback);
    xTimerStart(timer, 0);
}

/* This function is called once at start up ----------------------------------*/
void setup()
{
    Serial.begin(9600);
    pinMode(D7, OUTPUT);
    createTimer();
}

/* This function loops forever --------------------------------------------*/
void loop()
{
    delay(30000);
}

Happy multithreading on the Core!

6 Likes

I was tempted in, but cannot get it to compile in the web IDE. I used the example without the include line, then added the library using the Web IDE. It added the include line as per below, but fails to compile.

// This #include statement was automatically added by the Particle IDE.
#include "freertos4core/freertos4core.h"

This is what I get when I try to Verify it:

r3.cpp:3:20: error: variable or field 'timerCallback' declared void
 void timerCallback(TimerHandle_t handle);

r3.cpp:3:20: error: 'TimerHandle_t' was not declared in this scope
make[2]: *** [../build/target/user/platform-0-lr3.o] Error 1
make[1]: *** [user] Error 2
make: *** [main] Error 2

I tried one of the other Core examples that uses a (different) library and it compiled OK, so I think I’ve done the right steps to add a library in the IDE. Is there something else that I need to do for this particular one?

Strange. It’s working for me. The example in the library includes #pragma SPARK_NO_PREPROCESSOR - I’ve just added that to the code above.

Hi,

I am using a Core.
After including the library I get the following compile error. I do not call any function or use any data type from the library. I simply add the library to my project. Any clue??

/tmp/ccZn9rbw.ltrans23.ltrans.o: In function `__malloc_unlock':
freertos4core/freertos4core.cpp:35: undefined reference to `xQueueGiveMutexRecursive'
/tmp/ccZn9rbw.ltrans23.ltrans.o: In function `__malloc_lock':
freertos4core/freertos4core.cpp:29: undefined reference to `xQueueTakeMutexRecursive'
collect2: error: ld returned 1 exit status
make[1]: *** [f47e5d1601b9c355c41c3f85d7b9b1becc7310d000132d47dcabcbf8ce7f.elf] Error 1
make: *** [main] Error 2

Here is my code:

// This #include statement was automatically added by the Particle IDE.
#include "freertos4core/freertos4core.h"

  /***************/
 /* BELL - CORE */
/***************/

int comingButton = D3;
int comeUpButton = D2;
int buzzer = A0;

#define ring_duration 2000 // mSeconds

void setup() {
    pinMode(buzzer, OUTPUT);
    pinMode(comingButton, INPUT_PULLUP);
    pinMode(comeUpButton, INPUT_PULLUP);
    
    Particle.subscribe("sb-evt-from-display", eventDispatcher, MY_DEVICES);
}

void loop() {

}

void eventDispatcher(const char *event, const char *data) {
    String evt = String(data);
    
    if (evt.equals("bell-button-pressed")) {
        amIHome();
    }
}

void amIHome() {
    if (true) {
        Particle.publish("sb-evt-from-bell", "ringing", 60, PRIVATE);
        tone(buzzer, 392, ring_duration);
    }
}

void ring_timer_callback() {
    Particle.publish("sb-evt-from-bell", "no-answer", 60, PRIVATE);
}

Have you tried adding this (as the previous post points out)?

You might have to add #include "Parricle.h" and add function prototypes (forward declare) or adapt the order of your functions (declare before first call) too.

And what firmware version are you targeting?

Hi,

Thanks for your reply. I am targeting v0.4.9 for the firmware.
I have added the #pragma directive. I had to include Particle.h and rearrange my function declarations. I get the same error. I am not sure the #pragma does anything as it seems to be ignored.

smartbell-bell.cpp:2:0: warning: ignoring #pragma SPARK_NO_PREPROCESSOR  [-Wunknown-pragmas]
 #pragma SPARK_NO_PREPROCESSOR
 ^

/tmp/ccdnunac.ltrans23.ltrans.o: In function `__malloc_unlock':
freertos4core/freertos4core.cpp:35: undefined reference to `xQueueGiveMutexRecursive'
/tmp/ccdnunac.ltrans23.ltrans.o: In function `__malloc_lock':
freertos4core/freertos4core.cpp:29: undefined reference to `xQueueTakeMutexRecursive'
collect2: error: ld returned 1 exit status
make[1]: *** [ee9eff71d96b6a9b01c8fc0ec5fe1a9dec43f42743b9dfd0018973a8dfe2.elf] Error 1
make: *** [main] Error 2

That message is definetly wrong, but that's also a known glitch :sunglasses:

It does what it's supposed to do despite the warning.

But if this also doesn't help pinging @mdma might :wink:

@ScruffR Thanks for your message.
@mdma Building the example code from FreeRTOS library with firmwares 0.4.7 and 0.4.6 actually works. The error only appears with firmware 0.4.9. That’s as far as I can go.

1 Like

I published version 1.0.10 of the freertos4core library which addresses these build issues for 0.4.9. Thanks for notifying me of the issue!

@mdma No prob and thanks for the fix! The lib version on the web IDE is still 0.1.0.9. How can I use your latest version? Thanks!

Please click “Refresh Libraries” in the libraries drawer. That should pull in the latest version.