Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to e-hal 1.0.0-alpha.8 #61

Merged
merged 4 commits into from
Apr 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ experimental = []
[dependencies]
nb = "0.1.2"
mutex-trait = { version = "0.2", optional = true, default-features = false }
embedded-hal = "=1.0.0-alpha.7"
embedded-hal = "=1.0.0-alpha.8"
embedded-hal-0-2 = { package = "embedded-hal", version = "0.2.7", features = ["unproven"] }
embedded-svc = { version = "0.19", optional = true, default-features = false }
esp-idf-sys = { version = "0.31", optional = true, default-features = false, features = ["native"] }
Expand Down
2 changes: 1 addition & 1 deletion examples/spi_loopback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use std::thread;
use std::time::Duration;

use embedded_hal::spi::blocking::Transfer;
use embedded_hal::spi::blocking::SpiDevice;

use esp_idf_hal::peripherals::Peripherals;
use esp_idf_hal::prelude::*;
Expand Down
27 changes: 0 additions & 27 deletions src/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,24 +311,6 @@ where
}
}

#[cfg(not(feature = "riscv-ulp-hal"))]
impl<ADC, AN, PIN> embedded_hal::adc::nb::OneShot<AN, u16, PIN> for PoweredAdc<ADC>
where
ADC: Adc,
AN: Analog<ADC>,
PIN: embedded_hal::adc::nb::Channel<AN, ID = u8>,
{
type Error = EspError;

fn read(&mut self, pin: &mut PIN) -> nb::Result<u16, Self::Error> {
self.read(
ADC::unit(),
pin.channel() as adc_channel_t,
AN::attenuation(),
)
}
}

#[cfg(all(esp32, not(feature = "riscv-ulp-hal")))]
impl embedded_hal_0_2::adc::OneShot<ADC1, u16, hall::HallSensor> for PoweredAdc<ADC1> {
type Error = EspError;
Expand All @@ -338,15 +320,6 @@ impl embedded_hal_0_2::adc::OneShot<ADC1, u16, hall::HallSensor> for PoweredAdc<
}
}

#[cfg(all(esp32, not(feature = "riscv-ulp-hal")))]
impl embedded_hal::adc::nb::OneShot<ADC1, u16, hall::HallSensor> for PoweredAdc<ADC1> {
type Error = EspError;

fn read(&mut self, _hall_sensor: &mut hall::HallSensor) -> nb::Result<u16, Self::Error> {
self.read_hall()
}
}

macro_rules! impl_adc {
($adc:ident: $unit:expr) => {
pub struct $adc(::core::marker::PhantomData<*const ()>);
Expand Down
22 changes: 0 additions & 22 deletions src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -736,17 +736,6 @@ macro_rules! impl_adc {
$adc
}
}

impl<AN> embedded_hal::adc::nb::Channel<AN> for $pxi<AN>
where
AN: adc::Analog<adc::ADC1> + Send,
{
type ID = u8;

fn channel(&self) -> Self::ID {
$adc
}
}
};

($pxi:ident: $pin:expr, ADC2: $adc:expr) => {
Expand Down Expand Up @@ -815,17 +804,6 @@ macro_rules! impl_adc {
$adc
}
}

impl<AN> embedded_hal::adc::nb::Channel<AN> for $pxi<AN>
where
AN: adc::Analog<adc::ADC2> + Send,
{
type ID = u8;

fn channel(&self) -> Self::ID {
$adc
}
}
};

($pxi:ident: $pin:expr, NOADC: $adc:expr) => {};
Expand Down
8 changes: 0 additions & 8 deletions src/hall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,3 @@ impl embedded_hal_0_2::adc::Channel<adc::ADC1> for HallSensor {
()
}
}

impl embedded_hal::adc::nb::Channel<adc::ADC1> for HallSensor {
type ID = ();

fn channel(&self) -> Self::ID {
()
}
}
237 changes: 164 additions & 73 deletions src/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
//! - Multiple CS pins
//! - Slave

use core::cmp::{max, min};
use core::cmp::{max, min, Ordering};
use core::ptr;

use crate::delay::portMAX_DELAY;
Expand Down Expand Up @@ -216,6 +216,139 @@ impl Drop for Lock {
}
}

pub struct MasterBus {
handle: spi_device_handle_t,
trans_len: usize,
}

impl MasterBus {
// These parameters assume full duplex.
fn polling_transmit(
&mut self,
read: *mut u8,
write: *const u8,
transaction_length: usize,
rx_length: usize,
) -> Result<(), SpiError> {
let flags = 0;

// This unfortunately means that this implementation is incorrect for esp-idf < 4.4.
// The CS pin should be kept active through transactions.
#[cfg(not(esp_idf_version = "4.3"))]
let flags = SPI_TRANS_CS_KEEP_ACTIVE;

let mut transaction = spi_transaction_t {
flags,
__bindgen_anon_1: spi_transaction_t__bindgen_ty_1 {
tx_buffer: write as *const _,
},
__bindgen_anon_2: spi_transaction_t__bindgen_ty_2 {
rx_buffer: read as *mut _,
},
length: (transaction_length * 8) as _,
rxlength: (rx_length * 8) as _,
..Default::default()
};

esp!(unsafe { spi_device_polling_transmit(self.handle, &mut transaction as *mut _) })
.map_err(SpiError::other)
}

/// Empty transaction to de-assert CS.
fn finish(&mut self) -> Result<(), SpiError> {
let flags = 0;

let mut transaction = spi_transaction_t {
flags,
__bindgen_anon_1: spi_transaction_t__bindgen_ty_1 {
tx_buffer: ptr::null(),
},
__bindgen_anon_2: spi_transaction_t__bindgen_ty_2 {
rx_buffer: ptr::null_mut(),
},
length: 0,
rxlength: 0,
..Default::default()
};

esp!(unsafe { spi_device_polling_transmit(self.handle, &mut transaction as *mut _) })
.map_err(SpiError::other)
}
}

impl embedded_hal::spi::ErrorType for MasterBus {
type Error = SpiError;
}

impl embedded_hal::spi::blocking::SpiBusFlush for MasterBus {
fn flush(&mut self) -> Result<(), Self::Error> {
// Since we use polling transactions, flushing isn't required.
// In future, when DMA is available spi_device_get_trans_result
// will be called here.
Ok(())
}
}

impl embedded_hal::spi::blocking::SpiBusRead for MasterBus {
fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
for chunk in words.chunks_mut(self.trans_len) {
self.polling_transmit(chunk.as_mut_ptr(), ptr::null(), chunk.len(), chunk.len())?;
}
Ok(())
}
}

impl embedded_hal::spi::blocking::SpiBusWrite for MasterBus {
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
for chunk in words.chunks(self.trans_len) {
self.polling_transmit(ptr::null_mut(), chunk.as_ptr(), chunk.len(), 0)?;
}
Ok(())
}
}

impl embedded_hal::spi::blocking::SpiBus for MasterBus {
fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
let common_length = min(read.len(), write.len());
let common_read = read[0..common_length].chunks_mut(self.trans_len);
let common_write = write[0..common_length].chunks(self.trans_len);

for (read_chunk, write_chunk) in common_read.zip(common_write) {
self.polling_transmit(
read_chunk.as_mut_ptr(),
write_chunk.as_ptr(),
max(read_chunk.len(), write_chunk.len()),
read_chunk.len(),
)?;
}

match read.len().cmp(&write.len()) {
Ordering::Equal => { /* Nothing left to do */ }
Ordering::Greater => {
use embedded_hal::spi::blocking::SpiBusRead;
// Read remainder
self.read(&mut read[write.len()..])?;
}
Ordering::Less => {
use embedded_hal::spi::blocking::SpiBusWrite;
// Write remainder
self.write(&write[read.len()..])?;
}
}

Ok(())
}

fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
for chunk in words.chunks_mut(self.trans_len) {
let ptr = chunk.as_mut_ptr();
let len = chunk.len();
self.polling_transmit(ptr, ptr, len, len)?;
}
Ok(())
}
}

impl<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: OutputPin>
Master<SPI, SCLK, SDO, SDI, CS>
{
Expand Down Expand Up @@ -476,56 +609,55 @@ impl<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: O
}

impl<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: OutputPin>
embedded_hal_0_2::blocking::spi::Transfer<u8> for Master<SPI, SCLK, SDO, SDI, CS>
embedded_hal::spi::blocking::SpiDevice for Master<SPI, SCLK, SDO, SDI, CS>
{
type Error = SpiError;
type Bus = MasterBus;

fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
self.transfer_inplace_internal(words, true)?;
fn transaction<R>(
&mut self,
f: impl FnOnce(&mut Self::Bus) -> Result<R, <Self::Bus as embedded_hal::spi::ErrorType>::Error>,
) -> Result<R, Self::Error> {
let mut bus = MasterBus {
handle: self.device,
trans_len: TRANS_LEN,
};

Ok(words)
}
}
let lock = self.lock_bus()?;
let trans_result = f(&mut bus);

impl<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: OutputPin>
embedded_hal::spi::blocking::TransferInplace<u8> for Master<SPI, SCLK, SDO, SDI, CS>
{
fn transfer_inplace(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
self.transfer_inplace_internal(words, true)?;
let finish_result = bus.finish();

Ok(())
}
}
// Flush whatever is pending.
// Note that this is done even when an error is returned from the transaction.
use embedded_hal::spi::blocking::SpiBusFlush;
let flush_result = bus.flush();

impl<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: OutputPin>
embedded_hal::spi::blocking::Transfer<u8> for Master<SPI, SCLK, SDO, SDI, CS>
{
fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
self.transfer_internal(read, write, true)
}
}
core::mem::drop(lock);

impl<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: OutputPin>
embedded_hal::spi::blocking::Read<u8> for Master<SPI, SCLK, SDO, SDI, CS>
{
fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
self.transfer_internal(words, &[], true)
let result = trans_result?;
finish_result?;
flush_result?;
Ok(result)
}
}

impl<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: OutputPin>
embedded_hal_0_2::blocking::spi::Write<u8> for Master<SPI, SCLK, SDO, SDI, CS>
embedded_hal_0_2::blocking::spi::Transfer<u8> for Master<SPI, SCLK, SDO, SDI, CS>
{
type Error = SpiError;

fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
self.transfer_internal(&mut [], words, true)
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
self.transfer_inplace_internal(words, true)?;

Ok(words)
}
}

impl<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: OutputPin>
embedded_hal::spi::blocking::Write<u8> for Master<SPI, SCLK, SDO, SDI, CS>
embedded_hal_0_2::blocking::spi::Write<u8> for Master<SPI, SCLK, SDO, SDI, CS>
{
type Error = SpiError;

fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
self.transfer_internal(&mut [], words, true)
}
Expand All @@ -544,17 +676,6 @@ impl<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: O
}
}

impl<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: OutputPin>
embedded_hal::spi::blocking::WriteIter<u8> for Master<SPI, SCLK, SDO, SDI, CS>
{
fn write_iter<WI>(&mut self, words: WI) -> Result<(), Self::Error>
where
WI: IntoIterator<Item = u8>,
{
self.write_iter_internal(words)
}
}

impl<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: OutputPin>
embedded_hal_0_2::blocking::spi::Transactional<u8> for Master<SPI, SCLK, SDO, SDI, CS>
{
Expand All @@ -581,36 +702,6 @@ impl<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: O
}
}

impl<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: OutputPin>
embedded_hal::spi::blocking::Transactional<u8> for Master<SPI, SCLK, SDO, SDI, CS>
{
fn exec<'a>(
&mut self,
operations: &mut [embedded_hal::spi::blocking::Operation<'a, u8>],
) -> Result<(), Self::Error> {
let _lock = self.lock_bus()?;

for operation in operations {
match operation {
embedded_hal::spi::blocking::Operation::Read(read) => {
self.transfer_internal(read, &[], false)?
}
embedded_hal::spi::blocking::Operation::Write(write) => {
self.transfer_internal(&mut [], write, false)?
}
embedded_hal::spi::blocking::Operation::Transfer(read, write) => {
self.transfer_internal(read, write, false)?
}
embedded_hal::spi::blocking::Operation::TransferInplace(words) => {
self.transfer_inplace_internal(words, false)?
}
}
}

Ok(())
}
}

macro_rules! impl_spi {
($spi:ident: $device:expr) => {
pub struct $spi(::core::marker::PhantomData<*const ()>);
Expand Down