Skip to content

Commit

Permalink
Provide native APIs for I2C/SPI functionality currently handled by `e…
Browse files Browse the repository at this point in the history
[email protected]` traits (#1386)

* Provide native APIs for SPI functionality currently handled by `embedded-hal` traits

* Provide APIs for I2C functionality currently handled by `embedded-hal` traits

* Rebase and update HIL test for SPI to get it building again
  • Loading branch information
jessebraham authored Apr 4, 2024
1 parent bd98088 commit bf2cca9
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 20 deletions.
33 changes: 30 additions & 3 deletions esp-hal/src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,33 @@ pub struct I2C<'d, T, DM: crate::Mode> {
phantom: PhantomData<DM>,
}

impl<T, DM> I2C<'_, T, DM>
where
T: Instance,
DM: crate::Mode,
{
/// Reads enough bytes from slave with `address` to fill `buffer`
pub fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
self.peripheral.master_read(address, buffer)
}

/// Writes bytes to slave with address `address`
pub fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
self.peripheral.master_write(addr, bytes)
}

/// Writes bytes to slave with address `address` and then reads enough bytes
/// to fill `buffer` *in a single transaction*
pub fn write_read(
&mut self,
address: u8,
bytes: &[u8],
buffer: &mut [u8],
) -> Result<(), Error> {
self.peripheral.master_write_read(address, bytes, buffer)
}
}

#[cfg(feature = "embedded-hal-02")]
impl<T, DM: crate::Mode> embedded_hal_02::blocking::i2c::Read for I2C<'_, T, DM>
where
Expand All @@ -199,7 +226,7 @@ where
type Error = Error;

fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
self.peripheral.master_read(address, buffer)
self.read(address, buffer)
}
}

Expand All @@ -211,7 +238,7 @@ where
type Error = Error;

fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> {
self.peripheral.master_write(addr, bytes)
self.write(addr, bytes)
}
}

Expand All @@ -228,7 +255,7 @@ where
bytes: &[u8],
buffer: &mut [u8],
) -> Result<(), Self::Error> {
self.peripheral.master_write_read(address, bytes, buffer)
self.write_read(address, bytes, buffer)
}
}

Expand Down
50 changes: 44 additions & 6 deletions esp-hal/src/spi/master.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,46 @@ pub struct Spi<'d, T, M> {
_mode: PhantomData<M>,
}

impl<'d, T, M> Spi<'d, T, M>
where
T: Instance,
M: IsFullDuplex,
{
/// Read bytes from SPI.
///
/// Sends out a stuffing byte for every byte to read. This function doesn't
/// perform flushing. If you want to read the response to something you
/// have written before, consider using [`Self::transfer`] instead.
pub fn read_byte(&mut self) -> nb::Result<u8, Error> {
self.spi.read_byte()
}

/// Write a byte to SPI.
pub fn write_byte(&mut self, word: u8) -> nb::Result<(), Error> {
self.spi.write_byte(word)
}

/// Write bytes to SPI.
///
/// Copies the content of `words` in chunks of 64 bytes into the SPI
/// transmission FIFO. If `words` is longer than 64 bytes, multiple
/// sequential transfers are performed. This function will return before
/// all bytes of the last chunk to transmit have been sent to the wire. If
/// you must ensure that the whole messages was written correctly, use
/// [`Self::flush`].
pub fn write_bytes(&mut self, words: &[u8]) -> Result<(), Error> {
self.spi.write_bytes(words)?;
self.spi.flush()?;

Ok(())
}

/// Sends `words` to the slave. Returns the `words` received from the slave
pub fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Error> {
self.spi.transfer(words)
}
}

impl<'d, T> Spi<'d, T, FullDuplexMode>
where
T: Instance,
Expand Down Expand Up @@ -736,11 +776,11 @@ where
type Error = Error;

fn read(&mut self) -> nb::Result<u8, Self::Error> {
self.spi.read_byte()
self.read_byte()
}

fn send(&mut self, word: u8) -> nb::Result<(), Self::Error> {
self.spi.write_byte(word)
self.write_byte(word)
}
}

Expand All @@ -753,7 +793,7 @@ where
type Error = Error;

fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
self.spi.transfer(words)
self.transfer(words)
}
}

Expand All @@ -766,9 +806,7 @@ where
type Error = Error;

fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
self.spi.write_bytes(words)?;
self.spi.flush()?;
Ok(())
self.write_bytes(words)
}
}

Expand Down
2 changes: 0 additions & 2 deletions examples/src/bin/i2c_bmp180_calibration_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@
//! - SCL => GPIO5
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: embedded-hal-02

#![no_std]
#![no_main]

use embedded_hal_02::blocking::i2c::WriteRead;
use esp_backtrace as _;
use esp_hal::{clock::ClockControl, gpio::IO, i2c::I2C, peripherals::Peripherals, prelude::*};
use esp_println::println;
Expand Down
2 changes: 0 additions & 2 deletions examples/src/bin/spi_loopback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@
//! data.
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: embedded-hal-02

#![no_std]
#![no_main]

use embedded_hal_02::blocking::spi::Transfer;
use esp_backtrace as _;
use esp_hal::{
clock::ClockControl,
Expand Down
10 changes: 3 additions & 7 deletions hil-test/tests/spi_full_duplex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ mod tests {
let write = [0xde, 0xad, 0xbe, 0xef];
let mut read: [u8; 4] = [0x00u8; 4];

ctx.spi
.transfer(&mut read[..], &write[..])
SpiBus::transfer(&mut ctx.spi, &mut read[..], &write[..])
.expect("Symmetric transfer failed");
assert_eq!(write, read);
}
Expand All @@ -77,8 +76,7 @@ mod tests {
let write = [0xde, 0xad, 0xbe, 0xef];
let mut read: [u8; 4] = [0x00; 4];

ctx.spi
.transfer(&mut read[0..2], &write[..])
SpiBus::transfer(&mut ctx.spi, &mut read[0..2], &write[..])
.expect("Asymmetric transfer failed");
assert_eq!(write[0], read[0]);
assert_eq!(read[2], 0x00u8);
Expand All @@ -92,9 +90,7 @@ mod tests {
}
let mut read = [0x00u8; 4096];

ctx.spi
.transfer(&mut read[..], &write[..])
.expect("Huge transfer failed");
SpiBus::transfer(&mut ctx.spi, &mut read[..], &write[..]).expect("Huge transfer failed");
assert_eq!(write, read);
}

Expand Down

0 comments on commit bf2cca9

Please sign in to comment.