4ms deterministic cycle


We use an ESP32 wrom with freeRtos and VisualStudio 2022 with VisualGDB.

We want to run a deterministic application on one core of the esp32 and the ble communication on the second core.

We are able to run a deterministic “hello world” on a core 0, but we aren’t able to go faster than 8 ms. Our goal is to run at 4ms.

Also if we assign the ble communication to core 1 the determinism becomes imprecise. So:

  • is it possible to assign a specific task to a single core?

  • if yes, how?

  • how and which function to use to have a deterministic cycle?

Thank you

Would you please elaborate what you mean by that? Can you share what this “hello world” looks like?

If you are using FreeRTOS from ESP-IDF, you can do so by calling xTaskCreatePinnedToCore API.

If you want to execute a task every 4 ms, you can look at the following APIs -

Hello and thank you for your help.

We still use the vTaskDelayUntil but we are not able to go under 8/7ms.
Maybe we need to assign the task to the core1?
Or what can limit our task to 7/8ms?

The task is:

static void yys_rtc_task(void* arg)
static int64_t time = 0;
static int64_t endTime = 0;
static int64_t deltaT = 0;
static TickType_t xLastWakeTime;
static const TickType_t xFrequency = 7;
static BaseType_t xWasDelayed;

// Initialise the xLastWakeTime variable with the current time.
xLastWakeTime = xTaskGetTickCount();
for (;;)
time = esp_timer_get_time();
deltaT = time – endTime;
endTime = time;
// Wait for the next cycle.
//xWasDelayed = xTaskDelayUntil(&xLastWakeTime, xFrequency);
vTaskDelayUntil(&xLastWakeTime, xFrequency);

// time = esp_timer_get_time();
// deltaT = time – endTime;
// endTime = time;

// Perform action here. xWasDelayed value can be used to determine
// whether a deadline was missed if the code here took too long.
ESP_LOGE(“TEST”, “time %lld — deltaT %lld — xWasDelayed %d”, time, deltaT, xWasDelayed);

What is the frequency of the tick interrupt, and have you verified you are actually getting the tick frequency you think you are? The delay time is specified in ticks so only has a resolution of the tick frequency.

The frequency is 500 as you can see in the image. How i can verify it?

500Hz means a tick every 2 ms - so you’ll be able to get a delay of 2ms, 4ms, 6ms etc. You should use pdMS_TO_TICKS for defining xFrequency -

static const TickType_t xFrequency = pdMS_TO_TICKS(4); /* 4ms. */

To add a little to aggarg@'s reply. A 500Hz frequency (2ms period) means requesting to block for 4ms can result in a block time of 3.0001 (if the block starts immediately before the next tick interrupt) to 3.99999ms (if the block starts immediately after the last tick interrupt) because you have a 2ms resolution.

Isn’t it 2.0001 ms as minimum delay :thinking:

I was mis-trying to give the range for a requested 4ms delay with a 2ms tick. :man_facepalming: Won’t edit otherwise your post won’t make sense.

If you need to run at an exact interval, then it sounds like you should be doing this task from an ISR.

I’m not 100% sure on the determinism of waking up a task, but an alternative idea would be for the task to wait on a notification sent from the tick ISR, so no sleeps would be involved. Your task would have to have a high priority as well so you’d wake it up immediately after the ISR ends by calling portYIELD_FROM_ISR. You can read about notifications here.