613: Rust stable support r=Dirbaio a=Dirbaio
This PR adds (limited) stable Rust support!
The drawbacks are:
- No `#[embassy::task]`, `#[embassy::main]`. (requires `type_alias_impl_trait`). You have to manually allocate the tasks somewhere they'll live forever. See [example](https://github.com/embassy-rs/embassy/blob/master/examples/nrf/src/bin/raw_spawn.rs)
- No async trait impls (requires GATs). Note that the full API surface of HALs is still available through inherent methods: #552#581
- Some stuff is not constructible in const (requires `const_fn_trait_bound`), although there's an (ugly) workaround for the generic `Mutex`.
So it's not that bad in the end, it's fully usable for shipping production-ready firmwares. We'll still recommend nightly as the default, until GATs and `type_alias_impl_trait` are stable.
Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
This approach owns the sequence buffers which, while introducing an extra move, it eliminates the need to guard the lifetime of the sequence buffer. Given ownership, the buffer will be retained until the PWM sequence task is stopped.
Demonstrates how to set the colour of a WS2812B to blue using PWM, and the use of multiple sequences along with their own config. This required an API change.
I had introduced a small bug in my last PR where I assigned the sequence before stopping the PWM. I now stop the PWM before doing that now.
Also, corrected a math comment.
Sequences are now passed in via the start method to avoid having to stop the PWM and restart it. Sequences continue to be constrained with the same lifetime of the Pwm object itself. The pwm_sequence example has been extended to illustrate multiple sequences being passed around.
This commit allows event_endtx to be used outside of the Uarte itself. As a consequence, PPI can be used to drive tasks given the end of transmission on the Uarte. This is particularly useful for situations like RS485 where a GPIO must be set to high when transmitting then cleared when done. A non-ppi approach can cause a delay in the clearing of this GPIO as other Embassy tasks might become scheduled.
Unsafe is not required here given that all futures are required to live longer than their global peripheral instances. There are other occurrences of unsafe being used on new that should be removed. I started to do that but then went down a bit of a rabbit hole.
539: nrf: async usb r=Dirbaio a=jacobrosenthal
Frankensteined together from this old pr https://github.com/embassy-rs/embassy/pull/115 and nrf-usdb
~Doesnt currently work..~
Co-authored-by: Jacob Rosenthal <jacobrosenthal@gmail.com>
544: Introduces split on the nRF Uarte r=Dirbaio a=huntc
A new `split` method is introduced such that the Uarte tx and rx can be used from separate tasks. An MPSC is used in an example to illustrate how data may be passed between these tasks.
The approach taken within the `Uarte` struct is to split into tx and rx fields on calling `Uarte::new`. These fields are returned given a call to `Uarte::split`, but otherwise, if that call isn't made, then the API remains as it was before.
Here's a snippet from a new example introduced:
```rust
#[embassy::main]
async fn main(spawner: Spawner, p: Peripherals) {
// ...
let uart = uarte::Uarte::new(p.UARTE0, irq, p.P0_08, p.P0_06, NoPin, NoPin, config);
let (mut tx, rx) = uart.split();
// ...
// Spawn a task responsible purely for reading
unwrap!(spawner.spawn(reader(rx, s)));
// ...
// Continue reading in this main task and write
// back out the buffer we receive from the read
// task.
loop {
if let Some(buf) = r.recv().await {
info!("writing...");
unwrap!(tx.write(&buf).await);
}
}
}
#[embassy::task]
async fn reader(mut rx: UarteRx<'static, UARTE0>, s: Sender<'static, Noop, [u8; 8], 1>) {
let mut buf = [0; 8];
loop {
info!("reading...");
unwrap!(rx.read(&mut buf).await);
unwrap!(s.send(buf).await);
}
}
```
Co-authored-by: huntc <huntchr@gmail.com>