Merge #627
627: Update Rust nightly, embedded-hal 1.0, embedded-hal-async. r=Dirbaio a=Dirbaio Includes the SpiDevice/SpiBus split. https://github.com/rust-embedded/embedded-hal/pull/351 Includes the GAT where clause location change. https://github.com/rust-lang/rust/issues/89122 Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
This commit is contained in:
commit
db8050b388
@ -97,7 +97,7 @@ impl<'a, S: PeripheralState> PeripheralMutex<'a, S> {
|
||||
// Interrupts' priorities can only be changed with raw embassy `Interrupts`,
|
||||
// which can't safely store a `PeripheralMutex` across invocations.
|
||||
// - We can't have preempted a with() call because the irq is disabled during it.
|
||||
let state = unsafe { &mut *(p as *mut S) };
|
||||
let state = &mut *(p as *mut S);
|
||||
state.on_interrupt();
|
||||
});
|
||||
irq.set_handler_context(state_ptr as *mut ());
|
||||
|
@ -18,8 +18,8 @@ log = { version = "0.4.14", optional = true }
|
||||
|
||||
embassy = { version = "0.1.0", path = "../embassy", default-features = false }
|
||||
embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true }
|
||||
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.6", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true}
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy"}
|
||||
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.7", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy2", optional = true}
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy2"}
|
||||
embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common", default-features = false }
|
||||
futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] }
|
||||
embedded-hal = { version = "0.2", features = ["unproven"] }
|
||||
|
@ -78,7 +78,7 @@ impl<'a> SubGhzRadio<'a> {
|
||||
// This is safe because we only get interrupts when configured for, so
|
||||
// the radio will be awaiting on the signal at this point. If not, the ISR will
|
||||
// anyway only adjust the state in the IRQ signal state.
|
||||
let state = unsafe { &mut *(p as *mut StateInner<'a>) };
|
||||
let state = &mut *(p as *mut StateInner<'a>);
|
||||
state.on_interrupt();
|
||||
});
|
||||
irq.set_handler_context(state_ptr as *mut ());
|
||||
|
@ -20,7 +20,7 @@ pub trait RadioSwitch {
|
||||
/// Semtech Sx127x radio peripheral
|
||||
pub struct Sx127xRadio<SPI, CS, RESET, E, I, RFS>
|
||||
where
|
||||
SPI: ReadWrite<u8, Error = E> + 'static,
|
||||
SPI: SpiBus<u8, Error = E> + 'static,
|
||||
E: 'static,
|
||||
CS: OutputPin + 'static,
|
||||
RESET: OutputPin + 'static,
|
||||
@ -42,7 +42,7 @@ pub enum State {
|
||||
|
||||
impl<SPI, CS, RESET, E, I, RFS> Sx127xRadio<SPI, CS, RESET, E, I, RFS>
|
||||
where
|
||||
SPI: ReadWrite<u8, Error = E> + 'static,
|
||||
SPI: SpiBus<u8, Error = E> + 'static,
|
||||
CS: OutputPin + 'static,
|
||||
RESET: OutputPin + 'static,
|
||||
I: Wait + 'static,
|
||||
@ -64,7 +64,7 @@ where
|
||||
|
||||
impl<SPI, CS, RESET, E, I, RFS> Timings for Sx127xRadio<SPI, CS, RESET, E, I, RFS>
|
||||
where
|
||||
SPI: ReadWrite<u8, Error = E> + 'static,
|
||||
SPI: SpiBus<u8, Error = E> + 'static,
|
||||
CS: OutputPin + 'static,
|
||||
RESET: OutputPin + 'static,
|
||||
I: Wait + 'static,
|
||||
@ -80,7 +80,7 @@ where
|
||||
|
||||
impl<SPI, CS, RESET, E, I, RFS> PhyRxTx for Sx127xRadio<SPI, CS, RESET, E, I, RFS>
|
||||
where
|
||||
SPI: ReadWrite<u8, Error = E> + 'static,
|
||||
SPI: SpiBus<u8, Error = E> + 'static,
|
||||
CS: OutputPin + 'static,
|
||||
E: 'static,
|
||||
RESET: OutputPin + 'static,
|
||||
@ -89,15 +89,14 @@ where
|
||||
{
|
||||
type PhyError = Sx127xError;
|
||||
|
||||
type TxFuture<'m>
|
||||
type TxFuture<'m> = impl Future<Output = Result<u32, Self::PhyError>> + 'm
|
||||
where
|
||||
SPI: 'm,
|
||||
CS: 'm,
|
||||
RESET: 'm,
|
||||
E: 'm,
|
||||
I: 'm,
|
||||
RFS: 'm,
|
||||
= impl Future<Output = Result<u32, Self::PhyError>> + 'm;
|
||||
RFS: 'm;
|
||||
|
||||
fn tx<'m>(&'m mut self, config: TxConfig, buf: &'m [u8]) -> Self::TxFuture<'m> {
|
||||
trace!("TX START");
|
||||
@ -137,15 +136,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
type RxFuture<'m>
|
||||
type RxFuture<'m> = impl Future<Output = Result<(usize, RxQuality), Self::PhyError>> + 'm
|
||||
where
|
||||
SPI: 'm,
|
||||
CS: 'm,
|
||||
RESET: 'm,
|
||||
E: 'm,
|
||||
I: 'm,
|
||||
RFS: 'm,
|
||||
= impl Future<Output = Result<(usize, RxQuality), Self::PhyError>> + 'm;
|
||||
RFS: 'm;
|
||||
|
||||
fn rx<'m>(&'m mut self, config: RfConfig, buf: &'m mut [u8]) -> Self::RxFuture<'m> {
|
||||
trace!("RX START");
|
||||
|
@ -8,7 +8,7 @@
|
||||
use bit_field::BitField;
|
||||
use embassy::time::{Duration, Timer};
|
||||
use embedded_hal::digital::v2::OutputPin;
|
||||
use embedded_hal_async::spi::ReadWrite;
|
||||
use embedded_hal_async::spi::SpiBus;
|
||||
|
||||
mod register;
|
||||
use self::register::PaConfig;
|
||||
@ -48,7 +48,7 @@ const VERSION_CHECK: u8 = 0x09;
|
||||
|
||||
impl<SPI, CS, RESET, E> LoRa<SPI, CS, RESET>
|
||||
where
|
||||
SPI: ReadWrite<u8, Error = E>,
|
||||
SPI: SpiBus<u8, Error = E>,
|
||||
CS: OutputPin,
|
||||
RESET: OutputPin,
|
||||
{
|
||||
|
@ -63,8 +63,8 @@ embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["n
|
||||
embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
|
||||
|
||||
embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
|
||||
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.6", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true}
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true}
|
||||
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.7", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy2", optional = true}
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy2", optional = true}
|
||||
|
||||
defmt = { version = "0.3", optional = true }
|
||||
log = { version = "0.4.14", optional = true }
|
||||
|
@ -108,7 +108,7 @@ unsafe fn handle_gpiote_interrupt() {
|
||||
|
||||
for i in 0..CHANNEL_COUNT {
|
||||
if g.events_in[i].read().bits() != 0 {
|
||||
g.intenclr.write(|w| unsafe { w.bits(1 << i) });
|
||||
g.intenclr.write(|w| w.bits(1 << i));
|
||||
CHANNEL_WAKERS[i].wake();
|
||||
}
|
||||
}
|
||||
@ -481,52 +481,36 @@ mod eh1 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
|
||||
mod eh1a {
|
||||
use super::*;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] {
|
||||
use futures::FutureExt;
|
||||
|
||||
impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Input<'d, T> {
|
||||
type WaitForHighFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WaitForHighFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_high<'a>(&'a mut self) -> Self::WaitForHighFuture<'a> {
|
||||
self.wait_for_high().map(Ok)
|
||||
}
|
||||
|
||||
type WaitForLowFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WaitForLowFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_low<'a>(&'a mut self) -> Self::WaitForLowFuture<'a> {
|
||||
self.wait_for_low().map(Ok)
|
||||
}
|
||||
|
||||
type WaitForRisingEdgeFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WaitForRisingEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_rising_edge<'a>(&'a mut self) -> Self::WaitForRisingEdgeFuture<'a> {
|
||||
self.wait_for_rising_edge().map(Ok)
|
||||
}
|
||||
|
||||
type WaitForFallingEdgeFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WaitForFallingEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_falling_edge<'a>(&'a mut self) -> Self::WaitForFallingEdgeFuture<'a> {
|
||||
self.wait_for_falling_edge().map(Ok)
|
||||
}
|
||||
|
||||
type WaitForAnyEdgeFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WaitForAnyEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_any_edge<'a>(&'a mut self) -> Self::WaitForAnyEdgeFuture<'a> {
|
||||
self.wait_for_any_edge().map(Ok)
|
||||
@ -534,49 +518,35 @@ mod eh1a {
|
||||
}
|
||||
|
||||
impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Flex<'d, T> {
|
||||
type WaitForHighFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WaitForHighFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_high<'a>(&'a mut self) -> Self::WaitForHighFuture<'a> {
|
||||
self.wait_for_high().map(Ok)
|
||||
}
|
||||
|
||||
type WaitForLowFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WaitForLowFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_low<'a>(&'a mut self) -> Self::WaitForLowFuture<'a> {
|
||||
self.wait_for_low().map(Ok)
|
||||
}
|
||||
|
||||
type WaitForRisingEdgeFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WaitForRisingEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_rising_edge<'a>(&'a mut self) -> Self::WaitForRisingEdgeFuture<'a> {
|
||||
self.wait_for_rising_edge().map(Ok)
|
||||
}
|
||||
|
||||
type WaitForFallingEdgeFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WaitForFallingEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_falling_edge<'a>(&'a mut self) -> Self::WaitForFallingEdgeFuture<'a> {
|
||||
self.wait_for_falling_edge().map(Ok)
|
||||
}
|
||||
|
||||
type WaitForAnyEdgeFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WaitForAnyEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_any_edge<'a>(&'a mut self) -> Self::WaitForAnyEdgeFuture<'a> {
|
||||
self.wait_for_any_edge().map(Ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -455,43 +455,25 @@ mod eh1 {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::Read<u8> for Spim<'d, T> {
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusFlush for Spim<'d, T> {
|
||||
fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusRead<u8> for Spim<'d, T> {
|
||||
fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
|
||||
self.blocking_transfer(words, &[])
|
||||
}
|
||||
|
||||
fn read_transaction(&mut self, words: &mut [&mut [u8]]) -> Result<(), Self::Error> {
|
||||
for buf in words {
|
||||
self.blocking_read(buf)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::Write<u8> for Spim<'d, T> {
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusWrite<u8> for Spim<'d, T> {
|
||||
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
|
||||
self.blocking_write(words)
|
||||
}
|
||||
|
||||
fn write_transaction(&mut self, words: &[&[u8]]) -> Result<(), Self::Error> {
|
||||
for buf in words {
|
||||
self.blocking_write(buf)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_iter<WI>(&mut self, words: WI) -> Result<(), Self::Error>
|
||||
where
|
||||
WI: IntoIterator<Item = u8>,
|
||||
{
|
||||
for w in words {
|
||||
self.blocking_write(&[w])?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::ReadWrite<u8> for Spim<'d, T> {
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBus<u8> for Spim<'d, T> {
|
||||
fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
|
||||
self.blocking_transfer(read, write)
|
||||
}
|
||||
@ -499,100 +481,45 @@ mod eh1 {
|
||||
fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
|
||||
self.blocking_transfer_in_place(words)
|
||||
}
|
||||
|
||||
fn transaction<'a>(
|
||||
&mut self,
|
||||
operations: &mut [embedded_hal_1::spi::blocking::Operation<'a, u8>],
|
||||
) -> Result<(), Self::Error> {
|
||||
use embedded_hal_1::spi::blocking::Operation;
|
||||
for o in operations {
|
||||
match o {
|
||||
Operation::Read(b) => self.blocking_read(b)?,
|
||||
Operation::Write(b) => self.blocking_write(b)?,
|
||||
Operation::Transfer(r, w) => self.blocking_transfer(r, w)?,
|
||||
Operation::TransferInPlace(b) => self.blocking_transfer_in_place(b)?,
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
|
||||
mod eh1a {
|
||||
use super::*;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] {
|
||||
use core::future::Future;
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_async::spi::Read<u8> for Spim<'d, T> {
|
||||
type ReadFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
impl<'d, T: Instance> embedded_hal_async::spi::SpiBusFlush for Spim<'d, T> {
|
||||
type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
|
||||
async move { Ok(()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_async::spi::SpiBusRead<u8> for Spim<'d, T> {
|
||||
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn read<'a>(&'a mut self, words: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
self.read(words)
|
||||
}
|
||||
|
||||
type ReadTransactionFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
|
||||
fn read_transaction<'a>(
|
||||
&'a mut self,
|
||||
words: &'a mut [&'a mut [u8]],
|
||||
) -> Self::ReadTransactionFuture<'a> {
|
||||
async move {
|
||||
for buf in words {
|
||||
self.read(buf).await?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_async::spi::Write<u8> for Spim<'d, T> {
|
||||
type WriteFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
impl<'d, T: Instance> embedded_hal_async::spi::SpiBusWrite<u8> for Spim<'d, T> {
|
||||
type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
self.write(data)
|
||||
}
|
||||
|
||||
type WriteTransactionFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
|
||||
fn write_transaction<'a>(
|
||||
&'a mut self,
|
||||
words: &'a [&'a [u8]],
|
||||
) -> Self::WriteTransactionFuture<'a> {
|
||||
async move {
|
||||
for buf in words {
|
||||
self.write(buf).await?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_async::spi::ReadWrite<u8> for Spim<'d, T> {
|
||||
type TransferFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
impl<'d, T: Instance> embedded_hal_async::spi::SpiBus<u8> for Spim<'d, T> {
|
||||
type TransferFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn transfer<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::TransferFuture<'a> {
|
||||
self.transfer(rx, tx)
|
||||
}
|
||||
|
||||
type TransferInPlaceFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type TransferInPlaceFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn transfer_in_place<'a>(
|
||||
&'a mut self,
|
||||
@ -600,28 +527,6 @@ mod eh1a {
|
||||
) -> Self::TransferInPlaceFuture<'a> {
|
||||
self.transfer_in_place(words)
|
||||
}
|
||||
|
||||
type TransactionFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
|
||||
fn transaction<'a>(
|
||||
&'a mut self,
|
||||
operations: &'a mut [embedded_hal_async::spi::Operation<'a, u8>],
|
||||
) -> Self::TransactionFuture<'a> {
|
||||
use embedded_hal_1::spi::blocking::Operation;
|
||||
async move {
|
||||
for o in operations {
|
||||
match o {
|
||||
Operation::Read(b) => self.read(b).await?,
|
||||
Operation::Write(b) => self.write(b).await?,
|
||||
Operation::Transfer(r, w) => self.transfer(r, w).await?,
|
||||
Operation::TransferInPlace(b) => self.transfer_in_place(b).await?,
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -743,30 +743,22 @@ mod eh1 {
|
||||
}
|
||||
}
|
||||
|
||||
#[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;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] {
|
||||
impl<'d, T: Instance> embedded_hal_async::i2c::I2c for Twim<'d, T> {
|
||||
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
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> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
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> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn write_read<'a>(
|
||||
&'a mut self,
|
||||
@ -777,18 +769,17 @@ impl<'d, T: Instance> embedded_hal_async::i2c::I2c for Twim<'d, T> {
|
||||
self.write_read(address, wr_buffer, rd_buffer)
|
||||
}
|
||||
|
||||
type TransactionFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type TransactionFuture<'a, 'b> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a, 'b: 'a;
|
||||
|
||||
fn transaction<'a>(
|
||||
fn transaction<'a, 'b>(
|
||||
&'a mut self,
|
||||
address: u8,
|
||||
operations: &mut [embedded_hal_async::i2c::Operation<'a>],
|
||||
) -> Self::TransactionFuture<'a> {
|
||||
operations: &'a mut [embedded_hal_async::i2c::Operation<'b>],
|
||||
) -> Self::TransactionFuture<'a, 'b> {
|
||||
let _ = address;
|
||||
let _ = operations;
|
||||
async move { todo!() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -934,16 +934,12 @@ mod eh1 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
|
||||
mod eh1a {
|
||||
use super::*;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] {
|
||||
use core::future::Future;
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_async::serial::Read for Uarte<'d, T> {
|
||||
type ReadFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn read<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
self.read(buffer)
|
||||
@ -951,19 +947,13 @@ mod eh1a {
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_async::serial::Write for Uarte<'d, T> {
|
||||
type WriteFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
self.write(buffer)
|
||||
}
|
||||
|
||||
type FlushFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
|
||||
async move { Ok(()) }
|
||||
@ -971,19 +961,13 @@ mod eh1a {
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_async::serial::Write for UarteTx<'d, T> {
|
||||
type WriteFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
self.write(buffer)
|
||||
}
|
||||
|
||||
type FlushFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
|
||||
async move { Ok(()) }
|
||||
@ -991,10 +975,7 @@ mod eh1a {
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_async::serial::Read for UarteRx<'d, T> {
|
||||
type ReadFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn read<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
self.read(buffer)
|
||||
@ -1004,10 +985,7 @@ mod eh1a {
|
||||
impl<'d, U: Instance, T: TimerInstance> embedded_hal_async::serial::Read
|
||||
for UarteWithIdle<'d, U, T>
|
||||
{
|
||||
type ReadFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn read<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
self.read(buffer)
|
||||
@ -1017,22 +995,17 @@ mod eh1a {
|
||||
impl<'d, U: Instance, T: TimerInstance> embedded_hal_async::serial::Write
|
||||
for UarteWithIdle<'d, U, T>
|
||||
{
|
||||
type WriteFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
self.write(buffer)
|
||||
}
|
||||
|
||||
type FlushFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
|
||||
async move { Ok(()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,5 +34,5 @@ rp2040-pac2 = { git = "https://github.com/embassy-rs/rp2040-pac2", rev="9ad7223a
|
||||
#rp2040-pac2 = { path = "../../rp/rp2040-pac2", features = ["rt"] }
|
||||
|
||||
embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
|
||||
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.6", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true}
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true}
|
||||
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.7", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy2", optional = true}
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy2", optional = true}
|
||||
|
@ -342,43 +342,25 @@ mod eh1 {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::Read<u8> for Spi<'d, T> {
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusFlush for Spi<'d, T> {
|
||||
fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusRead<u8> for Spi<'d, T> {
|
||||
fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
|
||||
self.blocking_transfer(words, &[])
|
||||
}
|
||||
|
||||
fn read_transaction(&mut self, words: &mut [&mut [u8]]) -> Result<(), Self::Error> {
|
||||
for buf in words {
|
||||
self.blocking_read(buf)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::Write<u8> for Spi<'d, T> {
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusWrite<u8> for Spi<'d, T> {
|
||||
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
|
||||
self.blocking_write(words)
|
||||
}
|
||||
|
||||
fn write_transaction(&mut self, words: &[&[u8]]) -> Result<(), Self::Error> {
|
||||
for buf in words {
|
||||
self.blocking_write(buf)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_iter<WI>(&mut self, words: WI) -> Result<(), Self::Error>
|
||||
where
|
||||
WI: IntoIterator<Item = u8>,
|
||||
{
|
||||
for w in words {
|
||||
self.blocking_write(&[w])?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::ReadWrite<u8> for Spi<'d, T> {
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBus<u8> for Spi<'d, T> {
|
||||
fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
|
||||
self.blocking_transfer(read, write)
|
||||
}
|
||||
@ -386,21 +368,5 @@ mod eh1 {
|
||||
fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
|
||||
self.blocking_transfer_in_place(words)
|
||||
}
|
||||
|
||||
fn transaction<'a>(
|
||||
&mut self,
|
||||
operations: &mut [embedded_hal_1::spi::blocking::Operation<'a, u8>],
|
||||
) -> Result<(), Self::Error> {
|
||||
use embedded_hal_1::spi::blocking::Operation;
|
||||
for o in operations {
|
||||
match o {
|
||||
Operation::Read(b) => self.blocking_read(b)?,
|
||||
Operation::Write(b) => self.blocking_write(b)?,
|
||||
Operation::Transfer(r, w) => self.blocking_transfer(r, w)?,
|
||||
Operation::TransferInPlace(b) => self.blocking_transfer_in_place(b)?,
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,8 +35,8 @@ embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
|
||||
embassy-net = { version = "0.1.0", path = "../embassy-net", default-features = false, optional = true }
|
||||
|
||||
embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
|
||||
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.6", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true}
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true}
|
||||
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.7", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy2", optional = true}
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy2", optional = true}
|
||||
|
||||
defmt = { version = "0.3", optional = true }
|
||||
log = { version = "0.4.14", optional = true }
|
||||
|
@ -45,7 +45,7 @@ pub struct Ethernet<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> {
|
||||
macro_rules! config_pins {
|
||||
($($pin:ident),*) => {
|
||||
// NOTE(unsafe) Exclusive access to the registers
|
||||
critical_section::with(|_| unsafe {
|
||||
critical_section::with(|_| {
|
||||
$(
|
||||
$pin.set_as_af($pin.af_num(), AFType::OutputPushPull);
|
||||
$pin.set_speed(Speed::VeryHigh);
|
||||
|
@ -36,7 +36,7 @@ pub struct Ethernet<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> {
|
||||
macro_rules! config_pins {
|
||||
($($pin:ident),*) => {
|
||||
// NOTE(unsafe) Exclusive access to the registers
|
||||
critical_section::with(|_| unsafe {
|
||||
critical_section::with(|_| {
|
||||
$(
|
||||
$pin.set_as_af($pin.af_num(), AFType::OutputPushPull);
|
||||
$pin.set_speed(Speed::VeryHigh);
|
||||
|
@ -165,57 +165,42 @@ mod eh1 {
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
|
||||
mod eh1a {
|
||||
use super::*;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] {
|
||||
use futures::FutureExt;
|
||||
|
||||
impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for ExtiInput<'d, T> {
|
||||
type WaitForHighFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WaitForHighFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_high<'a>(&'a mut self) -> Self::WaitForHighFuture<'a> {
|
||||
self.wait_for_high().map(Ok)
|
||||
}
|
||||
|
||||
type WaitForLowFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WaitForLowFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_low<'a>(&'a mut self) -> Self::WaitForLowFuture<'a> {
|
||||
self.wait_for_low().map(Ok)
|
||||
}
|
||||
|
||||
type WaitForRisingEdgeFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WaitForRisingEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_rising_edge<'a>(&'a mut self) -> Self::WaitForRisingEdgeFuture<'a> {
|
||||
self.wait_for_rising_edge().map(Ok)
|
||||
}
|
||||
|
||||
type WaitForFallingEdgeFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WaitForFallingEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_falling_edge<'a>(&'a mut self) -> Self::WaitForFallingEdgeFuture<'a> {
|
||||
self.wait_for_falling_edge().map(Ok)
|
||||
}
|
||||
|
||||
type WaitForAnyEdgeFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WaitForAnyEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_any_edge<'a>(&'a mut self) -> Self::WaitForAnyEdgeFuture<'a> {
|
||||
self.wait_for_any_edge().map(Ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ExtiInputFuture<'a> {
|
||||
|
@ -917,36 +917,26 @@ mod eh1 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
|
||||
mod eh1a {
|
||||
use super::super::{RxDma, TxDma};
|
||||
use super::*;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] {
|
||||
use super::{RxDma, TxDma};
|
||||
use core::future::Future;
|
||||
|
||||
impl<'d, T: Instance, TXDMA: TxDma<T>, RXDMA: RxDma<T>> embedded_hal_async::i2c::I2c
|
||||
for I2c<'d, T, TXDMA, RXDMA>
|
||||
{
|
||||
type ReadFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
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> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
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> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
fn write_read<'a>(
|
||||
&'a mut self,
|
||||
address: u8,
|
||||
@ -956,19 +946,17 @@ mod eh1a {
|
||||
self.write_read(address, bytes, buffer)
|
||||
}
|
||||
|
||||
type TransactionFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type TransactionFuture<'a, 'b> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a, 'b: 'a;
|
||||
|
||||
fn transaction<'a>(
|
||||
fn transaction<'a, 'b>(
|
||||
&'a mut self,
|
||||
address: u8,
|
||||
operations: &mut [embedded_hal_async::i2c::Operation<'a>],
|
||||
) -> Self::TransactionFuture<'a> {
|
||||
operations: &'a mut [embedded_hal_async::i2c::Operation<'b>],
|
||||
) -> Self::TransactionFuture<'a, 'b> {
|
||||
let _ = address;
|
||||
let _ = operations;
|
||||
async move { todo!() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -445,6 +445,15 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
|
||||
self.set_word_size(W::WORDSIZE);
|
||||
let regs = T::regs();
|
||||
for word in words.iter_mut() {
|
||||
*word = transfer_word(regs, W::default())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
|
||||
self.set_word_size(W::WORDSIZE);
|
||||
let regs = T::regs();
|
||||
@ -453,6 +462,21 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> {
|
||||
self.set_word_size(W::WORDSIZE);
|
||||
let regs = T::regs();
|
||||
|
||||
let len = read.len().max(write.len());
|
||||
for i in 0..len {
|
||||
let wb = write.get(i).copied().unwrap_or_default();
|
||||
let rb = transfer_word(regs, wb)?;
|
||||
if let Some(r) = read.get_mut(i) {
|
||||
*r = rb;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> {
|
||||
@ -669,6 +693,34 @@ mod eh1 {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx, Rx> embedded_hal_1::spi::blocking::SpiBusFlush for Spi<'d, T, Tx, Rx> {
|
||||
fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusRead<u8> for Spi<'d, T, NoDma, NoDma> {
|
||||
fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
|
||||
self.blocking_read(words)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusWrite<u8> for Spi<'d, T, NoDma, NoDma> {
|
||||
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
|
||||
self.blocking_write(words)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBus<u8> for Spi<'d, T, NoDma, NoDma> {
|
||||
fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
|
||||
self.blocking_transfer(read, write)
|
||||
}
|
||||
|
||||
fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
|
||||
self.blocking_transfer_in_place(words)
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_hal_1::spi::Error for Error {
|
||||
fn kind(&self) -> embedded_hal_1::spi::ErrorKind {
|
||||
match *self {
|
||||
@ -681,85 +733,47 @@ mod eh1 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
|
||||
mod eh1a {
|
||||
use super::*;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] {
|
||||
use core::future::Future;
|
||||
impl<'d, T: Instance, Tx, Rx> embedded_hal_async::spi::SpiBusFlush for Spi<'d, T, Tx, Rx> {
|
||||
type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
impl<'d, T: Instance, Tx: TxDma<T>, Rx> embedded_hal_async::spi::Write<u8> for Spi<'d, T, Tx, Rx> {
|
||||
type WriteFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
|
||||
async { Ok(()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx: TxDma<T>, Rx> embedded_hal_async::spi::SpiBusWrite<u8>
|
||||
for Spi<'d, T, Tx, Rx>
|
||||
{
|
||||
type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
self.write(data)
|
||||
}
|
||||
|
||||
type WriteTransactionFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
|
||||
fn write_transaction<'a>(
|
||||
&'a mut self,
|
||||
words: &'a [&'a [u8]],
|
||||
) -> Self::WriteTransactionFuture<'a> {
|
||||
async move {
|
||||
for buf in words {
|
||||
self.write(buf).await?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx: TxDma<T>, Rx: RxDma<T>> embedded_hal_async::spi::Read<u8>
|
||||
impl<'d, T: Instance, Tx: TxDma<T>, Rx: RxDma<T>> embedded_hal_async::spi::SpiBusRead<u8>
|
||||
for Spi<'d, T, Tx, Rx>
|
||||
{
|
||||
type ReadFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
self.read(data)
|
||||
}
|
||||
|
||||
type ReadTransactionFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
|
||||
fn read_transaction<'a>(
|
||||
&'a mut self,
|
||||
words: &'a mut [&'a mut [u8]],
|
||||
) -> Self::ReadTransactionFuture<'a> {
|
||||
async move {
|
||||
for buf in words {
|
||||
self.read(buf).await?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, Tx: TxDma<T>, Rx: RxDma<T>> embedded_hal_async::spi::ReadWrite<u8>
|
||||
impl<'d, T: Instance, Tx: TxDma<T>, Rx: RxDma<T>> embedded_hal_async::spi::SpiBus<u8>
|
||||
for Spi<'d, T, Tx, Rx>
|
||||
{
|
||||
type TransferFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type TransferFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn transfer<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::TransferFuture<'a> {
|
||||
self.transfer(rx, tx)
|
||||
}
|
||||
|
||||
type TransferInPlaceFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type TransferInPlaceFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn transfer_in_place<'a>(
|
||||
&'a mut self,
|
||||
@ -769,28 +783,6 @@ mod eh1a {
|
||||
let result = self.blocking_transfer_in_place(words);
|
||||
async move { result }
|
||||
}
|
||||
|
||||
type TransactionFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
|
||||
fn transaction<'a>(
|
||||
&'a mut self,
|
||||
operations: &'a mut [embedded_hal_async::spi::Operation<'a, u8>],
|
||||
) -> Self::TransactionFuture<'a> {
|
||||
use embedded_hal_1::spi::blocking::Operation;
|
||||
async move {
|
||||
for o in operations {
|
||||
match o {
|
||||
Operation::Read(b) => self.read(b).await?,
|
||||
Operation::Write(b) => self.write(b).await?,
|
||||
Operation::Transfer(r, w) => self.transfer(r, w).await?,
|
||||
Operation::TransferInPlace(b) => self.transfer_in_place(b).await?,
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -862,7 +854,7 @@ pub(crate) mod sealed {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Word: Copy + 'static + sealed::Word {}
|
||||
pub trait Word: Copy + 'static + sealed::Word + Default {}
|
||||
|
||||
impl Word for u8 {}
|
||||
impl Word for u16 {}
|
||||
|
@ -275,28 +275,21 @@ mod eh1 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
|
||||
mod eh1a {
|
||||
use super::*;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] {
|
||||
use core::future::Future;
|
||||
|
||||
impl<'d, T: Instance, TxDma, RxDma> embedded_hal_async::serial::Write for Uart<'d, T, TxDma, RxDma>
|
||||
where
|
||||
TxDma: crate::usart::TxDma<T>,
|
||||
{
|
||||
type WriteFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
self.write(buf)
|
||||
}
|
||||
|
||||
type FlushFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
|
||||
async move { Ok(()) }
|
||||
@ -307,15 +300,13 @@ mod eh1a {
|
||||
where
|
||||
RxDma: crate::usart::RxDma<T>,
|
||||
{
|
||||
type ReadFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
self.read(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub use buffered::*;
|
||||
|
@ -9,8 +9,8 @@ std = []
|
||||
|
||||
[dependencies]
|
||||
embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
|
||||
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.6", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy" }
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy"}
|
||||
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.7", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy2" }
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy2"}
|
||||
embedded-storage = "0.3.0"
|
||||
embedded-storage-async = "0.3.0"
|
||||
nb = "1.0.0"
|
||||
|
@ -39,18 +39,9 @@ where
|
||||
+ blocking::i2c::Read<Error = E>
|
||||
+ blocking::i2c::Write<Error = E>,
|
||||
{
|
||||
type WriteFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type ReadFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WriteReadFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
type WriteReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
async move { self.wrapped.read(address, buffer) }
|
||||
@ -69,16 +60,13 @@ where
|
||||
async move { self.wrapped.write_read(address, bytes, buffer) }
|
||||
}
|
||||
|
||||
type TransactionFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type TransactionFuture<'a, 'b> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a, 'b: 'a;
|
||||
|
||||
fn transaction<'a>(
|
||||
fn transaction<'a, 'b>(
|
||||
&'a mut self,
|
||||
address: u8,
|
||||
operations: &mut [embedded_hal_async::i2c::Operation<'a>],
|
||||
) -> Self::TransactionFuture<'a> {
|
||||
operations: &'a mut [embedded_hal_async::i2c::Operation<'b>],
|
||||
) -> Self::TransactionFuture<'a, 'b> {
|
||||
let _ = address;
|
||||
let _ = operations;
|
||||
async move { todo!() }
|
||||
@ -97,15 +85,12 @@ where
|
||||
type Error = E;
|
||||
}
|
||||
|
||||
impl<T, E> embedded_hal_async::spi::ReadWrite<u8> for BlockingAsync<T>
|
||||
impl<T, E> embedded_hal_async::spi::SpiBus<u8> for BlockingAsync<T>
|
||||
where
|
||||
E: embedded_hal_1::spi::Error + 'static,
|
||||
T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
|
||||
{
|
||||
type TransferFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type TransferFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn transfer<'a>(&'a mut self, read: &'a mut [u8], write: &'a [u8]) -> Self::TransferFuture<'a> {
|
||||
async move {
|
||||
@ -118,37 +103,31 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
type TransferInPlaceFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type TransferInPlaceFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn transfer_in_place<'a>(&'a mut self, _: &'a mut [u8]) -> Self::TransferInPlaceFuture<'a> {
|
||||
async move { todo!() }
|
||||
}
|
||||
|
||||
type TransactionFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
|
||||
fn transaction<'a>(
|
||||
&'a mut self,
|
||||
_: &'a mut [embedded_hal_async::spi::Operation<'a, u8>],
|
||||
) -> Self::TransactionFuture<'a> {
|
||||
async move { todo!() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> embedded_hal_async::spi::Write<u8> for BlockingAsync<T>
|
||||
impl<T, E> embedded_hal_async::spi::SpiBusFlush for BlockingAsync<T>
|
||||
where
|
||||
E: embedded_hal_1::spi::Error + 'static,
|
||||
T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
|
||||
{
|
||||
type WriteFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
|
||||
async move { Ok(()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> embedded_hal_async::spi::SpiBusWrite<u8> for BlockingAsync<T>
|
||||
where
|
||||
E: embedded_hal_1::spi::Error + 'static,
|
||||
T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
|
||||
{
|
||||
type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
async move {
|
||||
@ -156,26 +135,14 @@ where
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
type WriteTransactionFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
|
||||
fn write_transaction<'a>(&'a mut self, _: &'a [&'a [u8]]) -> Self::WriteTransactionFuture<'a> {
|
||||
async move { todo!() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> embedded_hal_async::spi::Read<u8> for BlockingAsync<T>
|
||||
impl<T, E> embedded_hal_async::spi::SpiBusRead<u8> for BlockingAsync<T>
|
||||
where
|
||||
E: embedded_hal_1::spi::Error + 'static,
|
||||
T: blocking::spi::Transfer<u8, Error = E> + blocking::spi::Write<u8, Error = E>,
|
||||
{
|
||||
type ReadFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
async move {
|
||||
@ -183,18 +150,6 @@ where
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
type ReadTransactionFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
|
||||
fn read_transaction<'a>(
|
||||
&'a mut self,
|
||||
_: &'a mut [&'a mut [u8]],
|
||||
) -> Self::ReadTransactionFuture<'a> {
|
||||
async move { todo!() }
|
||||
}
|
||||
}
|
||||
|
||||
// Uart implementatinos
|
||||
@ -211,10 +166,7 @@ where
|
||||
T: serial::Read<u8, Error = E>,
|
||||
E: embedded_hal_1::serial::Error + 'static,
|
||||
{
|
||||
type ReadFuture<'a>
|
||||
where
|
||||
T: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where T: 'a;
|
||||
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
async move {
|
||||
let mut pos = 0;
|
||||
@ -238,18 +190,12 @@ where
|
||||
T: blocking::serial::Write<u8, Error = E> + serial::Read<u8, Error = E>,
|
||||
E: embedded_hal_1::serial::Error + 'static,
|
||||
{
|
||||
type WriteFuture<'a>
|
||||
where
|
||||
T: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where T: 'a;
|
||||
fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
async move { self.wrapped.bwrite_all(buf) }
|
||||
}
|
||||
|
||||
type FlushFuture<'a>
|
||||
where
|
||||
T: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where T: 'a;
|
||||
fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
|
||||
async move { self.wrapped.bflush() }
|
||||
}
|
||||
@ -273,18 +219,12 @@ where
|
||||
const WRITE_SIZE: usize = <T as NorFlash>::WRITE_SIZE;
|
||||
const ERASE_SIZE: usize = <T as NorFlash>::ERASE_SIZE;
|
||||
|
||||
type WriteFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
fn write<'a>(&'a mut self, offset: u32, data: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
async move { self.wrapped.write(offset, data) }
|
||||
}
|
||||
|
||||
type EraseFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type EraseFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
fn erase<'a>(&'a mut self, from: u32, to: u32) -> Self::EraseFuture<'a> {
|
||||
async move { self.wrapped.erase(from, to) }
|
||||
}
|
||||
@ -295,10 +235,7 @@ where
|
||||
T: ReadNorFlash,
|
||||
{
|
||||
const READ_SIZE: usize = <T as ReadNorFlash>::READ_SIZE;
|
||||
type ReadFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
fn read<'a>(&'a mut self, address: u32, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
async move { self.wrapped.read(address, data) }
|
||||
}
|
||||
|
@ -55,8 +55,8 @@ defmt = { version = "0.3", optional = true }
|
||||
log = { version = "0.4.14", optional = true }
|
||||
|
||||
embedded-hal-02 = { package = "embedded-hal", version = "0.2.6" }
|
||||
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.6", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true}
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true}
|
||||
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.7", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy2", optional = true}
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy2", optional = true}
|
||||
|
||||
futures = { version = "0.3.17", default-features = false, features = [ "cfg-target-has-atomic", "unstable" ] }
|
||||
pin-project = { version = "1.0.8", default-features = false }
|
||||
|
@ -1,12 +1,7 @@
|
||||
#![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)]
|
||||
#![cfg_attr(
|
||||
feature = "nightly",
|
||||
feature(
|
||||
const_fn_trait_bound,
|
||||
const_fn_fn_ptr_basics,
|
||||
generic_associated_types,
|
||||
type_alias_impl_trait
|
||||
)
|
||||
feature(generic_associated_types, type_alias_impl_trait)
|
||||
)]
|
||||
#![allow(clippy::new_without_default)]
|
||||
|
||||
|
@ -31,9 +31,8 @@ mod eh1 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
|
||||
mod eh1a {
|
||||
use super::*;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] {
|
||||
use crate::time::Timer;
|
||||
use core::future::Future;
|
||||
use futures::FutureExt;
|
||||
@ -41,24 +40,19 @@ mod eh1a {
|
||||
impl embedded_hal_async::delay::DelayUs for Delay {
|
||||
type Error = core::convert::Infallible;
|
||||
|
||||
type DelayUsFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type DelayUsFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn delay_us(&mut self, micros: u32) -> Self::DelayUsFuture<'_> {
|
||||
Timer::after(Duration::from_micros(micros as _)).map(Ok)
|
||||
}
|
||||
|
||||
type DelayMsFuture<'a>
|
||||
where
|
||||
Self: 'a,
|
||||
= impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||
type DelayMsFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn delay_ms(&mut self, millis: u32) -> Self::DelayMsFuture<'_> {
|
||||
Timer::after(Duration::from_millis(millis as _)).map(Ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod eh02 {
|
||||
|
@ -6,7 +6,7 @@ version = "0.1.0"
|
||||
|
||||
[features]
|
||||
default = ["nightly"]
|
||||
nightly = ["embassy-nrf/nightly"]
|
||||
nightly = ["embassy-nrf/nightly", "embassy-nrf/unstable-traits"]
|
||||
|
||||
[dependencies]
|
||||
embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt"] }
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
authors = ["Dario Nieuwenhuis <dirbaio@dirbaio.net>"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
name = "embassy-rp-examples"
|
||||
version = "0.1.0"
|
||||
|
||||
@ -15,9 +15,12 @@ defmt-rtt = "0.3"
|
||||
|
||||
cortex-m = "0.7.3"
|
||||
cortex-m-rt = "0.7.0"
|
||||
embedded-hal = "0.2.6"
|
||||
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||
futures = { version = "0.3.17", default-features = false, features = ["async-await", "cfg-target-has-atomic", "unstable"] }
|
||||
display-interface-spi = "0.4.1"
|
||||
embedded-graphics = "0.7.1"
|
||||
st7789 = "0.6.1"
|
||||
|
||||
embedded-hal = { version = "1.0.0-alpha.7", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy2" }
|
||||
display-interface = "0.4.1"
|
||||
byte-slice-cast = { version = "1.2.0", default-features = false }
|
||||
|
@ -6,16 +6,14 @@
|
||||
mod example_common;
|
||||
|
||||
use core::cell::RefCell;
|
||||
use core::fmt::Debug;
|
||||
|
||||
use defmt::*;
|
||||
use display_interface_spi::SPIInterfaceNoCS;
|
||||
use embassy::executor::Spawner;
|
||||
use embassy::time::Delay;
|
||||
use embassy_rp::peripherals;
|
||||
use embassy_rp::gpio::{Level, Output};
|
||||
use embassy_rp::spi;
|
||||
use embassy_rp::spi::Spi;
|
||||
use embassy_rp::{gpio, Peripherals};
|
||||
use embassy_rp::Peripherals;
|
||||
use embedded_graphics::image::{Image, ImageRawLE};
|
||||
use embedded_graphics::mono_font::ascii::FONT_10X20;
|
||||
use embedded_graphics::mono_font::MonoTextStyle;
|
||||
@ -23,9 +21,15 @@ use embedded_graphics::pixelcolor::Rgb565;
|
||||
use embedded_graphics::prelude::*;
|
||||
use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle};
|
||||
use embedded_graphics::text::Text;
|
||||
use gpio::{Level, Output};
|
||||
use st7789::{Orientation, ST7789};
|
||||
|
||||
use crate::my_display_interface::SPIDeviceInterface;
|
||||
use crate::shared_spi::SpiDeviceWithCs;
|
||||
use crate::touch::Touch;
|
||||
|
||||
//const DISPLAY_FREQ: u32 = 64_000_000;
|
||||
const TOUCH_FREQ: u32 = 200_000;
|
||||
|
||||
#[embassy::main]
|
||||
async fn main(_spawner: Spawner, p: Peripherals) {
|
||||
info!("Hello World!");
|
||||
@ -42,17 +46,16 @@ async fn main(_spawner: Spawner, p: Peripherals) {
|
||||
|
||||
// create SPI
|
||||
let mut config = spi::Config::default();
|
||||
config.frequency = DISPLAY_FREQ;
|
||||
config.frequency = TOUCH_FREQ; // use the lowest freq
|
||||
config.phase = spi::Phase::CaptureOnSecondTransition;
|
||||
config.polarity = spi::Polarity::IdleHigh;
|
||||
|
||||
let spi = RefCell::new(SpiState {
|
||||
last_mode: SpiMode::Display,
|
||||
spi: Spi::new(p.SPI1, clk, mosi, miso, config),
|
||||
display_cs: Output::new(display_cs, Level::Low),
|
||||
});
|
||||
let spi_bus = RefCell::new(Spi::new(p.SPI1, clk, mosi, miso, config));
|
||||
|
||||
let mut touch = Touch::new(TouchSpi(&spi), Output::new(touch_cs, Level::High));
|
||||
let display_spi = SpiDeviceWithCs::new(&spi_bus, Output::new(display_cs, Level::High));
|
||||
let touch_spi = SpiDeviceWithCs::new(&spi_bus, Output::new(touch_cs, Level::High));
|
||||
|
||||
let mut touch = Touch::new(touch_spi);
|
||||
|
||||
let dcx = Output::new(dcx, Level::Low);
|
||||
let rst = Output::new(rst, Level::Low);
|
||||
@ -62,7 +65,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
|
||||
let _bl = Output::new(bl, Level::High);
|
||||
|
||||
// display interface abstraction from SPI and DC
|
||||
let di = SPIInterfaceNoCS::new(DisplaySpi(&spi), dcx);
|
||||
let di = SPIDeviceInterface::new(display_spi, dcx);
|
||||
|
||||
// create driver
|
||||
let mut display = ST7789::new(di, rst, 240, 320);
|
||||
@ -104,98 +107,132 @@ async fn main(_spawner: Spawner, p: Peripherals) {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum SpiMode {
|
||||
Display,
|
||||
Touch,
|
||||
}
|
||||
mod shared_spi {
|
||||
use core::cell::RefCell;
|
||||
use core::fmt::Debug;
|
||||
|
||||
struct SpiState {
|
||||
spi: Spi<'static, peripherals::SPI1>,
|
||||
display_cs: Output<'static, peripherals::PIN_9>,
|
||||
use embedded_hal::digital::blocking::OutputPin;
|
||||
use embedded_hal::spi;
|
||||
use embedded_hal::spi::blocking::SpiDevice;
|
||||
|
||||
last_mode: SpiMode,
|
||||
}
|
||||
|
||||
const DISPLAY_FREQ: u32 = 64_000_000;
|
||||
const TOUCH_FREQ: u32 = 200_000;
|
||||
|
||||
struct DisplaySpi<'a>(&'a RefCell<SpiState>);
|
||||
impl<'a> embedded_hal::blocking::spi::Write<u8> for DisplaySpi<'a> {
|
||||
type Error = core::convert::Infallible;
|
||||
|
||||
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
|
||||
let this = &mut *self.0.borrow_mut();
|
||||
if this.last_mode != SpiMode::Display {
|
||||
this.spi.set_frequency(DISPLAY_FREQ);
|
||||
this.display_cs.set_low();
|
||||
this.last_mode = SpiMode::Display;
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub enum SpiDeviceWithCsError<BUS, CS> {
|
||||
#[allow(unused)] // will probably use in the future when adding a flush() to SpiBus
|
||||
Spi(BUS),
|
||||
Cs(CS),
|
||||
}
|
||||
|
||||
impl<BUS, CS> spi::Error for SpiDeviceWithCsError<BUS, CS>
|
||||
where
|
||||
BUS: spi::Error + Debug,
|
||||
CS: Debug,
|
||||
{
|
||||
fn kind(&self) -> spi::ErrorKind {
|
||||
match self {
|
||||
Self::Spi(e) => e.kind(),
|
||||
Self::Cs(_) => spi::ErrorKind::Other,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SpiDeviceWithCs<'a, BUS, CS> {
|
||||
bus: &'a RefCell<BUS>,
|
||||
cs: CS,
|
||||
}
|
||||
|
||||
impl<'a, BUS, CS> SpiDeviceWithCs<'a, BUS, CS> {
|
||||
pub fn new(bus: &'a RefCell<BUS>, cs: CS) -> Self {
|
||||
Self { bus, cs }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, BUS, CS> spi::ErrorType for SpiDeviceWithCs<'a, BUS, CS>
|
||||
where
|
||||
BUS: spi::ErrorType,
|
||||
CS: OutputPin,
|
||||
{
|
||||
type Error = SpiDeviceWithCsError<BUS::Error, CS::Error>;
|
||||
}
|
||||
|
||||
impl<'a, BUS, CS> SpiDevice for SpiDeviceWithCs<'a, BUS, CS>
|
||||
where
|
||||
BUS: spi::blocking::SpiBusFlush,
|
||||
CS: OutputPin,
|
||||
{
|
||||
type Bus = BUS;
|
||||
|
||||
fn transaction<R>(
|
||||
&mut self,
|
||||
f: impl FnOnce(&mut Self::Bus) -> Result<R, BUS::Error>,
|
||||
) -> Result<R, Self::Error> {
|
||||
let mut bus = self.bus.borrow_mut();
|
||||
self.cs.set_low().map_err(SpiDeviceWithCsError::Cs)?;
|
||||
|
||||
let f_res = f(&mut bus);
|
||||
|
||||
// On failure, it's important to still flush and deassert CS.
|
||||
let flush_res = bus.flush();
|
||||
let cs_res = self.cs.set_high();
|
||||
|
||||
let f_res = f_res.map_err(SpiDeviceWithCsError::Spi)?;
|
||||
flush_res.map_err(SpiDeviceWithCsError::Spi)?;
|
||||
cs_res.map_err(SpiDeviceWithCsError::Cs)?;
|
||||
|
||||
Ok(f_res)
|
||||
}
|
||||
this.spi.write(words).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct TouchSpi<'a>(&'a RefCell<SpiState>);
|
||||
impl<'a> embedded_hal::blocking::spi::Transfer<u8> for TouchSpi<'a> {
|
||||
type Error = core::convert::Infallible;
|
||||
/// Driver for the XPT2046 resistive touchscreen sensor
|
||||
mod touch {
|
||||
use embedded_hal::spi::blocking::{SpiBus, SpiBusRead, SpiBusWrite, SpiDevice};
|
||||
|
||||
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
|
||||
let this = &mut *self.0.borrow_mut();
|
||||
if this.last_mode != SpiMode::Touch {
|
||||
this.spi.set_frequency(TOUCH_FREQ);
|
||||
this.display_cs.set_high();
|
||||
this.last_mode = SpiMode::Touch;
|
||||
}
|
||||
this.spi.transfer(words).unwrap();
|
||||
Ok(words)
|
||||
}
|
||||
}
|
||||
|
||||
struct Calibration {
|
||||
struct Calibration {
|
||||
x1: i32,
|
||||
x2: i32,
|
||||
y1: i32,
|
||||
y2: i32,
|
||||
sx: i32,
|
||||
sy: i32,
|
||||
}
|
||||
}
|
||||
|
||||
const CALIBRATION: Calibration = Calibration {
|
||||
const CALIBRATION: Calibration = Calibration {
|
||||
x1: 3880,
|
||||
x2: 340,
|
||||
y1: 262,
|
||||
y2: 3850,
|
||||
sx: 320,
|
||||
sy: 240,
|
||||
};
|
||||
};
|
||||
|
||||
struct Touch<
|
||||
SPI: embedded_hal::blocking::spi::Transfer<u8>,
|
||||
CS: embedded_hal::digital::v2::OutputPin,
|
||||
> {
|
||||
pub struct Touch<SPI: SpiDevice> {
|
||||
spi: SPI,
|
||||
cs: CS,
|
||||
}
|
||||
}
|
||||
|
||||
impl<SPI: embedded_hal::blocking::spi::Transfer<u8>, CS: embedded_hal::digital::v2::OutputPin>
|
||||
Touch<SPI, CS>
|
||||
where
|
||||
SPI::Error: Debug,
|
||||
CS::Error: Debug,
|
||||
{
|
||||
pub fn new(spi: SPI, cs: CS) -> Self {
|
||||
Self { spi, cs }
|
||||
impl<SPI> Touch<SPI>
|
||||
where
|
||||
SPI: SpiDevice,
|
||||
SPI::Bus: SpiBus,
|
||||
{
|
||||
pub fn new(spi: SPI) -> Self {
|
||||
Self { spi }
|
||||
}
|
||||
|
||||
pub fn read(&mut self) -> Option<(i32, i32)> {
|
||||
self.cs.set_low().unwrap();
|
||||
let mut buf = [0x90, 0x00, 0x00, 0xd0, 0x00, 0x00];
|
||||
self.spi.transfer(&mut buf).unwrap();
|
||||
self.cs.set_high().unwrap();
|
||||
let mut x = [0; 2];
|
||||
let mut y = [0; 2];
|
||||
self.spi
|
||||
.transaction(|bus| {
|
||||
bus.write(&[0x90])?;
|
||||
bus.read(&mut x)?;
|
||||
bus.write(&[0xd0])?;
|
||||
bus.read(&mut y)?;
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let x = ((buf[1] as u32) << 5 | (buf[2] as u32) >> 3) as i32;
|
||||
let y = ((buf[4] as u32) << 5 | (buf[5] as u32) >> 3) as i32;
|
||||
let x = (u16::from_be_bytes(x) >> 3) as i32;
|
||||
let y = (u16::from_be_bytes(y) >> 3) as i32;
|
||||
|
||||
let cal = &CALIBRATION;
|
||||
|
||||
@ -207,4 +244,156 @@ where
|
||||
Some((x, y))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod my_display_interface {
|
||||
use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand};
|
||||
use embedded_hal::digital::blocking::OutputPin;
|
||||
use embedded_hal::spi::blocking::{SpiBusWrite, SpiDevice};
|
||||
|
||||
/// SPI display interface.
|
||||
///
|
||||
/// This combines the SPI peripheral and a data/command pin
|
||||
pub struct SPIDeviceInterface<SPI, DC> {
|
||||
spi: SPI,
|
||||
dc: DC,
|
||||
}
|
||||
|
||||
impl<SPI, DC> SPIDeviceInterface<SPI, DC>
|
||||
where
|
||||
SPI: SpiDevice,
|
||||
SPI::Bus: SpiBusWrite,
|
||||
DC: OutputPin,
|
||||
{
|
||||
/// Create new SPI interface for communciation with a display driver
|
||||
pub fn new(spi: SPI, dc: DC) -> Self {
|
||||
Self { spi, dc }
|
||||
}
|
||||
}
|
||||
|
||||
impl<SPI, DC> WriteOnlyDataCommand for SPIDeviceInterface<SPI, DC>
|
||||
where
|
||||
SPI: SpiDevice,
|
||||
SPI::Bus: SpiBusWrite,
|
||||
DC: OutputPin,
|
||||
{
|
||||
fn send_commands(&mut self, cmds: DataFormat<'_>) -> Result<(), DisplayError> {
|
||||
let r = self.spi.transaction(|bus| {
|
||||
// 1 = data, 0 = command
|
||||
if let Err(_) = self.dc.set_low() {
|
||||
return Ok(Err(DisplayError::DCError));
|
||||
}
|
||||
|
||||
// Send words over SPI
|
||||
send_u8(bus, cmds)?;
|
||||
|
||||
Ok(Ok(()))
|
||||
});
|
||||
r.map_err(|_| DisplayError::BusWriteError)?
|
||||
}
|
||||
|
||||
fn send_data(&mut self, buf: DataFormat<'_>) -> Result<(), DisplayError> {
|
||||
let r = self.spi.transaction(|bus| {
|
||||
// 1 = data, 0 = command
|
||||
if let Err(_) = self.dc.set_high() {
|
||||
return Ok(Err(DisplayError::DCError));
|
||||
}
|
||||
|
||||
// Send words over SPI
|
||||
send_u8(bus, buf)?;
|
||||
|
||||
Ok(Ok(()))
|
||||
});
|
||||
r.map_err(|_| DisplayError::BusWriteError)?
|
||||
}
|
||||
}
|
||||
|
||||
fn send_u8<T: SpiBusWrite>(spi: &mut T, words: DataFormat<'_>) -> Result<(), T::Error> {
|
||||
match words {
|
||||
DataFormat::U8(slice) => spi.write(slice),
|
||||
DataFormat::U16(slice) => {
|
||||
use byte_slice_cast::*;
|
||||
spi.write(slice.as_byte_slice())
|
||||
}
|
||||
DataFormat::U16LE(slice) => {
|
||||
use byte_slice_cast::*;
|
||||
for v in slice.as_mut() {
|
||||
*v = v.to_le();
|
||||
}
|
||||
spi.write(slice.as_byte_slice())
|
||||
}
|
||||
DataFormat::U16BE(slice) => {
|
||||
use byte_slice_cast::*;
|
||||
for v in slice.as_mut() {
|
||||
*v = v.to_be();
|
||||
}
|
||||
spi.write(slice.as_byte_slice())
|
||||
}
|
||||
DataFormat::U8Iter(iter) => {
|
||||
let mut buf = [0; 32];
|
||||
let mut i = 0;
|
||||
|
||||
for v in iter.into_iter() {
|
||||
buf[i] = v;
|
||||
i += 1;
|
||||
|
||||
if i == buf.len() {
|
||||
spi.write(&buf)?;
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if i > 0 {
|
||||
spi.write(&buf[..i])?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
DataFormat::U16LEIter(iter) => {
|
||||
use byte_slice_cast::*;
|
||||
let mut buf = [0; 32];
|
||||
let mut i = 0;
|
||||
|
||||
for v in iter.map(u16::to_le) {
|
||||
buf[i] = v;
|
||||
i += 1;
|
||||
|
||||
if i == buf.len() {
|
||||
spi.write(&buf.as_byte_slice())?;
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if i > 0 {
|
||||
spi.write(&buf[..i].as_byte_slice())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
DataFormat::U16BEIter(iter) => {
|
||||
use byte_slice_cast::*;
|
||||
let mut buf = [0; 64];
|
||||
let mut i = 0;
|
||||
let len = buf.len();
|
||||
|
||||
for v in iter.map(u16::to_be) {
|
||||
buf[i] = v;
|
||||
i += 1;
|
||||
|
||||
if i == len {
|
||||
spi.write(&buf.as_byte_slice())?;
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if i > 0 {
|
||||
spi.write(&buf[..i].as_byte_slice())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ resolver = "2"
|
||||
|
||||
[dependencies]
|
||||
embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "unstable-traits"] }
|
||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "usb-otg"] }
|
||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "usb-otg"] }
|
||||
|
||||
defmt = "0.3"
|
||||
defmt-rtt = "0.3"
|
||||
|
@ -19,7 +19,7 @@ defmt-rtt = "0.3"
|
||||
cortex-m = "0.7.3"
|
||||
cortex-m-rt = "0.7.0"
|
||||
embedded-hal = "0.2.6"
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy"}
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy2"}
|
||||
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
||||
heapless = { version = "0.7.5", default-features = false }
|
||||
|
@ -18,7 +18,7 @@ defmt-rtt = "0.3"
|
||||
cortex-m = "0.7.3"
|
||||
cortex-m-rt = "0.7.0"
|
||||
embedded-hal = "0.2.6"
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy"}
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy2"}
|
||||
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
||||
heapless = { version = "0.7.5", default-features = false }
|
||||
|
@ -12,7 +12,7 @@ use embassy_stm32::spi::{Config, Spi};
|
||||
use embassy_stm32::time::Hertz;
|
||||
use embassy_stm32::Peripherals;
|
||||
use embassy_traits::adapter::BlockingAsync;
|
||||
use embedded_hal_async::spi::ReadWrite;
|
||||
use embedded_hal_async::spi::SpiBus;
|
||||
use example_common::*;
|
||||
|
||||
#[embassy::main]
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Before upgrading check that everything is available on all tier1 targets here:
|
||||
# https://rust-lang.github.io/rustup-components-history
|
||||
[toolchain]
|
||||
channel = "nightly-2022-02-20"
|
||||
channel = "nightly-2022-03-10"
|
||||
components = [ "rust-src", "rustfmt" ]
|
||||
targets = [ "thumbv7em-none-eabi", "thumbv7m-none-eabi", "thumbv6m-none-eabi", "thumbv7em-none-eabihf", "thumbv8m.main-none-eabihf", "wasm32-unknown-unknown" ]
|
||||
|
@ -23,7 +23,7 @@ defmt-rtt = "0.3.0"
|
||||
cortex-m = "0.7.3"
|
||||
cortex-m-rt = "0.7.0"
|
||||
embedded-hal = "0.2.6"
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy"}
|
||||
embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy2"}
|
||||
panic-probe = { version = "0.3.0", features = ["print-defmt"] }
|
||||
|
||||
[profile.dev]
|
||||
|
Loading…
Reference in New Issue
Block a user