embassy-rs / embassy

Modern embedded framework, using Rust and async.
https://embassy.dev
Apache License 2.0
5.31k stars 732 forks source link

main attribute macro not found with ESP-IDF project with ESP32 Xtensa target #1586

Open kyp44 opened 1 year ago

kyp44 commented 1 year ago

Hi, I'm trying to incorporate embassy into my embedded project to add async capability to simplify multitasking.

My project targets an ESP32 Xtensa architecture (in particular I'm working with one of these), and uses the esp_idf_svc and esp_idf_hal crates, so that I have a full std environment and access to the networking protocols that esp_idf_svc provides out of the box.

The problem is that I get a compiler error that the embassy_executor::main attribute macro cannot be found. I converted some of my code to a task function declared with embassy_executor::task, and that works fine. I did enable the nightly feature of embassy_executor and I also tried it with each of the arch-xtensa and arch-xtensa features as well (not sure if you're supposed to generally specify your architecture in this way), but it can never find the main macro. I am compiling against the current latest release (0.2.0).

Is the ESP32 not fully supported yet, especially when using ESP-IDF, or is there something that I'm doing wrong here? I noticed that the esp-hal crate (i.e. the non-IDF HAL crate) has examples that illustrate using embassy in that environment, though interestingly those do not use the main macro (perhaps they are a little out of date?) and start the executor manually. I have seen no such examples for the esp-idf-hal crate (i.e. the IDF/std version of the HAL).

If it would be useful, I can quickly create an MRE to demonstrate the compiler error.

Dirbaio commented 1 year ago

Enabling features executor-thread, arch-xtensa and nightly should make #[embassy_executor::main] available.

However it likely won't work under ESP-IDF, because it assumes bare-metal. You'll have to create the executor manually under IDF's main. Also, I'm not sure if WFI is usable under ESP-IDF. If it's not you might have to use the raw executor to integrate the wakers with some semaphore/signal from the IDF RTOS for wakers.

I don't know much about IDF, it might be best to ask on espressif's repo or matrix channel.

Vollbrecht commented 1 year ago

In short:

  1. currently you can use everything from embassy in esp-idf expect the executor ( check embassy feature flags)
  2. you can use https://github.com/ivmarkov/edge-executor as an executor with the embassy primitives. A comprehensive project that is using it can be found here https://github.com/ivmarkov/ruwm
  3. for more background information check out the discussion here from esp maintainer ivmarkov and dirbaio in esp-rs matrix chat https://matrix.to/#/!LdaNPfUfvefOLewEIM:matrix.org/$-_0HgFptc1uoO6PCTP09EpD90w3uXN0RZSlQ9js1hTQ?via=matrix.org&via=tchncs.de&via=mozilla.org
kyp44 commented 1 year ago

I appreciate everyone's feedback and posting the question to Matrix. Even with features = ["arch-xtensa", "executor-thread", "nightly"] the main macro still seems not to be available, so I'm not sure whether that in and of itself is an issue or not.

I can get it to compile using a normal main function and manually starting the executor. However, I looked into the code a bit and I see that, for Xtensa, the embassy executor is directly executing ASM instructions to wait for interrupts, and I can definitely see that not being a safe thing to do with FreeRTOS, which is used by ESP-IDF in my environment.

Per the recommendation of @Vollbrecht I'll look into using edge-executor instead. My only concern there is whether this executor will put the chip into a sleep mode when idle.

Vollbrecht commented 1 year ago

Per the recommendation of @Vollbrecht I'll look into using edge-executor instead. My only concern there is whether this executor will put the chip into a sleep mode when idle.

It does only thinks you tell it to do. If you run the executor from a normal thread its just affected by the threads scheduling. You can also run multiple executors in different threads and utilize the RTOS priority thread system with preemptive scheduling on top of it. Technically the executor can also be run/scheduled from within ISR, but i did not play around with it, so far.

kyp44 commented 1 year ago

Thanks for the info! I just had a look at the ruwm project, and it's going to be a great resource for setting up async on the ESP32 and likely other things as well since it utilizes the esp-idf like my project. So thanks also for that recommendation!