rp: impl eh1.0 blocking traits
This commit is contained in:
parent
d7aea31a85
commit
d9aec181a4
@ -12,6 +12,13 @@ edition = "2018"
|
||||
# There are no plans to make this stable.
|
||||
unstable-pac = []
|
||||
|
||||
# Enable nightly-only features
|
||||
nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async"]
|
||||
|
||||
# Implement embedded-hal 1.0 alpha traits.
|
||||
# Implement embedded-hal-async traits if `nightly` is set as well.
|
||||
unstable-traits = ["embedded-hal-1"]
|
||||
|
||||
[dependencies]
|
||||
embassy = { version = "0.1.0", path = "../embassy", features = [ "time-tick-1mhz", "nightly"] }
|
||||
embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
|
||||
@ -25,4 +32,7 @@ critical-section = "0.2.5"
|
||||
|
||||
rp2040-pac2 = { git = "https://github.com/embassy-rs/rp2040-pac2", rev="9ad7223a48a065e612bc7dc7be5bf5bd0b41cfc4", features = ["rt"] }
|
||||
#rp2040-pac2 = { path = "../../rp/rp2040-pac2", features = ["rt"] }
|
||||
embedded-hal = { version = "0.2.6", features = [ "unproven" ] }
|
||||
|
||||
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}
|
||||
|
@ -8,7 +8,6 @@ use crate::peripherals;
|
||||
|
||||
use embassy::util::Unborrow;
|
||||
use embassy_hal_common::{unborrow, unsafe_impl_unborrow};
|
||||
use embedded_hal::digital::v2 as digital;
|
||||
|
||||
/// Represents a digital input or output level.
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
@ -81,18 +80,6 @@ impl<'d, T: Pin> Drop for Input<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Pin> digital::InputPin for Input<'d, T> {
|
||||
type Error = Infallible;
|
||||
|
||||
fn is_high(&self) -> Result<bool, Self::Error> {
|
||||
Ok(self.is_high())
|
||||
}
|
||||
|
||||
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||
Ok(self.is_low())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Output<'d, T: Pin> {
|
||||
pin: T,
|
||||
phantom: PhantomData<&'d mut T>,
|
||||
@ -151,34 +138,6 @@ impl<'d, T: Pin> Drop for Output<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Pin> digital::OutputPin for Output<'d, T> {
|
||||
type Error = Infallible;
|
||||
|
||||
/// Set the output as high.
|
||||
fn set_high(&mut self) -> Result<(), Self::Error> {
|
||||
self.set_high();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the output as low.
|
||||
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||
self.set_low();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Pin> digital::StatefulOutputPin for Output<'d, T> {
|
||||
/// Is the output pin set as high?
|
||||
fn is_set_high(&self) -> Result<bool, Self::Error> {
|
||||
Ok(self.is_set_high())
|
||||
}
|
||||
|
||||
/// Is the output pin set as low?
|
||||
fn is_set_low(&self) -> Result<bool, Self::Error> {
|
||||
Ok(self.is_set_low())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod sealed {
|
||||
use super::*;
|
||||
|
||||
@ -296,3 +255,86 @@ impl_pin!(PIN_QSPI_SD0, Bank::Qspi, 2);
|
||||
impl_pin!(PIN_QSPI_SD1, Bank::Qspi, 3);
|
||||
impl_pin!(PIN_QSPI_SD2, Bank::Qspi, 4);
|
||||
impl_pin!(PIN_QSPI_SD3, Bank::Qspi, 5);
|
||||
|
||||
// ====================
|
||||
|
||||
mod eh02 {
|
||||
use super::*;
|
||||
|
||||
impl<'d, T: Pin> embedded_hal_02::digital::v2::InputPin for Input<'d, T> {
|
||||
type Error = Infallible;
|
||||
|
||||
fn is_high(&self) -> Result<bool, Self::Error> {
|
||||
Ok(self.is_high())
|
||||
}
|
||||
|
||||
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||
Ok(self.is_low())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Pin> embedded_hal_02::digital::v2::OutputPin for Output<'d, T> {
|
||||
type Error = Infallible;
|
||||
|
||||
fn set_high(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(self.set_high())
|
||||
}
|
||||
|
||||
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(self.set_low())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Pin> embedded_hal_02::digital::v2::StatefulOutputPin for Output<'d, T> {
|
||||
fn is_set_high(&self) -> Result<bool, Self::Error> {
|
||||
Ok(self.is_set_high())
|
||||
}
|
||||
|
||||
fn is_set_low(&self) -> Result<bool, Self::Error> {
|
||||
Ok(self.is_set_low())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-traits")]
|
||||
mod eh1 {
|
||||
use super::*;
|
||||
|
||||
impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Input<'d, T> {
|
||||
type Error = Infallible;
|
||||
}
|
||||
|
||||
impl<'d, T: Pin> embedded_hal_1::digital::blocking::InputPin for Input<'d, T> {
|
||||
fn is_high(&self) -> Result<bool, Self::Error> {
|
||||
Ok(self.is_high())
|
||||
}
|
||||
|
||||
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||
Ok(self.is_low())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Output<'d, T> {
|
||||
type Error = Infallible;
|
||||
}
|
||||
|
||||
impl<'d, T: Pin> embedded_hal_1::digital::blocking::OutputPin for Output<'d, T> {
|
||||
fn set_high(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(self.set_high())
|
||||
}
|
||||
|
||||
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(self.set_low())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Pin> embedded_hal_1::digital::blocking::StatefulOutputPin for Output<'d, T> {
|
||||
fn is_set_high(&self) -> Result<bool, Self::Error> {
|
||||
Ok(self.is_set_high())
|
||||
}
|
||||
|
||||
fn is_set_low(&self) -> Result<bool, Self::Error> {
|
||||
Ok(self.is_set_low())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,28 +2,33 @@ use core::marker::PhantomData;
|
||||
|
||||
use embassy::util::Unborrow;
|
||||
use embassy_hal_common::unborrow;
|
||||
use embedded_hal::blocking::spi as eh;
|
||||
use embedded_hal::spi as ehnb;
|
||||
|
||||
use crate::gpio::sealed::Pin as _;
|
||||
use crate::gpio::{AnyPin, Pin as GpioPin};
|
||||
use crate::{pac, peripherals};
|
||||
|
||||
pub use ehnb::{Phase, Polarity};
|
||||
pub use embedded_hal_02::spi::{Phase, Polarity};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
// No errors for now
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct Config {
|
||||
pub frequency: u32,
|
||||
pub phase: ehnb::Phase,
|
||||
pub polarity: ehnb::Polarity,
|
||||
pub phase: Phase,
|
||||
pub polarity: Polarity,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
frequency: 1_000_000,
|
||||
phase: ehnb::Phase::CaptureOnFirstTransition,
|
||||
polarity: ehnb::Polarity::IdleLow,
|
||||
phase: Phase::CaptureOnFirstTransition,
|
||||
polarity: Polarity::IdleLow,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -130,8 +135,8 @@ impl<'d, T: Instance> Spi<'d, T> {
|
||||
p.cpsr().write(|w| w.set_cpsdvsr(presc));
|
||||
p.cr0().write(|w| {
|
||||
w.set_dss(0b0111); // 8bit
|
||||
w.set_spo(config.polarity == ehnb::Polarity::IdleHigh);
|
||||
w.set_sph(config.phase == ehnb::Phase::CaptureOnSecondTransition);
|
||||
w.set_spo(config.polarity == Polarity::IdleHigh);
|
||||
w.set_sph(config.phase == Phase::CaptureOnSecondTransition);
|
||||
w.set_scr(postdiv);
|
||||
});
|
||||
p.cr1().write(|w| {
|
||||
@ -157,7 +162,7 @@ impl<'d, T: Instance> Spi<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&mut self, data: &[u8]) {
|
||||
pub fn blocking_write(&mut self, data: &[u8]) -> Result<(), Error> {
|
||||
unsafe {
|
||||
let p = self.inner.regs();
|
||||
for &b in data {
|
||||
@ -166,11 +171,12 @@ impl<'d, T: Instance> Spi<'d, T> {
|
||||
while !p.sr().read().rne() {}
|
||||
let _ = p.dr().read();
|
||||
}
|
||||
self.flush();
|
||||
}
|
||||
self.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn transfer(&mut self, data: &mut [u8]) {
|
||||
pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> {
|
||||
unsafe {
|
||||
let p = self.inner.regs();
|
||||
for b in data {
|
||||
@ -179,15 +185,50 @@ impl<'d, T: Instance> Spi<'d, T> {
|
||||
while !p.sr().read().rne() {}
|
||||
*b = p.dr().read().data() as u8;
|
||||
}
|
||||
self.flush();
|
||||
}
|
||||
self.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn flush(&mut self) {
|
||||
pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<(), Error> {
|
||||
unsafe {
|
||||
let p = self.inner.regs();
|
||||
for b in data {
|
||||
while !p.sr().read().tnf() {}
|
||||
p.dr().write(|w| w.set_data(0));
|
||||
while !p.sr().read().rne() {}
|
||||
*b = p.dr().read().data() as u8;
|
||||
}
|
||||
}
|
||||
self.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
|
||||
unsafe {
|
||||
let p = self.inner.regs();
|
||||
let len = read.len().max(write.len());
|
||||
for i in 0..len {
|
||||
let wb = write.get(i).copied().unwrap_or(0);
|
||||
while !p.sr().read().tnf() {}
|
||||
p.dr().write(|w| w.set_data(wb as _));
|
||||
while !p.sr().read().rne() {}
|
||||
let rb = p.dr().read().data() as u8;
|
||||
if let Some(r) = read.get_mut(i) {
|
||||
*r = rb;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn flush(&mut self) -> Result<(), Error> {
|
||||
unsafe {
|
||||
let p = self.inner.regs();
|
||||
while p.sr().read().bsy() {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_frequency(&mut self, freq: u32) {
|
||||
@ -209,23 +250,6 @@ impl<'d, T: Instance> Spi<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> eh::Write<u8> for Spi<'d, T> {
|
||||
type Error = core::convert::Infallible;
|
||||
|
||||
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
|
||||
self.write(words);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> eh::Transfer<u8> for Spi<'d, T> {
|
||||
type Error = core::convert::Infallible;
|
||||
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
|
||||
self.transfer(words);
|
||||
Ok(words)
|
||||
}
|
||||
}
|
||||
|
||||
mod sealed {
|
||||
use super::*;
|
||||
|
||||
@ -281,3 +305,102 @@ impl_pin!(PIN_16, SPI0, MisoPin);
|
||||
impl_pin!(PIN_17, SPI0, CsPin);
|
||||
impl_pin!(PIN_18, SPI0, ClkPin);
|
||||
impl_pin!(PIN_19, SPI0, MosiPin);
|
||||
|
||||
// ====================
|
||||
|
||||
mod eh02 {
|
||||
use super::*;
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_02::blocking::spi::Transfer<u8> for Spi<'d, T> {
|
||||
type Error = Error;
|
||||
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
|
||||
self.blocking_transfer_in_place(words)?;
|
||||
Ok(words)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_02::blocking::spi::Write<u8> for Spi<'d, T> {
|
||||
type Error = Error;
|
||||
|
||||
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
|
||||
self.blocking_write(words)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-traits")]
|
||||
mod eh1 {
|
||||
use super::*;
|
||||
|
||||
impl embedded_hal_1::spi::Error for Error {
|
||||
fn kind(&self) -> embedded_hal_1::spi::ErrorKind {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::ErrorType for Spi<'d, T> {
|
||||
type Error = Error;
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_1::spi::blocking::Read<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> {
|
||||
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> {
|
||||
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)
|
||||
}
|
||||
|
||||
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(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
||||
runner = "probe-run-rp --chip RP2040"
|
||||
runner = "probe-run --chip RP2040"
|
||||
|
||||
[build]
|
||||
target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+
|
||||
|
@ -7,7 +7,7 @@ version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt"] }
|
||||
embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt"] }
|
||||
embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac"] }
|
||||
atomic-polyfill = "0.1.5"
|
||||
|
||||
defmt = "0.3"
|
||||
|
@ -34,7 +34,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
|
||||
loop {
|
||||
cs.set_low();
|
||||
let mut buf = [0x90, 0x00, 0x00, 0xd0, 0x00, 0x00];
|
||||
spi.transfer(&mut buf);
|
||||
spi.blocking_transfer_in_place(&mut buf).unwrap();
|
||||
cs.set_high();
|
||||
|
||||
let x = (buf[1] as u32) << 5 | (buf[2] as u32) >> 3;
|
||||
|
@ -131,7 +131,7 @@ impl<'a> embedded_hal::blocking::spi::Write<u8> for DisplaySpi<'a> {
|
||||
this.display_cs.set_low();
|
||||
this.last_mode = SpiMode::Display;
|
||||
}
|
||||
this.spi.write(words);
|
||||
this.spi.write(words).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -147,7 +147,7 @@ impl<'a> embedded_hal::blocking::spi::Transfer<u8> for TouchSpi<'a> {
|
||||
this.display_cs.set_high();
|
||||
this.last_mode = SpiMode::Touch;
|
||||
}
|
||||
this.spi.transfer(words);
|
||||
this.spi.transfer(words).unwrap();
|
||||
Ok(words)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user