diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f8a8e7e..d48cc416 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - complete and rework Dma Stream API [#666] - add `.set_count()` for QEI, add `.write_count()` for TIM [#677] - add "Fast start" section in README [#678] + - SPI bidi takes 2 pins [#526] +[#526]: https://github.com/stm32-rs/stm32f4xx-hal/pull/526 [#666]: https://github.com/stm32-rs/stm32f4xx-hal/pull/666 [#677]: https://github.com/stm32-rs/stm32f4xx-hal/pull/677 [#678]: https://github.com/stm32-rs/stm32f4xx-hal/pull/678 @@ -122,6 +124,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Cleanups [#595] - Fix comlementary for independent channels [#599] [#603] - Fix mstr bit for SPI Master/Slave [#625] + - I2c dma can now use single DMA channel for TX or RX only [#598] + - `ws2812::prerendered` in example [#585]: https://github.com/stm32-rs/stm32f4xx-hal/pull/585 [#587]: https://github.com/stm32-rs/stm32f4xx-hal/pull/587 @@ -194,6 +198,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Add missing timer pins [#536] - Revised temperature sensor input pins for all MCUs [#529] - Support `u16` read/write for SPI + - - Use `bool` for BIDI mode type - `PwmHz::get_period`: fix computation of return value, prevent division by zero - apply #[inline] attribute to bitbanding functions [#517] @@ -469,7 +474,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [breaking-change] Change `Pin>::internal_pull_up` signature from `(&mut self, _: bool) -> ()` to `(self, _: bool) -> Self`. [#399] -[#367]: https://github.com/stm32-rs/stm32f4xx-hal/pull/367 +[#367]: https://github.com/stm32-rm32f4xx-hal/pull/367 [#371]: https://github.com/stm32-rs/stm32f4xx-hal/pull/371 [#383]: https://github.com/stm32-rs/stm32f4xx-hal/pull/383 [#384]: https://github.com/stm32-rs/stm32f4xx-hal/pull/384 diff --git a/examples/ist7920-bidi-normal-spi.rs b/examples/ist7920-bidi-normal-spi.rs index 070c01d7..f4c5c50c 100644 --- a/examples/ist7920-bidi-normal-spi.rs +++ b/examples/ist7920-bidi-normal-spi.rs @@ -9,7 +9,7 @@ use stm32f4xx_hal as hal; use crate::hal::{pac, prelude::*, timer::Timer}; -use hal::spi::{Mode, NoMiso, Phase, Polarity}; +use hal::spi::{Mode, Phase, Polarity}; use display_interface_spi::SPIInterface; use ist7920::Ist7920; @@ -29,7 +29,6 @@ fn main() -> ! { led.set_low(); let sck = gpiob.pb3.into_alternate(); - let miso = NoMiso::new(); let mosi = gpiob.pb5; let dc = gpiob.pb4.into_push_pull_output(); @@ -46,7 +45,7 @@ fn main() -> ! { // Change spi transfer mode to Bidi for more efficient operations. // let spi = Spi::new(dp.SPI1, (sck, miso, mosi), mode, 8.MHz(), &clocks).to_bidi_transfer_mode(); // or - let spi = dp.SPI1.spi_bidi((sck, miso, mosi), mode, 8.MHz(), &clocks); + let spi = dp.SPI1.spi_bidi((sck, mosi), mode, 8.MHz(), &clocks); let iface = SPIInterface::new(spi, dc, cs); diff --git a/src/spi.rs b/src/spi.rs index b36fe445..8ce45740 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -207,15 +207,13 @@ pub trait SpiExt: Sized + Instance { fn spi_bidi( self, - pins: ( - impl Into, - impl Into, - impl Into, - ), + pins: (impl Into, impl Into), mode: impl Into, freq: Hertz, clocks: &Clocks, - ) -> Spi; + ) -> Spi + where + NoPin: Into; fn spi_slave( self, @@ -233,11 +231,12 @@ pub trait SpiExt: Sized + Instance { pins: ( impl Into, impl Into, - impl Into, Option, ), mode: impl Into, - ) -> SpiSlave; + ) -> SpiSlave + where + NoPin: Into; } impl SpiExt for SPI { @@ -266,15 +265,14 @@ impl SpiExt for SPI { /// Otherwise it may lead to the 'wrong last bit in every received byte' problem. fn spi_bidi( self, - pins: ( - impl Into, - impl Into, - impl Into, - ), + pins: (impl Into, impl Into), mode: impl Into, freq: Hertz, clocks: &Clocks, - ) -> Spi { + ) -> Spi + where + NoPin: Into, + { Spi::new_bidi(self, pins, mode, freq, clocks) } /// Enables the SPI clock, resets the peripheral, sets `Alternate` mode for `pins` and initialize the peripheral as SPI Slave Normal mode. @@ -304,11 +302,13 @@ impl SpiExt for SPI { pins: ( impl Into, impl Into, - impl Into, Option, ), mode: impl Into, - ) -> SpiSlave { + ) -> SpiSlave + where + NoPin: Into, + { SpiSlave::new_bidi(self, pins, mode) } } @@ -447,21 +447,20 @@ impl Spi { /// Otherwise it may lead to the 'wrong last bit in every received byte' problem. pub fn new_bidi( spi: SPI, - pins: ( - impl Into, - impl Into, - impl Into, - ), + pins: (impl Into, impl Into), mode: impl Into, freq: Hertz, clocks: &Clocks, - ) -> Self { + ) -> Self + where + NoPin: Into, + { unsafe { SPI::enable_unchecked(); SPI::reset_unchecked(); } - let pins = (pins.0.into(), pins.1.into(), pins.2.into()); + let pins = (pins.0.into(), NoPin::new().into(), pins.1.into()); Self::_new(spi, pins) .pre_init(mode.into(), freq, SPI::clock(clocks)) @@ -504,20 +503,18 @@ impl SpiSlave { /// Otherwise it may lead to the 'wrong last bit in every received byte' problem. pub fn new_bidi( spi: SPI, - pins: ( - impl Into, - impl Into, - impl Into, - Option, - ), + pins: (impl Into, impl Into, Option), mode: impl Into, - ) -> Self { + ) -> Self + where + NoPin: Into, + { unsafe { SPI::enable_unchecked(); SPI::reset_unchecked(); } - let pins = (pins.0.into(), pins.1.into(), pins.2.into(), pins.3); + let pins = (pins.0.into(), pins.1.into(), NoPin::new().into(), pins.2); Self::_new(spi, pins).pre_init(mode.into()).init() } @@ -729,6 +726,16 @@ impl Inner { self.spi.sr.read().ovr().bit_is_set() } + #[inline] + fn bidi_output(&mut self) { + self.spi.cr1.modify(|_, w| w.bidioe().set_bit()); + } + + #[inline] + fn bidi_input(&mut self) { + self.spi.cr1.modify(|_, w| w.bidioe().set_bit()); + } + fn read_data_reg(&mut self) -> W { // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows // reading a half-word) @@ -863,14 +870,14 @@ unsafe impl DMASet Spi { pub fn read_nonblocking(&mut self) -> nb::Result { if BIDI { - self.spi.cr1.modify(|_, w| w.bidioe().clear_bit()); + self.bidi_input(); } self.check_read() } pub fn write_nonblocking(&mut self, byte: W) -> nb::Result<(), Error> { if BIDI { - self.spi.cr1.modify(|_, w| w.bidioe().set_bit()); + self.bidi_output(); } self.check_send(byte) } @@ -900,10 +907,31 @@ impl Spi { } pub fn write(&mut self, words: &[W]) -> Result<(), Error> { - for word in words { - nb::block!(self.write_nonblocking(*word))?; - if !BIDI { - nb::block!(self.read_nonblocking())?; + if BIDI { + self.bidi_output(); + for word in words { + nb::block!(self.check_send(*word))?; + } + } else { + for word in words { + nb::block!(self.check_send(*word))?; + nb::block!(self.check_read::())?; + } + } + + Ok(()) + } + + pub fn write_iter(&mut self, words: impl IntoIterator) -> Result<(), Error> { + if BIDI { + self.bidi_output(); + for word in words.into_iter() { + nb::block!(self.check_send(word))?; + } + } else { + for word in words.into_iter() { + nb::block!(self.check_send(word))?; + nb::block!(self.check_read::())?; } } @@ -911,9 +939,16 @@ impl Spi { } pub fn read(&mut self, words: &mut [W]) -> Result<(), Error> { - for word in words { - nb::block!(self.write_nonblocking(W::default()))?; - *word = nb::block!(self.read_nonblocking())?; + if BIDI { + self.bidi_input(); + for word in words { + *word = nb::block!(self.check_read())?; + } + } else { + for word in words { + nb::block!(self.check_send(W::default()))?; + *word = nb::block!(self.check_read())?; + } } Ok(()) @@ -923,14 +958,14 @@ impl Spi { impl SpiSlave { pub fn read_nonblocking(&mut self) -> nb::Result { if BIDI { - self.spi.cr1.modify(|_, w| w.bidioe().clear_bit()); + self.bidi_input(); } self.check_read() } pub fn write_nonblocking(&mut self, byte: W) -> nb::Result<(), Error> { if BIDI { - self.spi.cr1.modify(|_, w| w.bidioe().set_bit()); + self.bidi_output(); } self.check_send(byte) } @@ -960,10 +995,15 @@ impl SpiSlave { } pub fn write(&mut self, words: &[W]) -> Result<(), Error> { - for word in words { - nb::block!(self.write_nonblocking(*word))?; - if !BIDI { - nb::block!(self.read_nonblocking())?; + if BIDI { + self.bidi_output(); + for word in words { + nb::block!(self.check_send(*word))?; + } + } else { + for word in words { + nb::block!(self.check_send(*word))?; + nb::block!(self.check_read::())?; } } @@ -971,9 +1011,16 @@ impl SpiSlave { } pub fn read(&mut self, words: &mut [W]) -> Result<(), Error> { - for word in words { - nb::block!(self.write_nonblocking(W::default()))?; - *word = nb::block!(self.read_nonblocking())?; + if BIDI { + self.bidi_input(); + for word in words { + *word = nb::block!(self.check_read())?; + } + } else { + for word in words { + nb::block!(self.check_send(W::default()))?; + *word = nb::block!(self.check_read())?; + } } Ok(()) diff --git a/src/spi/hal_02.rs b/src/spi/hal_02.rs index 0f6b8496..310d2d37 100644 --- a/src/spi/hal_02.rs +++ b/src/spi/hal_02.rs @@ -51,7 +51,7 @@ mod blocking { use super::super::{Error, Instance, Spi}; use embedded_hal::blocking::spi::{Operation, Transactional, Transfer, Write, WriteIter}; - impl Transfer for Spi + impl Transfer for Spi where SPI: Instance, { @@ -64,7 +64,7 @@ mod blocking { } } - impl Transfer for Spi + impl Transfer for Spi where SPI: Instance, { @@ -97,14 +97,7 @@ mod blocking { where WI: IntoIterator, { - for word in words.into_iter() { - nb::block!(self.write_nonblocking(word))?; - if !BIDI { - nb::block!(self.read_nonblocking())?; - } - } - - Ok(()) + self.write_iter(words) } } @@ -129,14 +122,7 @@ mod blocking { where WI: IntoIterator, { - for word in words.into_iter() { - nb::block!(self.write_nonblocking(word))?; - if !BIDI { - nb::block!(self.read_nonblocking())?; - } - } - - Ok(()) + self.write_iter(words) } } diff --git a/src/spi/hal_1.rs b/src/spi/hal_1.rs index a62a77f1..db9d9f51 100644 --- a/src/spi/hal_1.rs +++ b/src/spi/hal_1.rs @@ -78,23 +78,11 @@ mod blocking { } fn read(&mut self, words: &mut [W]) -> Result<(), Self::Error> { - for word in words { - nb::block!(self.write_nonblocking(W::default()))?; - *word = nb::block!(self.read_nonblocking())?; - } - - Ok(()) + self.read(words) } fn write(&mut self, words: &[W]) -> Result<(), Self::Error> { - for word in words { - nb::block!(self.write_nonblocking(*word))?; - if !BIDI { - nb::block!(self.read_nonblocking())?; - } - } - - Ok(()) + self.write(words) } fn flush(&mut self) -> Result<(), Self::Error> {