Skip to content

Commit 407eaf7

Browse files
committed
eh-1.0.0: spi
1 parent 20320b2 commit 407eaf7

File tree

4 files changed

+112
-31
lines changed

4 files changed

+112
-31
lines changed

examples/spi.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
use cortex_m_rt::entry;
66
#[macro_use]
77
mod utilities;
8+
9+
use embedded_hal::spi::*;
10+
use nb::block;
811
use stm32h7xx_hal::{pac, prelude::*, spi};
912

1013
use log::info;
1114

12-
use nb::block;
13-
1415
#[entry]
1516
fn main() -> ! {
1617
utilities::logger::init();

examples/spi_hardware_cs.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@
1616
use cortex_m_rt::entry;
1717
#[macro_use]
1818
mod utilities;
19+
20+
use embedded_hal::spi::*;
21+
use nb::block;
1922
use stm32h7xx_hal::{pac, prelude::*, spi};
2023

2124
use log::info;
2225

23-
use nb::block;
24-
2526
#[entry]
2627
fn main() -> ! {
2728
utilities::logger::init();

examples/spi_send_frames.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ use cortex_m_rt::entry;
1111
#[macro_use]
1212
mod utilities;
1313
use core::num::NonZeroU16;
14-
use spi::Spi;
14+
15+
use embedded_hal::spi::*;
1516
use stm32h7xx_hal::{pac, prelude::*, spi};
1617

1718
use log::info;
@@ -51,7 +52,7 @@ fn main() -> ! {
5152
info!("");
5253

5354
// Initialise the SPI peripheral.
54-
let mut spi: Spi<_, _, u8> = dp.SPI1.spi(
55+
let mut spi: spi::Spi<_, _, u8> = dp.SPI1.spi(
5556
// Give ownership of the pins
5657
(sck, miso, mosi, hcs),
5758
// Create a config with the hardware chip select given

src/spi.rs

Lines changed: 103 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ use core::ptr;
6969

7070
use crate::gpio::{self, Alternate};
7171
use crate::hal;
72-
use crate::hal::spi::FullDuplex;
7372
pub use crate::hal::spi::{
7473
Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3,
7574
};
@@ -107,6 +106,17 @@ pub enum Error {
107106
/// the SPI master fails to receive its own clock on the CLK pin
108107
DuplexFailed,
109108
}
109+
impl hal::spi::Error for Error {
110+
fn kind(&self) -> hal::spi::ErrorKind {
111+
use hal::spi::ErrorKind;
112+
113+
match self {
114+
Error::Overrun => ErrorKind::Overrun,
115+
Error::ModeFault => ErrorKind::ModeFault,
116+
_ => ErrorKind::Other,
117+
}
118+
}
119+
}
110120

111121
/// Enabled SPI peripheral (type state)
112122
pub struct Enabled;
@@ -557,8 +567,7 @@ pub trait SpiExt<SPI, WORD>: Sized {
557567
CONFIG: Into<Config>;
558568
}
559569

560-
pub trait HalEnabledSpi:
561-
HalSpi + FullDuplex<Self::Word, Error = Error>
570+
pub trait HalEnabledSpi: HalSpi // + FullDuplex<Self::Word, Error = Error>
562571
{
563572
type Disabled: HalDisabledSpi<
564573
Spi = Self::Spi,
@@ -1059,10 +1068,12 @@ macro_rules! spi {
10591068
}
10601069
}
10611070

1062-
impl hal::spi::FullDuplex<$TY> for Spi<$SPIX, Enabled, $TY> {
1063-
type Error = Error;
1064-
1065-
fn read(&mut self) -> nb::Result<$TY, Error> {
1071+
impl Spi<$SPIX, Enabled, $TY> {
1072+
/// Reads the word stored in the shift register.
1073+
///
1074+
/// NOTE: A word must be sent to the slave before attempting
1075+
/// to call this method
1076+
pub fn read(&mut self) -> nb::Result<$TY, Error> {
10661077
check_status_error!(self.spi;
10671078
{ // } else if sr.rxp().is_not_empty() {
10681079
rxp, is_not_empty,
@@ -1077,7 +1088,8 @@ macro_rules! spi {
10771088
})
10781089
}
10791090

1080-
fn send(&mut self, word: $TY) -> nb::Result<(), Error> {
1091+
/// Sends a word to the slave
1092+
pub fn send(&mut self, word: $TY) -> nb::Result<(), Error> {
10811093
check_status_error!(self.spi;
10821094
{ // } else if sr.txp().is_not_full() {
10831095
txp, is_not_full,
@@ -1172,10 +1184,16 @@ macro_rules! spi {
11721184
})
11731185
}
11741186

1175-
/// Internal implementation for blocking::spi::Write
1176-
fn transfer_internal_w(&mut self, write_words: &[$TY]) -> Result<(), Error> {
1177-
use hal::spi::FullDuplex;
1187+
/// Internal implementation for ensuring the current
1188+
/// transaction is completed
1189+
#[inline(always)]
1190+
fn flush(&mut self) -> Result<(), Error> {
1191+
while self.spi.sr.read().eot().is_completed() {}
1192+
Ok(())
1193+
}
11781194

1195+
/// Internal implementation for Write-only transfers
1196+
fn transfer_internal_w(&mut self, write_words: &[$TY]) -> Result<(), Error> {
11791197
// both buffers are the same length
11801198
if write_words.is_empty() {
11811199
return Ok(());
@@ -1230,10 +1248,67 @@ macro_rules! spi {
12301248
Ok(())
12311249
}
12321250

1233-
/// Internal implementation for blocking::spi::Transfer
1234-
fn transfer_internal_rw(&mut self, words : &mut [$TY]) -> Result<(), Error> {
1235-
use hal::spi::FullDuplex;
1251+
/// Internal implementation for Read Write transfers
1252+
fn transfer_internal_rw(&mut self, read: &mut [$TY], write: &[$TY])
1253+
-> Result<(), Error> {
1254+
if read.is_empty() | write.is_empty() {
1255+
return Ok(());
1256+
}
1257+
let len = core::cmp::max(read.len(), write.len());
1258+
1259+
// Are we in frame mode?
1260+
if matches!(self.hardware_cs_mode, HardwareCSMode::FrameTransaction) {
1261+
const MAX_WORDS: usize = 0xFFFF;
1262+
1263+
// Can we send
1264+
if len > MAX_WORDS {
1265+
return Err(Error::BufferTooBig { max_size: MAX_WORDS });
1266+
}
1267+
1268+
// Setup that we're going to send this amount of bits
1269+
// SAFETY: We already checked that `write_words` is not empty
1270+
self.setup_transaction(unsafe {
1271+
core::num::NonZeroU16::new_unchecked(len as u16)
1272+
})?;
1273+
}
1274+
1275+
// Depth of FIFO to use. All current SPI implementations
1276+
// have a FIFO depth of at least 8 (see RM0433 Rev 7
1277+
// Table 409.) but pick 4 as a conservative value.
1278+
const FIFO_WORDS: usize = 4;
1279+
1280+
// Fill the first half of the write FIFO
1281+
let mut write = write.into_iter();
1282+
for _ in 0..core::cmp::min(FIFO_WORDS, len) {
1283+
nb::block!(self.send(*write.next().unwrap_or(&0xFF)))?;
1284+
}
1285+
1286+
for i in FIFO_WORDS..len+FIFO_WORDS {
1287+
let read_value = if i < len {
1288+
// Continue filling write FIFO and emptying read FIFO
1289+
nb::block!(
1290+
self.exchange_duplex_internal(*write.next().unwrap_or(&0xFF))
1291+
)?
1292+
} else {
1293+
// Finish emptying the read FIFO
1294+
nb::block!(self.read_duplex_internal())?
1295+
};
1296+
if i - FIFO_WORDS < read.len() {
1297+
read[i - FIFO_WORDS] = read_value;
1298+
}
1299+
}
1300+
1301+
// Are we in frame mode?
1302+
if matches!(self.hardware_cs_mode, HardwareCSMode::FrameTransaction) {
1303+
// Clean up
1304+
self.end_transaction()?;
1305+
}
1306+
1307+
Ok(())
1308+
}
12361309

1310+
/// Internal implementation for in-place transfers
1311+
fn transfer_internal_in_place(&mut self, words : &mut [$TY]) -> Result<(), Error> {
12371312
if words.is_empty() {
12381313
return Ok(());
12391314
}
@@ -1289,22 +1364,25 @@ macro_rules! spi {
12891364
}
12901365
}
12911366

1292-
impl hal::blocking::spi::Transfer<$TY> for Spi<$SPIX, Enabled, $TY> {
1367+
impl hal::spi::ErrorType for Spi<$SPIX, Enabled, $TY> {
12931368
type Error = Error;
1294-
1295-
fn transfer<'w>(&mut self, words: &'w mut [$TY]) -> Result<&'w [$TY], Self::Error> {
1296-
1297-
self.transfer_internal_rw(words)?;
1298-
1299-
Ok(words)
1300-
}
13011369
}
1302-
impl hal::blocking::spi::Write<$TY> for Spi<$SPIX, Enabled, $TY> {
1303-
type Error = Error;
1304-
1370+
impl hal::spi::SpiBus<$TY> for Spi<$SPIX, Enabled, $TY> {
13051371
fn write(&mut self, words: &[$TY]) -> Result<(), Self::Error> {
13061372
self.transfer_internal_w(words)
13071373
}
1374+
fn read(&mut self, words: &mut [$TY]) -> Result<(), Self::Error> {
1375+
self.transfer_internal_rw(words, &[])
1376+
}
1377+
fn transfer(&mut self, read: &mut [$TY], write: &[$TY]) -> Result<(), Self::Error> {
1378+
self.transfer_internal_rw(read, write)
1379+
}
1380+
fn transfer_in_place(&mut self, words: &mut [$TY]) -> Result<(), Self::Error> {
1381+
self.transfer_internal_in_place(words)
1382+
}
1383+
fn flush(&mut self) -> Result<(), Self::Error> {
1384+
self.flush()
1385+
}
13081386
}
13091387
)+
13101388
)+

0 commit comments

Comments
 (0)