From b134d3dbc65a954141b7eb3519f640d18162c12f Mon Sep 17 00:00:00 2001 From: Dominic Fischer Date: Sun, 17 Apr 2022 06:14:39 +0100 Subject: [PATCH] Migrate to e-hal 1.0.0-alpha.8 (#61) * Migrate e-hal 1.0.0-alpha.8 * Implement SpiDevice trait * Fix bugs after real testing * Fix transfer --- Cargo.toml | 2 +- examples/spi_loopback.rs | 2 +- src/adc.rs | 27 ----- src/gpio.rs | 22 ---- src/hall.rs | 8 -- src/spi.rs | 243 +++++++++++++++++++++++++++------------ 6 files changed, 169 insertions(+), 135 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 278ffe058..deed8008a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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.20", optional = true, default-features = false } esp-idf-sys = { version = "0.31", optional = true, default-features = false, features = ["native"] } diff --git a/examples/spi_loopback.rs b/examples/spi_loopback.rs index c7eaecd24..842c73155 100644 --- a/examples/spi_loopback.rs +++ b/examples/spi_loopback.rs @@ -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::*; diff --git a/src/adc.rs b/src/adc.rs index 946b651ca..3ca2a9757 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -311,24 +311,6 @@ where } } -#[cfg(not(feature = "riscv-ulp-hal"))] -impl embedded_hal::adc::nb::OneShot for PoweredAdc -where - ADC: Adc, - AN: Analog, - PIN: embedded_hal::adc::nb::Channel, -{ - type Error = EspError; - - fn read(&mut self, pin: &mut PIN) -> nb::Result { - 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 for PoweredAdc { type Error = EspError; @@ -338,15 +320,6 @@ impl embedded_hal_0_2::adc::OneShot for PoweredAdc< } } -#[cfg(all(esp32, not(feature = "riscv-ulp-hal")))] -impl embedded_hal::adc::nb::OneShot for PoweredAdc { - type Error = EspError; - - fn read(&mut self, _hall_sensor: &mut hall::HallSensor) -> nb::Result { - self.read_hall() - } -} - macro_rules! impl_adc { ($adc:ident: $unit:expr) => { pub struct $adc(::core::marker::PhantomData<*const ()>); diff --git a/src/gpio.rs b/src/gpio.rs index ab955c88e..fd5ad2cee 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -736,17 +736,6 @@ macro_rules! impl_adc { $adc } } - - impl embedded_hal::adc::nb::Channel for $pxi - where - AN: adc::Analog + Send, - { - type ID = u8; - - fn channel(&self) -> Self::ID { - $adc - } - } }; ($pxi:ident: $pin:expr, ADC2: $adc:expr) => { @@ -815,17 +804,6 @@ macro_rules! impl_adc { $adc } } - - impl embedded_hal::adc::nb::Channel for $pxi - where - AN: adc::Analog + Send, - { - type ID = u8; - - fn channel(&self) -> Self::ID { - $adc - } - } }; ($pxi:ident: $pin:expr, NOADC: $adc:expr) => {}; diff --git a/src/hall.rs b/src/hall.rs index bb3ca14d8..5c21a7814 100644 --- a/src/hall.rs +++ b/src/hall.rs @@ -22,11 +22,3 @@ impl embedded_hal_0_2::adc::Channel for HallSensor { () } } - -impl embedded_hal::adc::nb::Channel for HallSensor { - type ID = (); - - fn channel(&self) -> Self::ID { - () - } -} diff --git a/src/spi.rs b/src/spi.rs index e351cef84..042ec56ff 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -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; @@ -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 Master { @@ -475,6 +608,39 @@ impl + embedded_hal::spi::blocking::SpiDevice for Master +{ + type Bus = MasterBus; + + fn transaction( + &mut self, + f: impl FnOnce(&mut Self::Bus) -> Result::Error>, + ) -> Result { + let mut bus = MasterBus { + handle: self.device, + trans_len: TRANS_LEN, + }; + + let lock = self.lock_bus()?; + let trans_result = f(&mut bus); + + let finish_result = bus.finish(); + + // 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(); + + core::mem::drop(lock); + + let result = trans_result?; + finish_result?; + flush_result?; + Ok(result) + } +} + impl embedded_hal_0_2::blocking::spi::Transfer for Master { @@ -487,32 +653,6 @@ impl - embedded_hal::spi::blocking::TransferInplace for Master -{ - fn transfer_inplace(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { - self.transfer_inplace_internal(words, true)?; - - Ok(()) - } -} - -impl - embedded_hal::spi::blocking::Transfer for Master -{ - fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { - self.transfer_internal(read, write, true) - } -} - -impl - embedded_hal::spi::blocking::Read for Master -{ - fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { - self.transfer_internal(words, &[], true) - } -} - impl embedded_hal_0_2::blocking::spi::Write for Master { @@ -523,14 +663,6 @@ impl - embedded_hal::spi::blocking::Write for Master -{ - fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { - self.transfer_internal(&mut [], words, true) - } -} - impl embedded_hal_0_2::blocking::spi::WriteIter for Master { @@ -544,17 +676,6 @@ impl - embedded_hal::spi::blocking::WriteIter for Master -{ - fn write_iter(&mut self, words: WI) -> Result<(), Self::Error> - where - WI: IntoIterator, - { - self.write_iter_internal(words) - } -} - impl embedded_hal_0_2::blocking::spi::Transactional for Master { @@ -581,36 +702,6 @@ impl - embedded_hal::spi::blocking::Transactional for Master -{ - 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 ()>);