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 commit is contained in:
bors[bot]
2022-02-12 00:30:47 +00:00
committed by GitHub
46 changed files with 988 additions and 848 deletions

View File

@ -463,7 +463,6 @@ mod eh02 {
#[cfg(feature = "unstable-traits")]
mod eh1 {
use super::*;
use futures::FutureExt;
impl<'d, C: Channel, T: GpioPin> embedded_hal_1::digital::ErrorType for InputChannel<'d, C, T> {
type Error = Infallible;
@ -480,6 +479,12 @@ mod eh1 {
self.pin.is_low()
}
}
}
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
mod eh1a {
use super::*;
use futures::FutureExt;
impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Input<'d, T> {
type WaitForHighFuture<'a>

View File

@ -1,6 +1,8 @@
#![no_std]
#![feature(generic_associated_types)]
#![feature(type_alias_impl_trait)]
#![cfg_attr(
feature = "nightly",
feature(generic_associated_types, type_alias_impl_trait)
)]
#[cfg(not(any(
feature = "nrf51",

View File

@ -374,7 +374,6 @@ mod eh02 {
#[cfg(feature = "unstable-traits")]
mod eh1 {
use super::*;
use core::future::Future;
impl embedded_hal_1::spi::Error for Error {
fn kind(&self) -> embedded_hal_1::spi::ErrorKind {
@ -437,7 +436,7 @@ mod eh1 {
fn transaction<'a>(
&mut self,
operations: &mut [embedded_hal_async::spi::Operation<'a, u8>],
operations: &mut [embedded_hal_1::spi::blocking::Operation<'a, u8>],
) -> Result<(), Self::Error> {
use embedded_hal_1::spi::blocking::Operation;
for o in operations {
@ -451,6 +450,12 @@ mod eh1 {
Ok(())
}
}
}
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
mod eh1a {
use super::*;
use core::future::Future;
impl<'d, T: Instance> embedded_hal_async::spi::Read<u8> for Spim<'d, T> {
type ReadFuture<'a>

View File

@ -2,6 +2,7 @@ use core::cell::Cell;
use core::sync::atomic::{compiler_fence, AtomicU32, AtomicU8, Ordering};
use core::{mem, ptr};
use critical_section::CriticalSection;
use embassy::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy::blocking_mutex::CriticalSectionMutex as Mutex;
use embassy::interrupt::{Interrupt, InterruptExt};
use embassy::time::driver::{AlarmHandle, Driver};
@ -94,7 +95,7 @@ const ALARM_STATE_NEW: AlarmState = AlarmState::new();
embassy::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver {
period: AtomicU32::new(0),
alarm_count: AtomicU8::new(0),
alarms: Mutex::new([ALARM_STATE_NEW; ALARM_COUNT]),
alarms: Mutex::const_new(CriticalSectionRawMutex::new(), [ALARM_STATE_NEW; ALARM_COUNT]),
});
impl RtcDriver {

View File

@ -679,7 +679,7 @@ mod eh1 {
fn transaction<'a>(
&mut self,
_address: u8,
_operations: &mut [embedded_hal_async::i2c::Operation<'a>],
_operations: &mut [embedded_hal_1::i2c::blocking::Operation<'a>],
) -> Result<(), Self::Error> {
todo!();
}
@ -690,58 +690,59 @@ mod eh1 {
_operations: O,
) -> Result<(), Self::Error>
where
O: IntoIterator<Item = embedded_hal_async::i2c::Operation<'a>>,
O: IntoIterator<Item = embedded_hal_1::i2c::blocking::Operation<'a>>,
{
todo!();
}
}
}
impl<'d, T: Instance> embedded_hal_async::i2c::I2c for Twim<'d, T> {
type ReadFuture<'a>
where
Self: 'a,
= impl Future<Output = Result<(), Self::Error>> + 'a;
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
impl<'d, T: Instance> embedded_hal_async::i2c::I2c for Twim<'d, T> {
type ReadFuture<'a>
where
Self: 'a,
= impl Future<Output = Result<(), Self::Error>> + 'a;
fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
self.read(address, buffer)
}
fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
self.read(address, buffer)
}
type WriteFuture<'a>
where
Self: 'a,
= impl Future<Output = Result<(), Self::Error>> + 'a;
type WriteFuture<'a>
where
Self: 'a,
= impl Future<Output = Result<(), Self::Error>> + 'a;
fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> {
self.write(address, bytes)
}
fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> {
self.write(address, bytes)
}
type WriteReadFuture<'a>
where
Self: 'a,
= impl Future<Output = Result<(), Self::Error>> + 'a;
type WriteReadFuture<'a>
where
Self: 'a,
= impl Future<Output = Result<(), Self::Error>> + 'a;
fn write_read<'a>(
&'a mut self,
address: u8,
wr_buffer: &'a [u8],
rd_buffer: &'a mut [u8],
) -> Self::WriteReadFuture<'a> {
self.write_read(address, wr_buffer, rd_buffer)
}
fn write_read<'a>(
&'a mut self,
address: u8,
wr_buffer: &'a [u8],
rd_buffer: &'a mut [u8],
) -> Self::WriteReadFuture<'a> {
self.write_read(address, wr_buffer, rd_buffer)
}
type TransactionFuture<'a>
where
Self: 'a,
= impl Future<Output = Result<(), Self::Error>> + 'a;
type TransactionFuture<'a>
where
Self: 'a,
= impl Future<Output = Result<(), Self::Error>> + 'a;
fn transaction<'a>(
&'a mut self,
address: u8,
operations: &mut [embedded_hal_async::i2c::Operation<'a>],
) -> Self::TransactionFuture<'a> {
let _ = address;
let _ = operations;
async move { todo!() }
}
fn transaction<'a>(
&'a mut self,
address: u8,
operations: &mut [embedded_hal_async::i2c::Operation<'a>],
) -> Self::TransactionFuture<'a> {
let _ = address;
let _ = operations;
async move { todo!() }
}
}

View File

@ -844,7 +844,6 @@ mod eh02 {
#[cfg(feature = "unstable-traits")]
mod eh1 {
use super::*;
use core::future::Future;
impl embedded_hal_1::serial::Error for Error {
fn kind(&self) -> embedded_hal_1::serial::ErrorKind {
@ -872,6 +871,36 @@ mod eh1 {
}
}
impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UarteTx<'d, T> {
type Error = Error;
}
impl<'d, T: Instance> embedded_hal_1::serial::blocking::Write for UarteTx<'d, T> {
fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
self.blocking_write(buffer)
}
fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UarteRx<'d, T> {
type Error = Error;
}
impl<'d, U: Instance, T: TimerInstance> embedded_hal_1::serial::ErrorType
for UarteWithIdle<'d, U, T>
{
type Error = Error;
}
}
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
mod eh1a {
use super::*;
use core::future::Future;
impl<'d, T: Instance> embedded_hal_async::serial::Read for Uarte<'d, T> {
type ReadFuture<'a>
where
@ -903,22 +932,6 @@ mod eh1 {
}
}
// =====================
impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UarteTx<'d, T> {
type Error = Error;
}
impl<'d, T: Instance> embedded_hal_1::serial::blocking::Write for UarteTx<'d, T> {
fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
self.blocking_write(buffer)
}
fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
impl<'d, T: Instance> embedded_hal_async::serial::Write for UarteTx<'d, T> {
type WriteFuture<'a>
where
@ -939,12 +952,6 @@ mod eh1 {
}
}
// =====================
impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for UarteRx<'d, T> {
type Error = Error;
}
impl<'d, T: Instance> embedded_hal_async::serial::Read for UarteRx<'d, T> {
type ReadFuture<'a>
where
@ -956,14 +963,6 @@ mod eh1 {
}
}
// =====================
impl<'d, U: Instance, T: TimerInstance> embedded_hal_1::serial::ErrorType
for UarteWithIdle<'d, U, T>
{
type Error = Error;
}
impl<'d, U: Instance, T: TimerInstance> embedded_hal_async::serial::Read
for UarteWithIdle<'d, U, T>
{