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
This commit is contained in:
Dominic Fischer 2022-04-17 06:14:39 +01:00 committed by GitHub
parent 0c55a52692
commit b134d3dbc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 169 additions and 135 deletions

View File

@ -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"] }

View File

@ -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::*;

View File

@ -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;
@ -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 ()>);

View File

@ -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) => {
@ -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) => {};

View File

@ -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 {
()
}
}

View File

@ -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<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: OutputPin>
Master<SPI, SCLK, SDO, SDI, CS>
{
@ -475,6 +608,39 @@ impl<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: O
type Error = SpiError;
}
impl<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: OutputPin>
embedded_hal::spi::blocking::SpiDevice for Master<SPI, SCLK, SDO, SDI, CS>
{
type Bus = MasterBus;
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,
};
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<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>
{
@ -487,32 +653,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::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)?;
Ok(())
}
}
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)
}
}
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)
}
}
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>
{
@ -523,14 +663,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::Write<u8> for Master<SPI, SCLK, SDO, SDI, CS>
{
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
self.transfer_internal(&mut [], words, true)
}
}
impl<SPI: Spi, SCLK: OutputPin, SDO: OutputPin, SDI: InputPin + OutputPin, CS: OutputPin>
embedded_hal_0_2::blocking::spi::WriteIter<u8> for Master<SPI, SCLK, SDO, SDI, CS>
{
@ -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>
{
@ -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 ()>);