Skip to content

Commit

Permalink
Migrate to e-hal 1.0.0-alpha.8 (#61)
Browse files Browse the repository at this point in the history
* Migrate e-hal 1.0.0-alpha.8

* Implement SpiDevice trait

* Fix bugs after real testing

* Fix transfer
  • Loading branch information
Dominaezzz committed Apr 17, 2022
1 parent 0c55a52 commit b134d3d
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 132 deletions.
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.20", 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

0 comments on commit b134d3d

Please sign in to comment.