@@ -998,6 +998,10 @@ where
998
998
}
999
999
1000
1000
/// An in-progress transaction for a single shot TX transaction.
1001
+ ///
1002
+ /// If the data size exceeds the size of the internal buffer, `.poll()` or
1003
+ /// `.wait()` needs to be called before the entire buffer has been sent to avoid
1004
+ /// underruns.
1001
1005
pub struct SingleShotTxTransaction < ' a , Raw >
1002
1006
where
1003
1007
Raw : TxChannelInternal ,
@@ -1017,15 +1021,61 @@ impl<Raw> SingleShotTxTransaction<'_, Raw>
1017
1021
where
1018
1022
Raw : TxChannelInternal ,
1019
1023
{
1020
- /// Wait for the transaction to complete
1021
- pub fn wait ( mut self ) -> Result < Channel < Blocking , Raw > , ( Error , Channel < Blocking , Raw > ) > {
1024
+ fn poll_internal ( & mut self ) -> Option < Event > {
1022
1025
let raw = self . channel . raw ;
1023
- let memsize = raw. memsize ( ) . codes ( ) ;
1024
1026
1027
+ let status = raw. get_tx_status ( ) ;
1028
+ if status == Some ( Event :: Threshold ) {
1029
+ raw. reset_tx_threshold_set ( ) ;
1030
+
1031
+ if !self . remaining_data . is_empty ( ) {
1032
+ // re-fill TX RAM
1033
+ let memsize = raw. memsize ( ) . codes ( ) ;
1034
+ let ptr = unsafe { raw. channel_ram_start ( ) . add ( self . ram_index ) } ;
1035
+ let count = self . remaining_data . len ( ) . min ( memsize / 2 ) ;
1036
+ let ( chunk, remaining) = self . remaining_data . split_at ( count) ;
1037
+ for ( idx, entry) in chunk. iter ( ) . enumerate ( ) {
1038
+ unsafe {
1039
+ ptr. add ( idx) . write_volatile ( * entry) ;
1040
+ }
1041
+ }
1042
+
1043
+ // If count == memsize / 2 codes were written, update ram_index as
1044
+ // - 0 -> memsize / 2
1045
+ // - memsize / 2 -> 0
1046
+ // Otherwise, for count < memsize / 2, the new position is invalid but the new
1047
+ // slice is empty and we won't use ram_index again.
1048
+ self . ram_index = memsize / 2 - self . ram_index ;
1049
+ self . remaining_data = remaining;
1050
+ debug_assert ! (
1051
+ self . ram_index == 0
1052
+ || self . ram_index == memsize / 2
1053
+ || self . remaining_data. is_empty( )
1054
+ ) ;
1055
+ }
1056
+ }
1057
+
1058
+ status
1059
+ }
1060
+
1061
+ /// Check transmission status and write new data to the hardware if
1062
+ /// necessary.
1063
+ ///
1064
+ /// Returns whether transmission has ended (whether successfully or with an
1065
+ /// error). In that case, a subsequent call to `wait()` returns immediately.
1066
+ pub fn poll ( & mut self ) -> bool {
1067
+ match self . poll_internal ( ) {
1068
+ Some ( Event :: Error | Event :: End ) => true ,
1069
+ Some ( Event :: Threshold ) | None => false ,
1070
+ }
1071
+ }
1072
+
1073
+ /// Wait for the transaction to complete
1074
+ pub fn wait ( mut self ) -> Result < Channel < Blocking , Raw > , ( Error , Channel < Blocking , Raw > ) > {
1075
+ // Not sure that all the error cases below can happen. However, it's best to
1076
+ // handle them to be sure that we don't lock up here in case they can happen.
1025
1077
loop {
1026
- // Not sure that all the error cases below can happen. However, it's best to
1027
- // handle them to be sure that we don't lock up here in case they can happen.
1028
- match raw. get_tx_status ( ) {
1078
+ match self . poll_internal ( ) {
1029
1079
Some ( Event :: Error ) => break Err ( ( Error :: TransmissionError , self . channel ) ) ,
1030
1080
Some ( Event :: End ) => {
1031
1081
if !self . remaining_data . is_empty ( ) {
@@ -1036,34 +1086,6 @@ where
1036
1086
break Ok ( self . channel ) ;
1037
1087
}
1038
1088
}
1039
- Some ( Event :: Threshold ) => {
1040
- raw. reset_tx_threshold_set ( ) ;
1041
-
1042
- if !self . remaining_data . is_empty ( ) {
1043
- // re-fill TX RAM
1044
- let ptr = unsafe { raw. channel_ram_start ( ) . add ( self . ram_index ) } ;
1045
- let count = self . remaining_data . len ( ) . min ( memsize / 2 ) ;
1046
- let ( chunk, remaining) = self . remaining_data . split_at ( count) ;
1047
- for ( idx, entry) in chunk. iter ( ) . enumerate ( ) {
1048
- unsafe {
1049
- ptr. add ( idx) . write_volatile ( * entry) ;
1050
- }
1051
- }
1052
-
1053
- // If count == memsize / 2 codes were written, update ram_index as
1054
- // - 0 -> memsize / 2
1055
- // - memsize / 2 -> 0
1056
- // Otherwise, for count < memsize / 2, the new position is invalid but the new
1057
- // slice is empty and we won't use ram_index again.
1058
- self . ram_index = memsize / 2 - self . ram_index ;
1059
- self . remaining_data = remaining;
1060
- debug_assert ! (
1061
- self . ram_index == 0
1062
- || self . ram_index == memsize / 2
1063
- || self . remaining_data. is_empty( )
1064
- ) ;
1065
- }
1066
- }
1067
1089
_ => continue ,
1068
1090
}
1069
1091
}
@@ -1298,32 +1320,53 @@ pub struct RxTransaction<'a, Raw: RxChannelInternal> {
1298
1320
}
1299
1321
1300
1322
impl < Raw : RxChannelInternal > RxTransaction < ' _ , Raw > {
1301
- /// Wait for the transaction to complete
1302
- pub fn wait ( self ) -> Result < Channel < Blocking , Raw > , ( Error , Channel < Blocking , Raw > ) > {
1323
+ fn poll_internal ( & mut self ) -> Option < Event > {
1303
1324
let raw = self . channel . raw ;
1304
1325
1305
- loop {
1306
- if raw. is_error ( ) {
1307
- return Err ( ( Error :: ReceiverError , self . channel ) ) ;
1308
- }
1326
+ let status = raw. get_rx_status ( ) ;
1327
+ if status == Some ( Event :: End ) {
1328
+ // Do not clear the interrupt flags here: Subsequent calls of wait() must
1329
+ // be able to observe them if this is currently called via poll()
1330
+ raw. stop_rx ( ) ;
1331
+ raw. update ( ) ;
1309
1332
1310
- if raw. is_rx_done ( ) {
1311
- break ;
1333
+ let ptr = raw. channel_ram_start ( ) ;
1334
+ // SAFETY: RxChannel.receive() verifies that the length of self.data does not
1335
+ // exceed the channel RAM size.
1336
+ for ( idx, entry) in self . data . iter_mut ( ) . enumerate ( ) {
1337
+ * entry = unsafe { ptr. add ( idx) . read_volatile ( ) } ;
1312
1338
}
1313
1339
}
1314
1340
1315
- raw. stop_rx ( ) ;
1316
- raw. clear_rx_interrupts ( ) ;
1317
- raw. update ( ) ;
1341
+ status
1342
+ }
1318
1343
1319
- let ptr = raw. channel_ram_start ( ) ;
1320
- // SAFETY: RxChannel.receive() verifies that the length of self.data does not
1321
- // exceed the channel RAM size.
1322
- for ( idx, entry) in self . data . iter_mut ( ) . enumerate ( ) {
1323
- * entry = unsafe { ptr. add ( idx) . read_volatile ( ) } ;
1344
+ /// Check receive status
1345
+ ///
1346
+ /// Returns whether reception has ended (whether successfully or with an
1347
+ /// error). In that case, a subsequent call to `wait()` returns immediately.
1348
+ pub fn poll ( & mut self ) -> bool {
1349
+ match self . poll_internal ( ) {
1350
+ Some ( Event :: Error | Event :: End ) => true ,
1351
+ Some ( Event :: Threshold ) | None => false ,
1324
1352
}
1353
+ }
1325
1354
1326
- Ok ( self . channel )
1355
+ /// Wait for the transaction to complete
1356
+ pub fn wait ( mut self ) -> Result < Channel < Blocking , Raw > , ( Error , Channel < Blocking , Raw > ) > {
1357
+ let raw = self . channel . raw ;
1358
+
1359
+ let result = loop {
1360
+ match self . poll_internal ( ) {
1361
+ Some ( Event :: Error ) => break Err ( ( Error :: ReceiverError , self . channel ) ) ,
1362
+ Some ( Event :: End ) => break Ok ( self . channel ) ,
1363
+ _ => continue ,
1364
+ }
1365
+ } ;
1366
+
1367
+ raw. clear_rx_interrupts ( ) ;
1368
+
1369
+ result
1327
1370
}
1328
1371
}
1329
1372
0 commit comments