From bf2cca90beb505c6e17f4a2d8d8926cf20fd921f Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Thu, 4 Apr 2024 14:09:35 +0000 Subject: [PATCH] Provide native APIs for I2C/SPI functionality currently handled by `embedded-hal@0.2.x` 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 --- esp-hal/src/i2c.rs | 33 ++++++++++-- esp-hal/src/spi/master.rs | 50 ++++++++++++++++--- .../src/bin/i2c_bmp180_calibration_data.rs | 2 - examples/src/bin/spi_loopback.rs | 2 - hil-test/tests/spi_full_duplex.rs | 10 ++-- 5 files changed, 77 insertions(+), 20 deletions(-) diff --git a/esp-hal/src/i2c.rs b/esp-hal/src/i2c.rs index 06027a57c..9db81e89b 100644 --- a/esp-hal/src/i2c.rs +++ b/esp-hal/src/i2c.rs @@ -191,6 +191,33 @@ pub struct I2C<'d, T, DM: crate::Mode> { phantom: PhantomData, } +impl 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 embedded_hal_02::blocking::i2c::Read for I2C<'_, T, DM> where @@ -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) } } @@ -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) } } @@ -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) } } diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index 46e1fb73a..d73980aae 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -391,6 +391,46 @@ pub struct Spi<'d, T, M> { _mode: PhantomData, } +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 { + 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, @@ -736,11 +776,11 @@ where type Error = Error; fn read(&mut self) -> nb::Result { - 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) } } @@ -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) } } @@ -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) } } diff --git a/examples/src/bin/i2c_bmp180_calibration_data.rs b/examples/src/bin/i2c_bmp180_calibration_data.rs index 90fcaddcc..aa217b08e 100644 --- a/examples/src/bin/i2c_bmp180_calibration_data.rs +++ b/examples/src/bin/i2c_bmp180_calibration_data.rs @@ -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; diff --git a/examples/src/bin/spi_loopback.rs b/examples/src/bin/spi_loopback.rs index a7462be3f..796b2da95 100644 --- a/examples/src/bin/spi_loopback.rs +++ b/examples/src/bin/spi_loopback.rs @@ -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, diff --git a/hil-test/tests/spi_full_duplex.rs b/hil-test/tests/spi_full_duplex.rs index 9a75fa39a..1b85d45ea 100644 --- a/hil-test/tests/spi_full_duplex.rs +++ b/hil-test/tests/spi_full_duplex.rs @@ -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); } @@ -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); @@ -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); }