Skip to content

Commit d9e693d

Browse files
committed
enhance(spi): impl half-duplex spi
1 parent ce135a4 commit d9e693d

File tree

2 files changed

+77
-9
lines changed

2 files changed

+77
-9
lines changed

examples/hpm5300evk/src/bin/qspi.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -282,14 +282,12 @@ fn main() -> ! {
282282
// PA10
283283
let mut led = Output::new(p.PA10, Level::Low, Speed::Fast);
284284

285-
let spi_config = Config {
286-
frequency: Hertz(40_000_000),
287-
mode: MODE_0,
288-
timing: Timings {
289-
cs2sclk: hpm_hal::spi::Cs2Sclk::_1HalfSclk,
290-
csht: hpm_hal::spi::CsHighTime::_8HalfSclk,
291-
},
292-
..Default::default()
285+
let mut spi_config = Config::default();
286+
spi_config.frequency = Hertz(40_000_000);
287+
spi_config.mode = MODE_0;
288+
spi_config.timing = Timings {
289+
cs2sclk: hpm_hal::spi::Cs2Sclk::_1HalfSclk,
290+
csht: hpm_hal::spi::CsHighTime::_8HalfSclk,
293291
};
294292

295293
let spi: hal::spi::Spi<'_, Blocking> =

src/spi/mod.rs

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ pub struct Config {
142142
pub frequency: Hertz,
143143
/// Timings
144144
pub timing: Timings,
145+
/// Half duplex mode, only MOSI is used.
146+
pub half_duplex: bool,
145147
}
146148

147149
impl Default for Config {
@@ -151,6 +153,7 @@ impl Default for Config {
151153
mode: MODE_0,
152154
frequency: Hertz(10_000_000),
153155
timing: Timings::default(),
156+
half_duplex: false,
154157
}
155158
}
156159
}
@@ -253,6 +256,36 @@ impl<'d> Spi<'d, Blocking> {
253256
)
254257
}
255258

259+
pub fn new_blocking_half_duplex<T: Instance>(
260+
peri: impl Peripheral<P = T> + 'd,
261+
sclk: impl Peripheral<P = impl SclkPin<T>> + 'd,
262+
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
263+
mut config: Config,
264+
) -> Self {
265+
into_ref!(sclk, mosi);
266+
267+
T::add_resource_group(0);
268+
269+
mosi.set_as_alt(mosi.alt_num());
270+
sclk.ioc_pad().func_ctl().modify(|w| {
271+
w.set_alt_select(sclk.alt_num());
272+
w.set_loop_back(true);
273+
});
274+
config.half_duplex = true;
275+
276+
Self::new_inner(
277+
peri,
278+
Some(sclk.map_into()),
279+
Some(mosi.map_into()),
280+
None,
281+
None,
282+
None,
283+
None,
284+
None,
285+
config,
286+
)
287+
}
288+
256289
pub fn new_blocking_rxonly<T: Instance>(
257290
peri: impl Peripheral<P = T> + 'd,
258291
sclk: impl Peripheral<P = impl SclkPin<T>> + 'd,
@@ -406,6 +439,39 @@ impl<'d> Spi<'d, Async> {
406439
)
407440
}
408441

442+
pub fn new_half_duplex<T: Instance>(
443+
peri: impl Peripheral<P = T> + 'd,
444+
sclk: impl Peripheral<P = impl SclkPin<T>> + 'd,
445+
mosi: impl Peripheral<P = impl MosiPin<T>> + 'd,
446+
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
447+
rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
448+
mut config: Config,
449+
) -> Self {
450+
into_ref!(sclk, mosi);
451+
452+
T::add_resource_group(0);
453+
454+
mosi.set_as_alt(mosi.alt_num());
455+
sclk.ioc_pad().func_ctl().modify(|w| {
456+
w.set_alt_select(sclk.alt_num());
457+
w.set_loop_back(true);
458+
});
459+
460+
config.half_duplex = true;
461+
462+
Self::new_inner(
463+
peri,
464+
Some(sclk.map_into()),
465+
Some(mosi.map_into()),
466+
None,
467+
None,
468+
None,
469+
new_dma!(tx_dma),
470+
new_dma!(rx_dma),
471+
config,
472+
)
473+
}
474+
409475
pub fn new_rxonly<T: Instance>(
410476
peri: impl Peripheral<P = T> + 'd,
411477
sclk: impl Peripheral<P = impl SclkPin<T>> + 'd,
@@ -690,7 +756,11 @@ impl<'d, M: PeriMode> Spi<'d, M> {
690756
// 32 bit data length only works when the data is 32bit aligned
691757
w.set_datalen(<u8 as SealedWord>::CONFIG);
692758
w.set_datamerge(false);
693-
w.set_mosibidir(false);
759+
if config.half_duplex {
760+
w.set_mosibidir(true);
761+
} else {
762+
w.set_mosibidir(false);
763+
}
694764
w.set_lsb(config.bit_order == BitOrder::LsbFirst);
695765
w.set_slvmode(false); // default master mode
696766
w.set_cpha(cpha);

0 commit comments

Comments
 (0)