Here is a simple example of Threads in Photon. As you all know since 0.4.6, threads are supported in beta. Looking at the firmware code, I found this file which defines the threads. I just played with it by creating multiple threads that simply prints some debug strings. I thought it would be great to share it here. I modified my sample to blink 3 LEDs at different rates (replica of this VIPER sample).
Here is the source code of the sample, hope this sneak peek is helpful for you.
#include "application.h"
// LED Param, defines pin and delay between blinks
typedef struct {
int pin;
int delay;
} LED_PARAM;
// LED pins
int led1 = D5;
int led2 = D3;
int led3 = D1;
// Defines thread parameters
LED_PARAM ledParams[3] = {
{led1, 500},
{led2, 1000},
{led3, 2000}
};
Thread* led1Thread;
Thread* led2Thread;
Thread* led3Thread;
os_thread_return_t ledBlink(void* param){
LED_PARAM *p = (LED_PARAM*)param;
// Start never ending loop
for(;;) {
Serial.print("Thread Parameters: ");
Serial.print(p->pin);
Serial.print(", ");
Serial.println(p->delay);
// Blink led
digitalWrite(p->pin, HIGH);
delay(p->delay);
digitalWrite(p->pin, LOW);
delay(p->delay);
}
}
void setup() {
Serial.begin(115200);
// Set pin mode
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
// Start new threads
led1Thread = new Thread("sample", ledBlink, &ledParams[0]);
led2Thread = new Thread("sample", ledBlink, &ledParams[1]);
led3Thread = new Thread("sample", ledBlink, &ledParams[2]);
}
void loop() {
// Nothing here.
}
This a nice simple example for introducing threading.
Unfortunately it also introduces one if the pitfalls of multithreaded code. I imagine if you look at the serial output, you may see missing output, interleaved output or other problems, and not a nice interleaving of the 3 threads as you might expect.
In a future release, the photon will also support mutexes, which are one way to solve this problem.
yes, the interleaving is more visible when the delay is same for all threads or the difference is very small. When I looked at the code I didn’t see any synchronization objects. But found Critical Section. For the time being this should help
So I have a threads question and this feels like a good place to ask it. @mdma mentioned earlier that mutexes are coming, and I was under the impression that the application CPU on Particle devices was single threaded, so doesn’t that mean that there can’t ever be a race condition between threads? If there’s only one actual hardware thread, a variable can’t be changed while being used by another, on a Photon or Electron, right?
I’m thinking I’m wrong about that because mutexes are coming, and if they’re coming that means they deliver something that is not present currently.
So, my logic is arguing with itself, here. Which is right?
@naikrovek, single threaded doesn’t guarantee mutual exclusivity. FreeRTOS is preemptive meaning it can interrupt code at any time. Variables might be in the process of being changed when the FreeRTOS scheduler changes threads. Add to that the fact that hardware resources (SPI, I2C, Serial) can’t be grabbed at any time. There are wonderful examples of this classic mistake on this forum where folks were confused that data going to a serial port on two different threads was not in the order they expected! Adding mutexes is not only for variables but also for hardware resources.
I don’t know if this is the right place to post. Is there a dedicated sub forum for freertos?
If yes, please move this.
So, I have been reading the photon is using freeRTOS (am I mistaken?) but the functions I find here are not the ones I am using when working on freeRTOS.
I am looking for a way to send messages in queues, just like in freeRTOS, can anyone inform me on how to do this?
In freeRTOS, I would create a queue with the xQueueCreate function and send messages with the xQueueSend function.
Hi, the example at the top of the page is now working.
However I found these two files from another post here:
But when I even try to include any freertos file, the compiler complains that it cannot find these files.
Is there any example that is using the functions from these files?
Just for a kickstart, after that I think I can work it out. I have been using freeRTOS for a couple of years now and I like it a lot.
These files are included in the framework and hence no #include statement (other than Particle.h) is required for the public APIs (esp. spark_wiring_thread.h).
But for concurrent_hal.cpp you may not have direct access to these functions as they might not be public (would need to check that tho’)
Yes I found out about the concurrent_hal API after a while. I used the queue functions, I created one, sent a message and received it and it is working fine!
Now I am looking at the TCP functions, I want to use the classic socket approach with accept etc
By the way, why did you choose not to just expose the FreeRTOS functions to the user?