ESP32 and FreeRTOS and atomic updates

Hi All...

I'm playing with an ESP32 card, which is 32 bit and my understanding is that its Arduino lib port is based on FreeRTOS.

If I have a data structure full of floats, like this:

typedef struct {
float var1;
float var2;
float var3;
} tRawData;

and I then have an instance of this type:

tRawData rawData;

When I update the members, since floats are 32 bits wide and the ESP32 is a 32 bit processor, is it correct that the updates to these members are atomic? I realize that updates to the entire data type may not be atomic, but am I at least guaranteed that the update of any individual member is atomic?

I ask of course because I want to populate this type in one thread (task) and consume the data in another thread.

Thanks very much...

Going off this

Atomic operations in concurrent programming are program operations that run completely independently of any other processes.

. Your update task would be the only task or have the highest preemptive priority, for the moment, running on the assigned core. I would, also assign such a task to Core0. Hrrumph or is that Core1, I got it wrote down somewhere. Yup, I am correct, setup() and loop() are run on core1. So you'd run your task on core0.

If you are meaning that the ESP32 memory/register changes are done as a single 32 bit operation, then yes that is the case.

If you want to run freeRTOS on the ESP32 you'l need to include freeRTOS.

#include "esp_system.h" //This inclusion configures the peripherals in the ESP system.
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "freertos/event_groups.h"

Using queues is the way to pass info from one task to another or from core to core.

Idahowalker:
Using queues is the way to pass info from one task to another or from core to core.

Yes I could use queues, or also semaphores / mutexes, but if 32 bit variables are updated atomically in this 32 bit processor that is unnecessary. That's what I'm trying to figure out.

Idahowalker:
Going off this . Your update task would be the only task or have the highest preemptive priority, for the moment, running on the assigned core. I would, also assign such a task to Core0. Hrrumph or is that Core1, I got it wrote down somewhere. Yup, I am correct, setup() and loop() are run on core1. So you'd run your task on core0.

Okay I'll take a closer look at the xTaskCreate() function but I recall that I can assign a priority but not necessarily a core. It's good to know setup() and loop() run on core 1, thanks.

If you are meaning that the ESP32 memory/register changes are done as a single 32 bit operation, then yes that is the case.

Yes so I expect the compiler generated code moves the variable through the register.

If you want to run freeRTOS on the ESP32 you'l need to include freeRTOS.

#include "esp_system.h" //This inclusion configures the peripherals in the ESP system.

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "freertos/event_groups.h"

Interestingly, selecting the ESP32 in the Arduino dev environment, I was able to create tasks in my app, and run the samples, without including any of that. I don't know why.

xTaskCreatePinnedToCore( fSendSerialToBrain, "fSendSerialToBrain", TaskStack20K, NULL, Priority3, &xHANDLE_SendSerialToBrain, TaskCore0 );

Yes 32 bit operations are atomic. But.. protecting shared data between tasks is a different matter.

czu001:
Yes 32 bit operations are atomic. But.. protecting shared data between tasks is a different matter.

Right at this point if I have atomic reads and writes then I won't run the risk of reading a variable while it is half updated. Thats good enough for now.

Hey, anyone who's reading this, the original question was PERFECTLY GOOD. There's no reason to pass every little thing in a message, and there's every reason to avoid messages when in a constrained environment like Arduino / ESP. The original poster was asking a fairly sophisticated question, because memory "tearing" exists on some processors, where simply setting a 4 byte value, you might attempt to do a read on 4 bytes, and see half the new value and half the old value - and this especially happens on multi-core systems.

I am also assuming the ESP32, which seems to internally work at 32-bits everywhere, would not exhibit any tearing if doing 32-bit reads on 32-bit aligned access. I sure hope that's true :slight_smile: