Skip to content

Commit

Permalink
SPI bidi 2 pins & rm unused bidioe
Browse files Browse the repository at this point in the history
  • Loading branch information
burrbull committed Aug 9, 2023
1 parent 47404df commit aa7579f
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 85 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -469,7 +474,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- [breaking-change] Change `Pin<Output<OpenDrain>>::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
Expand Down
5 changes: 2 additions & 3 deletions examples/ist7920-bidi-normal-spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
Expand All @@ -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);

Expand Down
145 changes: 96 additions & 49 deletions src/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,15 +207,13 @@ pub trait SpiExt: Sized + Instance {

fn spi_bidi(
self,
pins: (
impl Into<Self::Sck>,
impl Into<Self::Miso>,
impl Into<Self::Mosi>,
),
pins: (impl Into<Self::Sck>, impl Into<Self::Mosi>),
mode: impl Into<Mode>,
freq: Hertz,
clocks: &Clocks,
) -> Spi<Self, true, u8>;
) -> Spi<Self, true, u8>
where
NoPin: Into<Self::Miso>;

fn spi_slave(
self,
Expand All @@ -233,11 +231,12 @@ pub trait SpiExt: Sized + Instance {
pins: (
impl Into<Self::Sck>,
impl Into<Self::Miso>,
impl Into<Self::Mosi>,
Option<Self::Nss>,
),
mode: impl Into<Mode>,
) -> SpiSlave<Self, true, u8>;
) -> SpiSlave<Self, true, u8>
where
NoPin: Into<Self::Mosi>;
}

impl<SPI: Instance> SpiExt for SPI {
Expand Down Expand Up @@ -266,15 +265,14 @@ impl<SPI: Instance> SpiExt for SPI {
/// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
fn spi_bidi(
self,
pins: (
impl Into<Self::Sck>,
impl Into<Self::Miso>,
impl Into<Self::Mosi>,
),
pins: (impl Into<Self::Sck>, impl Into<Self::Mosi>),
mode: impl Into<Mode>,
freq: Hertz,
clocks: &Clocks,
) -> Spi<Self, true, u8> {
) -> Spi<Self, true, u8>
where
NoPin: Into<Self::Miso>,
{
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.
Expand Down Expand Up @@ -304,11 +302,13 @@ impl<SPI: Instance> SpiExt for SPI {
pins: (
impl Into<Self::Sck>,
impl Into<Self::Miso>,
impl Into<Self::Mosi>,
Option<Self::Nss>,
),
mode: impl Into<Mode>,
) -> SpiSlave<Self, true, u8> {
) -> SpiSlave<Self, true, u8>
where
NoPin: Into<Self::Mosi>,
{
SpiSlave::new_bidi(self, pins, mode)
}
}
Expand Down Expand Up @@ -447,21 +447,20 @@ impl<SPI: Instance> Spi<SPI, true, u8> {
/// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
pub fn new_bidi(
spi: SPI,
pins: (
impl Into<SPI::Sck>,
impl Into<SPI::Miso>,
impl Into<SPI::Mosi>,
),
pins: (impl Into<SPI::Sck>, impl Into<SPI::Mosi>),
mode: impl Into<Mode>,
freq: Hertz,
clocks: &Clocks,
) -> Self {
) -> Self
where
NoPin: Into<SPI::Miso>,
{
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))
Expand Down Expand Up @@ -504,20 +503,18 @@ impl<SPI: Instance> SpiSlave<SPI, true, u8> {
/// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
pub fn new_bidi(
spi: SPI,
pins: (
impl Into<SPI::Sck>,
impl Into<SPI::Miso>,
impl Into<SPI::Mosi>,
Option<SPI::Nss>,
),
pins: (impl Into<SPI::Sck>, impl Into<SPI::Miso>, Option<SPI::Nss>),
mode: impl Into<Mode>,
) -> Self {
) -> Self
where
NoPin: Into<SPI::Mosi>,
{
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()
}
Expand Down Expand Up @@ -729,6 +726,16 @@ impl<SPI: Instance> Inner<SPI> {
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<W: FrameSize>(&mut self) -> W {
// NOTE(read_volatile) read only 1 byte (the svd2rust API only allows
// reading a half-word)
Expand Down Expand Up @@ -863,14 +870,14 @@ unsafe impl<SPI, STREAM, const CHANNEL: u8> DMASet<STREAM, CHANNEL, MemoryToPeri
impl<SPI: Instance, const BIDI: bool, W: FrameSize> Spi<SPI, BIDI, W> {
pub fn read_nonblocking(&mut self) -> nb::Result<W, Error> {
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)
}
Expand Down Expand Up @@ -900,20 +907,48 @@ impl<SPI: Instance, const BIDI: bool, W: FrameSize> Spi<SPI, BIDI, W> {
}

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::<W>())?;
}
}

Ok(())
}

pub fn write_iter(&mut self, words: impl IntoIterator<Item = W>) -> 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::<W>())?;
}
}

Ok(())
}

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(())
Expand All @@ -923,14 +958,14 @@ impl<SPI: Instance, const BIDI: bool, W: FrameSize> Spi<SPI, BIDI, W> {
impl<SPI: Instance, const BIDI: bool, W: FrameSize> SpiSlave<SPI, BIDI, W> {
pub fn read_nonblocking(&mut self) -> nb::Result<W, Error> {
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)
}
Expand Down Expand Up @@ -960,20 +995,32 @@ impl<SPI: Instance, const BIDI: bool, W: FrameSize> SpiSlave<SPI, BIDI, W> {
}

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::<W>())?;
}
}

Ok(())
}

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(())
Expand Down
22 changes: 4 additions & 18 deletions src/spi/hal_02.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ mod blocking {
use super::super::{Error, Instance, Spi};
use embedded_hal::blocking::spi::{Operation, Transactional, Transfer, Write, WriteIter};

impl<SPI, const BIDI: bool> Transfer<u8> for Spi<SPI, BIDI, u8>
impl<SPI> Transfer<u8> for Spi<SPI, false, u8>
where
SPI: Instance,
{
Expand All @@ -64,7 +64,7 @@ mod blocking {
}
}

impl<SPI, const BIDI: bool> Transfer<u16> for Spi<SPI, BIDI, u16>
impl<SPI> Transfer<u16> for Spi<SPI, false, u16>
where
SPI: Instance,
{
Expand Down Expand Up @@ -97,14 +97,7 @@ mod blocking {
where
WI: IntoIterator<Item = u8>,
{
for word in words.into_iter() {
nb::block!(self.write_nonblocking(word))?;
if !BIDI {
nb::block!(self.read_nonblocking())?;
}
}

Ok(())
self.write_iter(words)
}
}

Expand All @@ -129,14 +122,7 @@ mod blocking {
where
WI: IntoIterator<Item = u16>,
{
for word in words.into_iter() {
nb::block!(self.write_nonblocking(word))?;
if !BIDI {
nb::block!(self.read_nonblocking())?;
}
}

Ok(())
self.write_iter(words)
}
}

Expand Down
Loading

0 comments on commit aa7579f

Please sign in to comment.