@@ -1087,74 +1087,76 @@ macro_rules! spi {
1087
1087
}
1088
1088
}
1089
1089
1090
- impl hal:: blocking:: spi:: Transfer <$TY> for Spi <$SPIX, Enabled , $TY> {
1091
- type Error = Error ;
1092
-
1093
- fn transfer<' w>( & mut self , words: & ' w mut [ $TY] ) -> Result <& ' w [ $TY] , Self :: Error > {
1094
- use embedded_hal:: spi:: FullDuplex ;
1095
-
1096
- if words. is_empty( ) {
1097
- return Ok ( words) ;
1090
+ impl Spi <$SPIX, Enabled , $TY>
1091
+ {
1092
+ /// Internal implementation for blocking::spi::Transfer and
1093
+ /// blocking::spi::Write
1094
+ fn transfer_internal<' w>( & mut self ,
1095
+ write_words: & ' w [ $TY] ,
1096
+ read_words: Option <& ' w mut [ $TY] >
1097
+ ) -> Result <( ) , Error > {
1098
+ use hal:: spi:: FullDuplex ;
1099
+
1100
+ // both buffers are the same length
1101
+ if let Some ( ref read) = read_words {
1102
+ debug_assert!( write_words. len( ) == read. len( ) ) ;
1103
+ }
1104
+ if write_words. is_empty( ) {
1105
+ return Ok ( ( ) ) ;
1098
1106
}
1099
1107
1100
1108
// Are we in frame mode?
1101
1109
if matches!( self . hardware_cs_mode, HardwareCSMode :: FrameTransaction ) {
1102
1110
const MAX_WORDS : usize = 0xFFFF ;
1103
1111
1104
1112
// Can we send
1105
- if words . len( ) > MAX_WORDS {
1113
+ if write_words . len( ) > MAX_WORDS {
1106
1114
return Err ( Error :: BufferTooBig { max_size: MAX_WORDS } ) ;
1107
1115
}
1108
1116
1109
1117
// Setup that we're going to send this amount of bits
1110
- // SAFETY: We already checked that `words` is not empty
1111
- self . setup_transaction( unsafe { core:: num:: NonZeroU16 :: new_unchecked( words. len( ) as u16 ) } ) ?;
1118
+ // SAFETY: We already checked that `write_words` is not empty
1119
+ self . setup_transaction( unsafe {
1120
+ core:: num:: NonZeroU16 :: new_unchecked( write_words. len( ) as u16 )
1121
+ } ) ?;
1112
1122
}
1113
1123
1114
- // Send the data
1115
- for word in words. iter_mut( ) {
1116
- nb:: block!( self . send( word. clone( ) ) ) ?;
1117
- * word = nb:: block!( self . read( ) ) ?;
1118
- }
1124
+ // Depth of FIFO to use. All current SPI implementations
1125
+ // have a FIFO depth of at least 8 (see RM0433 Rev 7
1126
+ // Tabel 409.) but pick 4 as a conservative value.
1127
+ const FIFO_WORDS : usize = 4 ;
1119
1128
1120
- // Are we in frame mode?
1121
- if matches!( self . hardware_cs_mode, HardwareCSMode :: FrameTransaction ) {
1122
- // Clean up
1123
- self . end_transaction( ) ?;
1129
+ // Fill the first half of the write FIFO
1130
+ let len = write_words. len( ) ;
1131
+ let mut write = write_words. iter( ) ;
1132
+ for _ in 0 ..core:: cmp:: min( FIFO_WORDS , len) {
1133
+ nb:: block!( self . send( * write. next( ) . unwrap( ) ) ) ?;
1124
1134
}
1125
1135
1126
- Ok ( words)
1127
- }
1128
- }
1136
+ if let Some ( read) = read_words {
1137
+ let mut read = read. iter_mut( ) ;
1129
1138
1130
- impl hal:: blocking:: spi:: Write <$TY> for Spi <$SPIX, Enabled , $TY> {
1131
- type Error = Error ;
1132
-
1133
- fn write( & mut self , words: & [ $TY] ) -> Result <( ) , Self :: Error > {
1134
- use embedded_hal:: spi:: FullDuplex ;
1135
-
1136
- if words. is_empty( ) {
1137
- return Ok ( ( ) ) ;
1138
- }
1139
-
1140
- // Are we in frame mode?
1141
- if matches!( self . hardware_cs_mode, HardwareCSMode :: FrameTransaction ) {
1142
- const MAX_WORDS : usize = 0xFFFF ;
1143
-
1144
- // Can we send
1145
- if words. len( ) > MAX_WORDS {
1146
- return Err ( Error :: BufferTooBig { max_size: MAX_WORDS } ) ;
1139
+ // Continue filling write FIFO and emptying read FIFO
1140
+ for word in write {
1141
+ nb:: block!( self . send( * word) ) ?;
1142
+ * read. next( ) . unwrap( ) = nb:: block!( self . read( ) ) ?;
1147
1143
}
1148
1144
1149
- // Setup that we're going to send this amount of bits
1150
- // SAFETY: We already checked that `words` is not empty
1151
- self . setup_transaction( unsafe { core:: num:: NonZeroU16 :: new_unchecked( words. len( ) as u16 ) } ) ?;
1152
- }
1145
+ // Finish emptying the read FIFO
1146
+ for word in read {
1147
+ * word = nb:: block!( self . read( ) ) ?;
1148
+ }
1149
+ } else {
1150
+ // Continue filling write FIFO and emptying read FIFO
1151
+ for word in write {
1152
+ nb:: block!( self . send( * word) ) ?;
1153
+ let _ = nb:: block!( self . read( ) ) ?;
1154
+ }
1153
1155
1154
- // Send the data
1155
- for word in words {
1156
- nb:: block!( self . send ( word . clone ( ) ) ) ?;
1157
- nb :: block! ( self . read ( ) ) ? ;
1156
+ // Dummy read from the read FIFO
1157
+ for _ in 0 ..core :: cmp :: min ( FIFO_WORDS , len ) {
1158
+ let _ = nb:: block!( self . read ( ) ) ?;
1159
+ }
1158
1160
}
1159
1161
1160
1162
// Are we in frame mode?
@@ -1166,6 +1168,27 @@ macro_rules! spi {
1166
1168
Ok ( ( ) )
1167
1169
}
1168
1170
}
1171
+ impl hal:: blocking:: spi:: Transfer <$TY> for Spi <$SPIX, Enabled , $TY> {
1172
+ type Error = Error ;
1173
+
1174
+ fn transfer<' w>( & mut self , words: & ' w mut [ $TY] ) -> Result <& ' w [ $TY] , Self :: Error > {
1175
+ // SAFETY: transfer_internal always writes out bytes
1176
+ // before modifying them
1177
+ let write = unsafe {
1178
+ core:: slice:: from_raw_parts( words. as_ptr( ) , words. len( ) )
1179
+ } ;
1180
+ self . transfer_internal( write, Some ( words) ) ?;
1181
+
1182
+ Ok ( words)
1183
+ }
1184
+ }
1185
+ impl hal:: blocking:: spi:: Write <$TY> for Spi <$SPIX, Enabled , $TY> {
1186
+ type Error = Error ;
1187
+
1188
+ fn write( & mut self , words: & [ $TY] ) -> Result <( ) , Self :: Error > {
1189
+ self . transfer_internal( words, None )
1190
+ }
1191
+ }
1169
1192
) +
1170
1193
) +
1171
1194
}
0 commit comments