mirror of
https://github.com/esp-rs/esp-idf-hal.git
synced 2025-09-28 12:51:04 +00:00
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:
parent
0c55a52692
commit
b134d3dbc6
@ -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"] }
|
||||
|
@ -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::*;
|
||||
|
27
src/adc.rs
27
src/adc.rs
@ -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 ()>);
|
||||
|
22
src/gpio.rs
22
src/gpio.rs
@ -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) => {};
|
||||
|
@ -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 {
|
||||
()
|
||||
}
|
||||
}
|
||||
|
243
src/spi.rs
243
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<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 ()>);
|
||||
|
Loading…
x
Reference in New Issue
Block a user