diff --git a/src/spi.rs b/src/spi.rs index d0c6fa9a558..65e8de80423 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -155,6 +155,17 @@ pub mod config { } } + #[derive(Copy, Clone)] + pub enum Chunk { + EightBits = 1, + SixteenBits = 2, + TwentyFourBits = 3, + ThirtyTwoBits = 4, + FourtyEightBits = 6, + SixtyFourBits = 8, + None = 64, + } + /// SPI Device configuration #[derive(Copy, Clone)] pub struct Config { @@ -167,6 +178,10 @@ pub mod config { pub write_only: bool, pub duplex: Duplex, pub cs_active_high: bool, + /// Number of bits in a transfer unit e.g 8bit 32bit. + /// A transfer unit is a continoues clkout signal without a gap. + /// Some Devices can only work with 8bit transfer units + pub chunk_size: Chunk, } impl Config { @@ -200,6 +215,11 @@ pub mod config { self.cs_active_high = true; self } + + pub fn transfer_by_chunk(mut self, chunk_size: Chunk) -> Self { + self.chunk_size = chunk_size; + self + } } impl Default for Config { @@ -210,6 +230,7 @@ pub mod config { write_only: false, cs_active_high: false, duplex: Duplex::Full, + chunk_size: Chunk::None, } } } @@ -342,7 +363,7 @@ impl<'d> SpiBus for SpiBusDriver<'d> { pub struct SpiDriver<'d> { host: u8, - max_transfer_size: usize, + dma: Dma, _p: PhantomData<&'d mut ()>, } @@ -358,11 +379,11 @@ impl<'d> SpiDriver<'d> { sdi: Option + 'd>, dma: Dma, ) -> Result { - let max_transfer_size = Self::new_internal(SPI1::device(), sclk, sdo, sdi, dma)?; + Self::new_internal(SPI1::device(), sclk, sdo, sdi, dma)?; Ok(Self { host: SPI1::device() as _, - max_transfer_size, + dma, _p: PhantomData, }) } @@ -375,11 +396,11 @@ impl<'d> SpiDriver<'d> { sdi: Option + 'd>, dma: Dma, ) -> Result { - let max_transfer_size = Self::new_internal(SPI::device(), sclk, sdo, sdi, dma)?; + Self::new_internal(SPI::device(), sclk, sdo, sdi, dma)?; Ok(Self { host: SPI::device() as _, - max_transfer_size, + dma, _p: PhantomData, }) } @@ -394,11 +415,10 @@ impl<'d> SpiDriver<'d> { sdo: impl Peripheral

+ 'd, sdi: Option + 'd>, dma: Dma, - ) -> Result { + ) -> Result<(), EspError> { crate::into_ref!(sclk, sdo); let sdi = sdi.map(|sdi| sdi.into_ref()); - let max_transfer_sz = dma.max_transfer_size(); let dma_chan: spi_dma_chan_t = dma.into(); #[cfg(not(esp_idf_version = "4.3"))] @@ -426,7 +446,7 @@ impl<'d> SpiDriver<'d> { quadhd_io_num: -1, //data3_io_num: -1, }, - max_transfer_sz: max_transfer_sz as i32, + max_transfer_sz: dma.max_transfer_size() as i32, ..Default::default() }; @@ -440,13 +460,13 @@ impl<'d> SpiDriver<'d> { quadwp_io_num: -1, quadhd_io_num: -1, - max_transfer_sz: max_transfer_sz as i32, + max_transfer_sz: dma.max_transfer_size() as i32, ..Default::default() }; esp!(unsafe { spi_bus_initialize(host, &bus_config, dma_chan) })?; - Ok(max_transfer_sz) + Ok(()) } } @@ -464,6 +484,7 @@ pub struct SpiDeviceDriver<'d, T> { handle: spi_device_handle_t, driver: T, with_cs_pin: bool, + transfer_unit_size: u8, _p: PhantomData<&'d ()>, } @@ -505,6 +526,8 @@ where ) -> Result { let cs = cs.map(|cs| cs.into_ref().pin()).unwrap_or(-1); + let transfer_unit_size = config.chunk_size as u8; + let conf = spi_device_interface_config_t { spics_io_num: cs, clock_speed_hz: config.baudrate.0 as i32, @@ -532,6 +555,7 @@ where handle, driver, with_cs_pin: cs >= 0, + transfer_unit_size, _p: PhantomData, }) } @@ -548,7 +572,11 @@ where E: From, { // if DMA used -> get trans length info from driver - let trans_len = self.driver.borrow().max_transfer_size; + let trans_len = if self.driver.borrow().dma == Dma::Disabled { + self.transfer_unit_size as usize + } else { + self.driver.borrow().dma.max_transfer_size() + }; let mut bus = SpiBusDriver { handle: self.handle, @@ -630,9 +658,12 @@ where fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { let _lock = self.lock_bus()?; - let mut chunks = words - .chunks_mut(self.driver.borrow().max_transfer_size) - .peekable(); + let trans_len = if self.driver.borrow().dma == Dma::Disabled { + self.transfer_unit_size as usize + } else { + self.driver.borrow().dma.max_transfer_size() + }; + let mut chunks = words.chunks_mut(trans_len).peekable(); while let Some(chunk) = chunks.next() { let ptr = chunk.as_mut_ptr(); @@ -652,9 +683,12 @@ where fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { let _lock = self.lock_bus()?; - let mut chunks = words - .chunks(self.driver.borrow().max_transfer_size) - .peekable(); + let trans_len = if self.driver.borrow().dma == Dma::Disabled { + self.transfer_unit_size as usize + } else { + self.driver.borrow().dma.max_transfer_size() + }; + let mut chunks = words.chunks(trans_len).peekable(); while let Some(chunk) = chunks.next() { polling_transmit(