Channel-based concurrency for bare metal applications

I'm writing no-std application for ESP32. Currently, in order to send data to another core, I use Mutex with Option, and check it each n millis when waiting for value.
I wonder if there are any mpsc or spsc channel implementations available?

If like you say you can use std::sync::Mutex, then you should be able to use std::sync::mpsc::channel just as well.

You mention you have a no-std application, but the mutex in std requires... std... Are you using some other crate?

Sorry, I should have specified that I use Mutex from critical_section

Alright, and I'm going to assume you don't use alloc either.

Maybe something like ringbuf works for you? I haven't used it myself though.

1 Like

That looks great, thank you. I would also like to have an ability to wait on read, but not a problem.

You could achieve that by making extension traits and spinning. For example:

trait ConsumerExt<T> {
    fn pop_block(&mut self) -> T;
}
impl<T, const N: usize> ConsumerExt<T> for Consumer<T, &StaticRb<T, N>> {
    fn pop_block(&mut self) -> T {
        loop {
            match self.pop() {
                Some(val) => return val,
                None => spin_loop(),
            }
        }
    }
}

trait ProducerExt<T> {
    fn push_block(&mut self, elem: T);
}
impl<T, const N: usize> ProducerExt<T> for Producer<T, &StaticRb<T, N>> {
    fn push_block(&mut self, mut elem: T) {
        loop {
            match self.push(elem) {
                Ok(()) => break,
                Err(val) => {
                    elem = val;
                    spin_loop();
                }
            }
        }
    }
}

Here's a running example on Rust Explorer.

There might be more efficient ways of implementing the blocking read, but that's the simplest that came to mind.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.