esp-rs / esp-idf-sys

Bindings for ESP-IDF (Espressif's IoT Development Framework)
Apache License 2.0
240 stars 114 forks source link

Do Rust Native Queues and Mutexes Properly Suspend Tasks #277

Closed marsfan closed 4 months ago

marsfan commented 4 months ago

Note: Hopefully posting a question here is allowed. If not, please let me know where I should be asking this so I can put the question in the correct place.

When writing code in C/C++ with the ESP-IDF, functions that read from a queue (e.g. xQueueReceive) or attempt to take a mutex (e.g. xSemaphoreTake) will put the task task into a suspended state, so that the FreeRTOS system can switch to other tasks while waiting for the resource to be obtained. Will the equivalent functionality built into Rust do this as well?

I ask as I considering on porting a project from C++ to Rust that will need to read from different sensors in different tasks, and it seems that embedded-hal-bus is the way to do this. Furthermore, I will then have a task that needs to sit waiting to be able to read data from a queue. I would like to be able to use Rusts's built in functions to do this, but I'm worried that the tasks will not properly suspend when they are waiting.

N3xed commented 4 months ago

As far as I know, all rust platform APIs use libc behind the scenes, which then uses the newlib implementation in esp-idf-sys, which for the threading stuff ultimately uses the right FreeRTOS APIs.

So in short, yes. For interrupts, you have to use the native FreeRTOS APIs though, as far as I know.

ivmarkov commented 4 months ago

I also confirm that all Rust sunchronization primitives, including std::sync::Mutex suspend the FreeRTOS tasks when waiting on the primitive, because these primitives are implemented in terms of FreeRTOS lower level synchronization primitives. Just like Rust threads are implemented in terms of FreeRTOS tasks.

@N3xed is right that you should be extra careful if you also plan to hook FreeRTOS interrupts yourself, because in that case you cannot use off-the-shelf Rust synchronization primitives, as they are not interrupt-safe. In that case, you should do unsafe calls into FreeRTOS primitives, or use the few ones which already have safe Rust wrappers in esp-idf-hal/esp-idf-svc.

As for questions, please use the Matrix channel, which is linked from the README of this crate.

marsfan commented 3 months ago

@N3xed and @ivmarkov Thank you on both accounts. I will use matrix for further questions.