Skip to content

Commit 6a05a0e

Browse files
authored
Merge pull request #526 from stm32-rs/duplex
SPI bidi 2 pins & rm unused bidioe
2 parents 47404df + fcce24f commit 6a05a0e

File tree

5 files changed

+106
-84
lines changed

5 files changed

+106
-84
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1010
- complete and rework Dma Stream API [#666]
1111
- add `.set_count()` for QEI, add `.write_count()` for TIM [#677]
1212
- add "Fast start" section in README [#678]
13+
- SPI bidi takes 2 pins [#526]
1314

15+
[#526]: https://github.com/stm32-rs/stm32f4xx-hal/pull/526
1416
[#666]: https://github.com/stm32-rs/stm32f4xx-hal/pull/666
1517
[#677]: https://github.com/stm32-rs/stm32f4xx-hal/pull/677
1618
[#678]: https://github.com/stm32-rs/stm32f4xx-hal/pull/678

examples/ist7920-bidi-normal-spi.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use stm32f4xx_hal as hal;
99

1010
use crate::hal::{pac, prelude::*, timer::Timer};
1111

12-
use hal::spi::{Mode, NoMiso, Phase, Polarity};
12+
use hal::spi::{Mode, Phase, Polarity};
1313

1414
use display_interface_spi::SPIInterface;
1515
use ist7920::Ist7920;
@@ -29,7 +29,6 @@ fn main() -> ! {
2929
led.set_low();
3030

3131
let sck = gpiob.pb3.into_alternate();
32-
let miso = NoMiso::new();
3332
let mosi = gpiob.pb5;
3433

3534
let dc = gpiob.pb4.into_push_pull_output();
@@ -46,7 +45,7 @@ fn main() -> ! {
4645
// Change spi transfer mode to Bidi for more efficient operations.
4746
// let spi = Spi::new(dp.SPI1, (sck, miso, mosi), mode, 8.MHz(), &clocks).to_bidi_transfer_mode();
4847
// or
49-
let spi = dp.SPI1.spi_bidi((sck, miso, mosi), mode, 8.MHz(), &clocks);
48+
let spi = dp.SPI1.spi_bidi((sck, mosi), mode, 8.MHz(), &clocks);
5049

5150
let iface = SPIInterface::new(spi, dc, cs);
5251

src/spi.rs

Lines changed: 96 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -207,15 +207,13 @@ pub trait SpiExt: Sized + Instance {
207207

208208
fn spi_bidi(
209209
self,
210-
pins: (
211-
impl Into<Self::Sck>,
212-
impl Into<Self::Miso>,
213-
impl Into<Self::Mosi>,
214-
),
210+
pins: (impl Into<Self::Sck>, impl Into<Self::Mosi>),
215211
mode: impl Into<Mode>,
216212
freq: Hertz,
217213
clocks: &Clocks,
218-
) -> Spi<Self, true, u8>;
214+
) -> Spi<Self, true, u8>
215+
where
216+
NoPin: Into<Self::Miso>;
219217

220218
fn spi_slave(
221219
self,
@@ -233,11 +231,12 @@ pub trait SpiExt: Sized + Instance {
233231
pins: (
234232
impl Into<Self::Sck>,
235233
impl Into<Self::Miso>,
236-
impl Into<Self::Mosi>,
237234
Option<Self::Nss>,
238235
),
239236
mode: impl Into<Mode>,
240-
) -> SpiSlave<Self, true, u8>;
237+
) -> SpiSlave<Self, true, u8>
238+
where
239+
NoPin: Into<Self::Mosi>;
241240
}
242241

243242
impl<SPI: Instance> SpiExt for SPI {
@@ -266,15 +265,14 @@ impl<SPI: Instance> SpiExt for SPI {
266265
/// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
267266
fn spi_bidi(
268267
self,
269-
pins: (
270-
impl Into<Self::Sck>,
271-
impl Into<Self::Miso>,
272-
impl Into<Self::Mosi>,
273-
),
268+
pins: (impl Into<Self::Sck>, impl Into<Self::Mosi>),
274269
mode: impl Into<Mode>,
275270
freq: Hertz,
276271
clocks: &Clocks,
277-
) -> Spi<Self, true, u8> {
272+
) -> Spi<Self, true, u8>
273+
where
274+
NoPin: Into<Self::Miso>,
275+
{
278276
Spi::new_bidi(self, pins, mode, freq, clocks)
279277
}
280278
/// 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<SPI: Instance> SpiExt for SPI {
304302
pins: (
305303
impl Into<Self::Sck>,
306304
impl Into<Self::Miso>,
307-
impl Into<Self::Mosi>,
308305
Option<Self::Nss>,
309306
),
310307
mode: impl Into<Mode>,
311-
) -> SpiSlave<Self, true, u8> {
308+
) -> SpiSlave<Self, true, u8>
309+
where
310+
NoPin: Into<Self::Mosi>,
311+
{
312312
SpiSlave::new_bidi(self, pins, mode)
313313
}
314314
}
@@ -447,21 +447,20 @@ impl<SPI: Instance> Spi<SPI, true, u8> {
447447
/// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
448448
pub fn new_bidi(
449449
spi: SPI,
450-
pins: (
451-
impl Into<SPI::Sck>,
452-
impl Into<SPI::Miso>,
453-
impl Into<SPI::Mosi>,
454-
),
450+
pins: (impl Into<SPI::Sck>, impl Into<SPI::Mosi>),
455451
mode: impl Into<Mode>,
456452
freq: Hertz,
457453
clocks: &Clocks,
458-
) -> Self {
454+
) -> Self
455+
where
456+
NoPin: Into<SPI::Miso>,
457+
{
459458
unsafe {
460459
SPI::enable_unchecked();
461460
SPI::reset_unchecked();
462461
}
463462

464-
let pins = (pins.0.into(), pins.1.into(), pins.2.into());
463+
let pins = (pins.0.into(), NoPin::new().into(), pins.1.into());
465464

466465
Self::_new(spi, pins)
467466
.pre_init(mode.into(), freq, SPI::clock(clocks))
@@ -504,20 +503,18 @@ impl<SPI: Instance> SpiSlave<SPI, true, u8> {
504503
/// Otherwise it may lead to the 'wrong last bit in every received byte' problem.
505504
pub fn new_bidi(
506505
spi: SPI,
507-
pins: (
508-
impl Into<SPI::Sck>,
509-
impl Into<SPI::Miso>,
510-
impl Into<SPI::Mosi>,
511-
Option<SPI::Nss>,
512-
),
506+
pins: (impl Into<SPI::Sck>, impl Into<SPI::Miso>, Option<SPI::Nss>),
513507
mode: impl Into<Mode>,
514-
) -> Self {
508+
) -> Self
509+
where
510+
NoPin: Into<SPI::Mosi>,
511+
{
515512
unsafe {
516513
SPI::enable_unchecked();
517514
SPI::reset_unchecked();
518515
}
519516

520-
let pins = (pins.0.into(), pins.1.into(), pins.2.into(), pins.3);
517+
let pins = (pins.0.into(), pins.1.into(), NoPin::new().into(), pins.2);
521518

522519
Self::_new(spi, pins).pre_init(mode.into()).init()
523520
}
@@ -729,6 +726,16 @@ impl<SPI: Instance> Inner<SPI> {
729726
self.spi.sr.read().ovr().bit_is_set()
730727
}
731728

729+
#[inline]
730+
fn bidi_output(&mut self) {
731+
self.spi.cr1.modify(|_, w| w.bidioe().set_bit());
732+
}
733+
734+
#[inline]
735+
fn bidi_input(&mut self) {
736+
self.spi.cr1.modify(|_, w| w.bidioe().set_bit());
737+
}
738+
732739
fn read_data_reg<W: FrameSize>(&mut self) -> W {
733740
// NOTE(read_volatile) read only 1 byte (the svd2rust API only allows
734741
// reading a half-word)
@@ -863,14 +870,14 @@ unsafe impl<SPI, STREAM, const CHANNEL: u8> DMASet<STREAM, CHANNEL, MemoryToPeri
863870
impl<SPI: Instance, const BIDI: bool, W: FrameSize> Spi<SPI, BIDI, W> {
864871
pub fn read_nonblocking(&mut self) -> nb::Result<W, Error> {
865872
if BIDI {
866-
self.spi.cr1.modify(|_, w| w.bidioe().clear_bit());
873+
self.bidi_input();
867874
}
868875
self.check_read()
869876
}
870877

871878
pub fn write_nonblocking(&mut self, byte: W) -> nb::Result<(), Error> {
872879
if BIDI {
873-
self.spi.cr1.modify(|_, w| w.bidioe().set_bit());
880+
self.bidi_output();
874881
}
875882
self.check_send(byte)
876883
}
@@ -900,20 +907,48 @@ impl<SPI: Instance, const BIDI: bool, W: FrameSize> Spi<SPI, BIDI, W> {
900907
}
901908

902909
pub fn write(&mut self, words: &[W]) -> Result<(), Error> {
903-
for word in words {
904-
nb::block!(self.write_nonblocking(*word))?;
905-
if !BIDI {
906-
nb::block!(self.read_nonblocking())?;
910+
if BIDI {
911+
self.bidi_output();
912+
for word in words {
913+
nb::block!(self.check_send(*word))?;
914+
}
915+
} else {
916+
for word in words {
917+
nb::block!(self.check_send(*word))?;
918+
nb::block!(self.check_read::<W>())?;
919+
}
920+
}
921+
922+
Ok(())
923+
}
924+
925+
pub fn write_iter(&mut self, words: impl IntoIterator<Item = W>) -> Result<(), Error> {
926+
if BIDI {
927+
self.bidi_output();
928+
for word in words.into_iter() {
929+
nb::block!(self.check_send(word))?;
930+
}
931+
} else {
932+
for word in words.into_iter() {
933+
nb::block!(self.check_send(word))?;
934+
nb::block!(self.check_read::<W>())?;
907935
}
908936
}
909937

910938
Ok(())
911939
}
912940

913941
pub fn read(&mut self, words: &mut [W]) -> Result<(), Error> {
914-
for word in words {
915-
nb::block!(self.write_nonblocking(W::default()))?;
916-
*word = nb::block!(self.read_nonblocking())?;
942+
if BIDI {
943+
self.bidi_input();
944+
for word in words {
945+
*word = nb::block!(self.check_read())?;
946+
}
947+
} else {
948+
for word in words {
949+
nb::block!(self.check_send(W::default()))?;
950+
*word = nb::block!(self.check_read())?;
951+
}
917952
}
918953

919954
Ok(())
@@ -923,14 +958,14 @@ impl<SPI: Instance, const BIDI: bool, W: FrameSize> Spi<SPI, BIDI, W> {
923958
impl<SPI: Instance, const BIDI: bool, W: FrameSize> SpiSlave<SPI, BIDI, W> {
924959
pub fn read_nonblocking(&mut self) -> nb::Result<W, Error> {
925960
if BIDI {
926-
self.spi.cr1.modify(|_, w| w.bidioe().clear_bit());
961+
self.bidi_input();
927962
}
928963
self.check_read()
929964
}
930965

931966
pub fn write_nonblocking(&mut self, byte: W) -> nb::Result<(), Error> {
932967
if BIDI {
933-
self.spi.cr1.modify(|_, w| w.bidioe().set_bit());
968+
self.bidi_output();
934969
}
935970
self.check_send(byte)
936971
}
@@ -960,20 +995,32 @@ impl<SPI: Instance, const BIDI: bool, W: FrameSize> SpiSlave<SPI, BIDI, W> {
960995
}
961996

962997
pub fn write(&mut self, words: &[W]) -> Result<(), Error> {
963-
for word in words {
964-
nb::block!(self.write_nonblocking(*word))?;
965-
if !BIDI {
966-
nb::block!(self.read_nonblocking())?;
998+
if BIDI {
999+
self.bidi_output();
1000+
for word in words {
1001+
nb::block!(self.check_send(*word))?;
1002+
}
1003+
} else {
1004+
for word in words {
1005+
nb::block!(self.check_send(*word))?;
1006+
nb::block!(self.check_read::<W>())?;
9671007
}
9681008
}
9691009

9701010
Ok(())
9711011
}
9721012

9731013
pub fn read(&mut self, words: &mut [W]) -> Result<(), Error> {
974-
for word in words {
975-
nb::block!(self.write_nonblocking(W::default()))?;
976-
*word = nb::block!(self.read_nonblocking())?;
1014+
if BIDI {
1015+
self.bidi_input();
1016+
for word in words {
1017+
*word = nb::block!(self.check_read())?;
1018+
}
1019+
} else {
1020+
for word in words {
1021+
nb::block!(self.check_send(W::default()))?;
1022+
*word = nb::block!(self.check_read())?;
1023+
}
9771024
}
9781025

9791026
Ok(())

src/spi/hal_02.rs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ mod blocking {
5151
use super::super::{Error, Instance, Spi};
5252
use embedded_hal::blocking::spi::{Operation, Transactional, Transfer, Write, WriteIter};
5353

54-
impl<SPI, const BIDI: bool> Transfer<u8> for Spi<SPI, BIDI, u8>
54+
impl<SPI> Transfer<u8> for Spi<SPI, false, u8>
5555
where
5656
SPI: Instance,
5757
{
@@ -64,7 +64,7 @@ mod blocking {
6464
}
6565
}
6666

67-
impl<SPI, const BIDI: bool> Transfer<u16> for Spi<SPI, BIDI, u16>
67+
impl<SPI> Transfer<u16> for Spi<SPI, false, u16>
6868
where
6969
SPI: Instance,
7070
{
@@ -97,14 +97,7 @@ mod blocking {
9797
where
9898
WI: IntoIterator<Item = u8>,
9999
{
100-
for word in words.into_iter() {
101-
nb::block!(self.write_nonblocking(word))?;
102-
if !BIDI {
103-
nb::block!(self.read_nonblocking())?;
104-
}
105-
}
106-
107-
Ok(())
100+
self.write_iter(words)
108101
}
109102
}
110103

@@ -129,14 +122,7 @@ mod blocking {
129122
where
130123
WI: IntoIterator<Item = u16>,
131124
{
132-
for word in words.into_iter() {
133-
nb::block!(self.write_nonblocking(word))?;
134-
if !BIDI {
135-
nb::block!(self.read_nonblocking())?;
136-
}
137-
}
138-
139-
Ok(())
125+
self.write_iter(words)
140126
}
141127
}
142128

src/spi/hal_1.rs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -78,23 +78,11 @@ mod blocking {
7878
}
7979

8080
fn read(&mut self, words: &mut [W]) -> Result<(), Self::Error> {
81-
for word in words {
82-
nb::block!(self.write_nonblocking(W::default()))?;
83-
*word = nb::block!(self.read_nonblocking())?;
84-
}
85-
86-
Ok(())
81+
self.read(words)
8782
}
8883

8984
fn write(&mut self, words: &[W]) -> Result<(), Self::Error> {
90-
for word in words {
91-
nb::block!(self.write_nonblocking(*word))?;
92-
if !BIDI {
93-
nb::block!(self.read_nonblocking())?;
94-
}
95-
}
96-
97-
Ok(())
85+
self.write(words)
9886
}
9987

10088
fn flush(&mut self) -> Result<(), Self::Error> {

0 commit comments

Comments
 (0)