@@ -69,7 +69,6 @@ use core::ptr;
69
69
70
70
use crate :: gpio:: { self , Alternate } ;
71
71
use crate :: hal;
72
- use crate :: hal:: spi:: FullDuplex ;
73
72
pub use crate :: hal:: spi:: {
74
73
Mode , Phase , Polarity , MODE_0 , MODE_1 , MODE_2 , MODE_3 ,
75
74
} ;
@@ -107,6 +106,17 @@ pub enum Error {
107
106
/// the SPI master fails to receive its own clock on the CLK pin
108
107
DuplexFailed ,
109
108
}
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
+ }
110
120
111
121
/// Enabled SPI peripheral (type state)
112
122
pub struct Enabled ;
@@ -557,8 +567,7 @@ pub trait SpiExt<SPI, WORD>: Sized {
557
567
CONFIG : Into < Config > ;
558
568
}
559
569
560
- pub trait HalEnabledSpi :
561
- HalSpi + FullDuplex < Self :: Word , Error = Error >
570
+ pub trait HalEnabledSpi : HalSpi // + FullDuplex<Self::Word, Error = Error>
562
571
{
563
572
type Disabled : HalDisabledSpi <
564
573
Spi = Self :: Spi ,
@@ -1059,10 +1068,12 @@ macro_rules! spi {
1059
1068
}
1060
1069
}
1061
1070
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 > {
1066
1077
check_status_error!( self . spi;
1067
1078
{ // } else if sr.rxp().is_not_empty() {
1068
1079
rxp, is_not_empty,
@@ -1077,7 +1088,8 @@ macro_rules! spi {
1077
1088
} )
1078
1089
}
1079
1090
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 > {
1081
1093
check_status_error!( self . spi;
1082
1094
{ // } else if sr.txp().is_not_full() {
1083
1095
txp, is_not_full,
@@ -1172,10 +1184,16 @@ macro_rules! spi {
1172
1184
} )
1173
1185
}
1174
1186
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
+ }
1178
1194
1195
+ /// Internal implementation for Write-only transfers
1196
+ fn transfer_internal_w( & mut self , write_words: & [ $TY] ) -> Result <( ) , Error > {
1179
1197
// both buffers are the same length
1180
1198
if write_words. is_empty( ) {
1181
1199
return Ok ( ( ) ) ;
@@ -1230,10 +1248,67 @@ macro_rules! spi {
1230
1248
Ok ( ( ) )
1231
1249
}
1232
1250
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
+ }
1236
1309
1310
+ /// Internal implementation for in-place transfers
1311
+ fn transfer_internal_in_place( & mut self , words : & mut [ $TY] ) -> Result <( ) , Error > {
1237
1312
if words. is_empty( ) {
1238
1313
return Ok ( ( ) ) ;
1239
1314
}
@@ -1289,22 +1364,25 @@ macro_rules! spi {
1289
1364
}
1290
1365
}
1291
1366
1292
- impl hal:: blocking :: spi:: Transfer <$TY> for Spi <$SPIX, Enabled , $TY> {
1367
+ impl hal:: spi:: ErrorType for Spi <$SPIX, Enabled , $TY> {
1293
1368
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
- }
1301
1369
}
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> {
1305
1371
fn write( & mut self , words: & [ $TY] ) -> Result <( ) , Self :: Error > {
1306
1372
self . transfer_internal_w( words)
1307
1373
}
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
+ }
1308
1386
}
1309
1387
) +
1310
1388
) +
0 commit comments