-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SmartLedsAdapter::new does not have async impl for Rmt::new_async? #4
Comments
I somehow missed that on Matrix. There is no async-version of |
Thanks! Perhaps worth opening another issue/discussion although applies to this particular case too: What do you think about the use of
Is it worth making this uniform across peripherals in /cc @MabezDev |
Seeing as the (Though one could argue that since this struct's sole purpose was to provide an adapter for smart_leds, maybe it shouldn't have an async variant without an upstream trait, but no reason to be strict I guess)
This could probably be done for the drivers that mandate DMA, as the async mode could be inferred from the dma channel as well. (Personally I'd say it's too soon as the DMA based apis aren't mature enough) |
Thanks for the comments and ideas!
Indeed, that Rmt struct member,
I'm not sure if limiting the async-ness to just the For now I'm being cheeky, breaking stuff locally, patching and defaulting to on smartleds-esp-hal: diff --git a/esp-hal-smartled/src/lib.rs b/esp-hal-smartled/src/lib.rs
index 98164779..86a91249 100644
--- a/esp-hal-smartled/src/lib.rs
+++ b/esp-hal-smartled/src/lib.rs
@@ -30,7 +30,7 @@ use esp_hal::{
clock::Clocks,
gpio::OutputPin,
peripheral::Peripheral,
- rmt::{Error as RmtError, PulseCode, TxChannel, TxChannelConfig, TxChannelCreator},
+ rmt::{asynch::TxChannelAsync, Error as RmtError, PulseCode, TxChannelConfig, TxChannelCreatorAsync},
};
use smart_leds_trait::{SmartLedsWrite, RGB8};
@@ -73,7 +73,7 @@ macro_rules! smartLedBuffer {
/// interaction functionality using the `smart-leds` crate
pub struct SmartLedsAdapter<TX, const BUFFER_SIZE: usize>
where
- TX: TxChannel,
+ TX: TxChannelAsync,
{
channel: Option<TX>,
rmt_buffer: [u32; BUFFER_SIZE],
@@ -82,7 +82,7 @@ where
impl<'d, TX, const BUFFER_SIZE: usize> SmartLedsAdapter<TX, BUFFER_SIZE>
where
- TX: TxChannel,
+ TX: TxChannelAsync,
{
/// Create a new adapter object that drives the pin using the RMT channel.
pub fn new<C, O>(
@@ -93,7 +93,7 @@ where
) -> SmartLedsAdapter<TX, BUFFER_SIZE>
where
O: OutputPin + 'd,
- C: TxChannelCreator<'d, TX, O>,
+ C: TxChannelCreatorAsync<'d, TX, O>,
{
let config = TxChannelConfig {
clk_divider: 1,
@@ -160,7 +160,7 @@ where
impl<TX, const BUFFER_SIZE: usize> SmartLedsWrite for SmartLedsAdapter<TX, BUFFER_SIZE>
where
- TX: TxChannel,
+ TX: TxChannelAsync,
{
type Error = LedAdapterError;
type Color = RGB8;
@@ -168,7 +168,7 @@ where
/// Convert all RGB8 items of the iterator to the RMT format and
/// add them to internal buffer, then start a singular RMT operation
/// based on that buffer.
- fn write<T, I>(&mut self, iterator: T) -> Result<(), Self::Error>
+ async fn write<T, I>(&mut self, iterator: T) -> Result<(), Self::Error>
where
T: IntoIterator<Item = I>,
I: Into<Self::Color>,
@@ -187,14 +187,15 @@ where
*seq_iter.next().ok_or(LedAdapterError::BufferSizeExceeded)? = 0;
// Perform the actual RMT operation. We use the u32 values here right away.
- let channel = self.channel.take().unwrap();
- match channel.transmit(&self.rmt_buffer).wait() {
- Ok(chan) => {
- self.channel = Some(chan);
+ let mut channel = self.channel.take().unwrap();
+ match channel.transmit(&self.rmt_buffer).await {
+ Ok(_) => {
+ //self.channel = Some(chan);
Ok(())
}
- Err((e, chan)) => {
- self.channel = Some(chan);
+ //Err((e, chan)) => {
+ Err(e) => {
+ //self.channel = Some(chan);
Err(LedAdapterError::TransmissionError(e))
}
} Then adding |
Oh, scratch that comment about what to convert to async @Dominaezzz: I just realised that With this out of the way, it seems like I just need to carefully gate my changes through |
Digging around with this today (see comments in esp-rs/esp-hal#1779) I seem to be stuck. The async context switching is surprisingly slow. Sometimes so slow that by the first time the future is polled, the RMT has already read 32 pulses. And wake up triggered by interrupt is particularly bad. (though I am also suspicious I may be doing something wrong with the interrupts) I have this kind of working in my branch (esp-rs/esp-hal@main...tschundler:esp-hal:async-led-iterator) in very messy code with no interrupts. Maybe it can serve as inspiration? I may personally give up on async and focus on my original goal in esp-rs/esp-hal#1768 of iterator input for RMT since that part I have working well. I'm well beyond my depth at this point. I'm debugging by panicking and dumping RMT registers. I feel there has to be a better way. |
Are you running in release mode? |
Yes. Even though the cargo generate template has some optimization in debug mode, I also tried with Digging around FastLED I see a lot of mention of IRAM for timing critical stuff. Maybe that is a factor? Specifically for Embassy itself? Fwiw without async, I get working LED signals in Wokwi at 40MHz stimulated, so that gives time for 5x more code than that is running, which is why I feel the issue is the overhead of async executor. But I also haven't played with |
@tschundler Maybe async is an issue, but you'll likely also want to place the rmt driver in RAM (esp-idf has an option for this), for better perf. We already have a config option for this with SPI, once esp-rs/esp-hal#2156 is merged we could add one for RMT. |
Mentioned in esp-rs matrix and here too, flagging it here:
The text was updated successfully, but these errors were encountered: