Skip to content

Commit fa67f41

Browse files
bors[bot]burrbull
andauthored
Merge #524
524: Spi u16 frame r=therealprof a=burrbull part of #523 Co-authored-by: Andrey Zgarbul <zgarbul.andrey@gmail.com>
2 parents aa10e6f + df01d0d commit fa67f41

File tree

4 files changed

+185
-65
lines changed

4 files changed

+185
-65
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99

1010
### Changed
1111

12+
- Support `u16` read/write for SPI
1213
- Use `bool` for BIDI mode type
1314
- `PwmHz::get_period`: fix computation of return value, prevent division by zero
1415
- apply #[inline] attribute to bitbanding functions [#517]

src/spi.rs

Lines changed: 116 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,32 @@ impl Ms for Master {
131131
const MSTR: bool = true;
132132
}
133133

134+
pub trait FrameSize: Copy + Default {
135+
const DFF: bool;
136+
}
137+
138+
impl FrameSize for u8 {
139+
const DFF: bool = false;
140+
}
141+
142+
impl FrameSize for u16 {
143+
const DFF: bool = true;
144+
}
145+
146+
/// The bit format to send the data in
147+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
148+
pub enum BitFormat {
149+
/// Least significant bit first
150+
LsbFirst,
151+
/// Most significant bit first
152+
MsbFirst,
153+
}
154+
134155
#[derive(Debug)]
135-
pub struct Spi<SPI, PINS, const BIDI: bool = false, OPERATION = Master> {
156+
pub struct Spi<SPI, PINS, const BIDI: bool = false, W = u8, OPERATION = Master> {
136157
spi: SPI,
137158
pins: PINS,
138-
_operation: PhantomData<OPERATION>,
159+
_operation: PhantomData<(W, OPERATION)>,
139160
}
140161

141162
// Implemented by all SPI instances
@@ -149,8 +170,8 @@ pub trait Instance:
149170
// Implemented by all SPI instances
150171
macro_rules! spi {
151172
($SPI:ty: $Spi:ident) => {
152-
pub type $Spi<PINS, const BIDI: bool = false, OPERATION = Master> =
153-
Spi<$SPI, PINS, BIDI, OPERATION>;
173+
pub type $Spi<PINS, const BIDI: bool = false, W = u8, OPERATION = Master> =
174+
Spi<$SPI, PINS, BIDI, W, OPERATION>;
154175

155176
impl Instance for $SPI {
156177
fn ptr() -> *const spi1::RegisterBlock {
@@ -182,7 +203,7 @@ pub trait SpiExt: Sized + Instance {
182203
mode: impl Into<Mode>,
183204
freq: Hertz,
184205
clocks: &Clocks,
185-
) -> Spi<Self, (SCK, MISO, MOSI), false, Master>
206+
) -> Spi<Self, (SCK, MISO, MOSI), false, u8, Master>
186207
where
187208
(SCK, MISO, MOSI): Pins<Self>;
188209
fn spi_bidi<SCK, MISO, MOSI>(
@@ -191,7 +212,7 @@ pub trait SpiExt: Sized + Instance {
191212
mode: impl Into<Mode>,
192213
freq: Hertz,
193214
clocks: &Clocks,
194-
) -> Spi<Self, (SCK, MISO, MOSI), true, Master>
215+
) -> Spi<Self, (SCK, MISO, MOSI), true, u8, Master>
195216
where
196217
(SCK, MISO, MOSI): Pins<Self>;
197218
fn spi_slave<SCK, MISO, MOSI>(
@@ -200,7 +221,7 @@ pub trait SpiExt: Sized + Instance {
200221
mode: impl Into<Mode>,
201222
freq: Hertz,
202223
clocks: &Clocks,
203-
) -> Spi<Self, (SCK, MISO, MOSI), false, Slave>
224+
) -> Spi<Self, (SCK, MISO, MOSI), false, u8, Slave>
204225
where
205226
(SCK, MISO, MOSI): Pins<Self>;
206227
fn spi_bidi_slave<SCK, MISO, MOSI>(
@@ -209,7 +230,7 @@ pub trait SpiExt: Sized + Instance {
209230
mode: impl Into<Mode>,
210231
freq: Hertz,
211232
clocks: &Clocks,
212-
) -> Spi<Self, (SCK, MISO, MOSI), true, Slave>
233+
) -> Spi<Self, (SCK, MISO, MOSI), true, u8, Slave>
213234
where
214235
(SCK, MISO, MOSI): Pins<Self>;
215236
}
@@ -221,7 +242,7 @@ impl<SPI: Instance> SpiExt for SPI {
221242
mode: impl Into<Mode>,
222243
freq: Hertz,
223244
clocks: &Clocks,
224-
) -> Spi<Self, (SCK, MISO, MOSI), false, Master>
245+
) -> Spi<Self, (SCK, MISO, MOSI), false, u8, Master>
225246
where
226247
(SCK, MISO, MOSI): Pins<Self>,
227248
{
@@ -233,7 +254,7 @@ impl<SPI: Instance> SpiExt for SPI {
233254
mode: impl Into<Mode>,
234255
freq: Hertz,
235256
clocks: &Clocks,
236-
) -> Spi<Self, (SCK, MISO, MOSI), true, Master>
257+
) -> Spi<Self, (SCK, MISO, MOSI), true, u8, Master>
237258
where
238259
(SCK, MISO, MOSI): Pins<Self>,
239260
{
@@ -245,7 +266,7 @@ impl<SPI: Instance> SpiExt for SPI {
245266
mode: impl Into<Mode>,
246267
freq: Hertz,
247268
clocks: &Clocks,
248-
) -> Spi<Self, (SCK, MISO, MOSI), false, Slave>
269+
) -> Spi<Self, (SCK, MISO, MOSI), false, u8, Slave>
249270
where
250271
(SCK, MISO, MOSI): Pins<Self>,
251272
{
@@ -257,22 +278,26 @@ impl<SPI: Instance> SpiExt for SPI {
257278
mode: impl Into<Mode>,
258279
freq: Hertz,
259280
clocks: &Clocks,
260-
) -> Spi<Self, (SCK, MISO, MOSI), true, Slave>
281+
) -> Spi<Self, (SCK, MISO, MOSI), true, u8, Slave>
261282
where
262283
(SCK, MISO, MOSI): Pins<Self>,
263284
{
264285
Spi::new_bidi_slave(self, pins, mode, freq, clocks)
265286
}
266287
}
267288

268-
impl<SPI: Instance, PINS, const BIDI: bool, OPERATION: Ms> Spi<SPI, PINS, BIDI, OPERATION> {
289+
impl<SPI: Instance, PINS, const BIDI: bool, W: FrameSize, OPERATION: Ms>
290+
Spi<SPI, PINS, BIDI, W, OPERATION>
291+
{
269292
pub fn init(self) -> Self {
270293
self.spi.cr1.modify(|_, w| {
271294
// bidimode: 2-line or 1-line unidirectional
272295
w.bidimode().bit(BIDI);
273296
w.bidioe().bit(BIDI);
274297
// master/slave mode
275298
w.mstr().bit(OPERATION::MSTR);
299+
// data frame size
300+
w.dff().bit(W::DFF);
276301
// spe: enable the SPI bus
277302
w.spe().set_bit()
278303
});
@@ -281,31 +306,51 @@ impl<SPI: Instance, PINS, const BIDI: bool, OPERATION: Ms> Spi<SPI, PINS, BIDI,
281306
}
282307
}
283308

284-
impl<SPI: Instance, PINS, OPERATION: Ms> Spi<SPI, PINS, false, OPERATION> {
285-
pub fn to_bidi_transfer_mode(self) -> Spi<SPI, PINS, true, OPERATION> {
309+
impl<SPI: Instance, PINS, W: FrameSize, OPERATION: Ms> Spi<SPI, PINS, false, W, OPERATION> {
310+
pub fn to_bidi_transfer_mode(self) -> Spi<SPI, PINS, true, W, OPERATION> {
311+
self.into_mode()
312+
}
313+
}
314+
315+
impl<SPI: Instance, PINS, W: FrameSize, OPERATION: Ms> Spi<SPI, PINS, true, W, OPERATION> {
316+
pub fn to_normal_transfer_mode(self) -> Spi<SPI, PINS, false, W, OPERATION> {
317+
self.into_mode()
318+
}
319+
}
320+
321+
impl<SPI: Instance, PINS, const BIDI: bool, W: FrameSize> Spi<SPI, PINS, BIDI, W, Master> {
322+
pub fn to_slave_operation(self) -> Spi<SPI, PINS, BIDI, W, Slave> {
286323
self.into_mode()
287324
}
288325
}
289326

290-
impl<SPI: Instance, PINS, OPERATION: Ms> Spi<SPI, PINS, true, OPERATION> {
291-
pub fn to_normal_transfer_mode(self) -> Spi<SPI, PINS, false, OPERATION> {
327+
impl<SPI: Instance, PINS, const BIDI: bool, W: FrameSize> Spi<SPI, PINS, BIDI, W, Slave> {
328+
pub fn to_master_operation(self) -> Spi<SPI, PINS, BIDI, W, Master> {
292329
self.into_mode()
293330
}
294331
}
295332

296-
impl<SPI: Instance, PINS, const BIDI: bool> Spi<SPI, PINS, BIDI, Master> {
297-
pub fn to_slave_operation(self) -> Spi<SPI, PINS, BIDI, Slave> {
333+
impl<SPI, PINS, const BIDI: bool, OPERATION: Ms> Spi<SPI, PINS, BIDI, u8, OPERATION>
334+
where
335+
SPI: Instance,
336+
{
337+
/// Converts from 8bit dataframe to 16bit.
338+
pub fn frame_size_16bit(self) -> Spi<SPI, PINS, BIDI, u16, OPERATION> {
298339
self.into_mode()
299340
}
300341
}
301342

302-
impl<SPI: Instance, PINS, const BIDI: bool> Spi<SPI, PINS, BIDI, Slave> {
303-
pub fn to_master_operation(self) -> Spi<SPI, PINS, BIDI, Master> {
343+
impl<SPI, PINS, const BIDI: bool, OPERATION: Ms> Spi<SPI, PINS, BIDI, u16, OPERATION>
344+
where
345+
SPI: Instance,
346+
{
347+
/// Converts from 16bit dataframe to 8bit.
348+
pub fn frame_size_8bit(self) -> Spi<SPI, PINS, BIDI, u8, OPERATION> {
304349
self.into_mode()
305350
}
306351
}
307352

308-
impl<SPI: Instance, SCK, MISO, MOSI> Spi<SPI, (SCK, MISO, MOSI), false, Master> {
353+
impl<SPI: Instance, SCK, MISO, MOSI> Spi<SPI, (SCK, MISO, MOSI), false, u8, Master> {
309354
pub fn new(
310355
spi: SPI,
311356
mut pins: (SCK, MISO, MOSI),
@@ -331,7 +376,7 @@ impl<SPI: Instance, SCK, MISO, MOSI> Spi<SPI, (SCK, MISO, MOSI), false, Master>
331376
}
332377
}
333378

334-
impl<SPI: Instance, SCK, MISO, MOSI> Spi<SPI, (SCK, MISO, MOSI), true, Master> {
379+
impl<SPI: Instance, SCK, MISO, MOSI> Spi<SPI, (SCK, MISO, MOSI), true, u8, Master> {
335380
pub fn new_bidi(
336381
spi: SPI,
337382
mut pins: (SCK, MISO, MOSI),
@@ -357,7 +402,7 @@ impl<SPI: Instance, SCK, MISO, MOSI> Spi<SPI, (SCK, MISO, MOSI), true, Master> {
357402
}
358403
}
359404

360-
impl<SPI: Instance, SCK, MISO, MOSI> Spi<SPI, (SCK, MISO, MOSI), false, Slave> {
405+
impl<SPI: Instance, SCK, MISO, MOSI> Spi<SPI, (SCK, MISO, MOSI), false, u8, Slave> {
361406
pub fn new_slave(
362407
spi: SPI,
363408
mut pins: (SCK, MISO, MOSI),
@@ -383,7 +428,7 @@ impl<SPI: Instance, SCK, MISO, MOSI> Spi<SPI, (SCK, MISO, MOSI), false, Slave> {
383428
}
384429
}
385430

386-
impl<SPI: Instance, SCK, MISO, MOSI> Spi<SPI, (SCK, MISO, MOSI), true, Slave> {
431+
impl<SPI: Instance, SCK, MISO, MOSI> Spi<SPI, (SCK, MISO, MOSI), true, u8, Slave> {
387432
pub fn new_bidi_slave(
388433
spi: SPI,
389434
mut pins: (SCK, MISO, MOSI),
@@ -421,7 +466,7 @@ where
421466
}
422467
}
423468

424-
impl<SPI: Instance, PINS, const BIDI: bool, OPERATION> Spi<SPI, PINS, BIDI, OPERATION> {
469+
impl<SPI: Instance, PINS, const BIDI: bool, W, OPERATION> Spi<SPI, PINS, BIDI, W, OPERATION> {
425470
fn _new(spi: SPI, pins: PINS) -> Self {
426471
Self {
427472
spi,
@@ -431,7 +476,9 @@ impl<SPI: Instance, PINS, const BIDI: bool, OPERATION> Spi<SPI, PINS, BIDI, OPER
431476
}
432477

433478
/// Convert the spi to another mode.
434-
fn into_mode<const BIDI2: bool, OPERATION2: Ms>(self) -> Spi<SPI, PINS, BIDI2, OPERATION2> {
479+
fn into_mode<const BIDI2: bool, W2: FrameSize, OPERATION2: Ms>(
480+
self,
481+
) -> Spi<SPI, PINS, BIDI2, W2, OPERATION2> {
435482
let mut spi = Spi::_new(self.spi, self.pins);
436483
spi.enable(false);
437484
spi.init()
@@ -482,6 +529,14 @@ impl<SPI: Instance, PINS, const BIDI: bool, OPERATION> Spi<SPI, PINS, BIDI, OPER
482529
self
483530
}
484531

532+
/// Select which frame format is used for data transfers
533+
pub fn bit_format(&mut self, format: BitFormat) {
534+
match format {
535+
BitFormat::LsbFirst => self.spi.cr1.modify(|_, w| w.lsbfirst().set_bit()),
536+
BitFormat::MsbFirst => self.spi.cr1.modify(|_, w| w.lsbfirst().clear_bit()),
537+
}
538+
}
539+
485540
/// Enable interrupts for the given `event`:
486541
/// - Received data ready to be read (RXNE)
487542
/// - Transmit data register empty (TXE)
@@ -550,13 +605,36 @@ impl<SPI: Instance, PINS, const BIDI: bool, OPERATION> Spi<SPI, PINS, BIDI, OPER
550605
pub fn is_overrun(&self) -> bool {
551606
self.spi.sr.read().ovr().bit_is_set()
552607
}
608+
}
553609

554-
pub fn use_dma(self) -> DmaBuilder<SPI> {
555-
DmaBuilder { spi: self.spi }
610+
trait ReadWriteReg<W> {
611+
fn read_data_reg(&mut self) -> W;
612+
fn write_data_reg(&mut self, data: W);
613+
}
614+
615+
impl<SPI, PINS, const BIDI: bool, W, OPERATION> ReadWriteReg<W>
616+
for Spi<SPI, PINS, BIDI, W, OPERATION>
617+
where
618+
SPI: Instance,
619+
W: FrameSize,
620+
{
621+
fn read_data_reg(&mut self) -> W {
622+
// NOTE(read_volatile) read only 1 byte (the svd2rust API only allows
623+
// reading a half-word)
624+
unsafe { ptr::read_volatile(&self.spi.dr as *const _ as *const W) }
556625
}
557626

627+
fn write_data_reg(&mut self, data: W) {
628+
// NOTE(write_volatile) see note above
629+
unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut W, data) }
630+
}
631+
}
632+
633+
impl<SPI: Instance, PINS, const BIDI: bool, W: FrameSize, OPERATION>
634+
Spi<SPI, PINS, BIDI, W, OPERATION>
635+
{
558636
#[inline(always)]
559-
fn check_read(&mut self) -> nb::Result<u8, Error> {
637+
fn check_read(&mut self) -> nb::Result<W, Error> {
560638
let sr = self.spi.sr.read();
561639

562640
Err(if sr.ovr().bit_is_set() {
@@ -566,14 +644,14 @@ impl<SPI: Instance, PINS, const BIDI: bool, OPERATION> Spi<SPI, PINS, BIDI, OPER
566644
} else if sr.crcerr().bit_is_set() {
567645
Error::Crc.into()
568646
} else if sr.rxne().bit_is_set() {
569-
return Ok(self.read_u8());
647+
return Ok(self.read_data_reg());
570648
} else {
571649
nb::Error::WouldBlock
572650
})
573651
}
574652

575653
#[inline(always)]
576-
fn check_send(&mut self, byte: u8) -> nb::Result<(), Error> {
654+
fn check_send(&mut self, byte: W) -> nb::Result<(), Error> {
577655
let sr = self.spi.sr.read();
578656

579657
Err(if sr.ovr().bit_is_set() {
@@ -592,23 +670,19 @@ impl<SPI: Instance, PINS, const BIDI: bool, OPERATION> Spi<SPI, PINS, BIDI, OPER
592670
});
593671
Error::Crc.into()
594672
} else if sr.txe().bit_is_set() {
595-
self.send_u8(byte);
673+
self.write_data_reg(byte);
596674
return Ok(());
597675
} else {
598676
nb::Error::WouldBlock
599677
})
600678
}
679+
}
601680

602-
#[inline(always)]
603-
fn read_u8(&mut self) -> u8 {
604-
// NOTE(read_volatile) read only 1 byte (the svd2rust API only allows reading a half-word)
605-
unsafe { ptr::read_volatile(&self.spi.dr as *const _ as *const u8) }
606-
}
681+
// Spi DMA
607682

608-
#[inline(always)]
609-
fn send_u8(&mut self, byte: u8) {
610-
// NOTE(write_volatile) see note above
611-
unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u8, byte) }
683+
impl<SPI: Instance, PINS, const BIDI: bool> Spi<SPI, PINS, BIDI, u8, Master> {
684+
pub fn use_dma(self) -> DmaBuilder<SPI> {
685+
DmaBuilder { spi: self.spi }
612686
}
613687
}
614688

0 commit comments

Comments
 (0)