@@ -140,6 +140,28 @@ pub enum Event {
140
140
// WakeupFromStopMode,
141
141
}
142
142
143
+ /// Check if an interrupt event happend.
144
+ #[ inline]
145
+ pub fn is_event_triggered ( uart : & impl Instance , event : Event ) -> bool {
146
+ let isr = uart. isr . read ( ) ;
147
+ match event {
148
+ Event :: TransmitDataRegisterEmtpy => isr. txe ( ) . bit ( ) ,
149
+ Event :: CtsInterrupt => isr. ctsif ( ) . bit ( ) ,
150
+ Event :: TransmissionComplete => isr. tc ( ) . bit ( ) ,
151
+ Event :: ReceiveDataRegisterNotEmpty => isr. rxne ( ) . bit ( ) ,
152
+ Event :: OverrunError => isr. ore ( ) . bit ( ) ,
153
+ Event :: Idle => isr. idle ( ) . bit ( ) ,
154
+ Event :: ParityError => isr. pe ( ) . bit ( ) ,
155
+ Event :: LinBreak => isr. lbdf ( ) . bit ( ) ,
156
+ Event :: NoiseError => isr. nf ( ) . bit ( ) ,
157
+ Event :: FramingError => isr. fe ( ) . bit ( ) ,
158
+ Event :: CharacterMatch => isr. cmf ( ) . bit ( ) ,
159
+ Event :: ReceiverTimeout => isr. rtof ( ) . bit ( ) ,
160
+ // Event::EndOfBlock => isr.eobf().bit(),
161
+ // Event::WakeupFromStopMode => isr.wuf().bit(),
162
+ }
163
+ }
164
+
143
165
/// Serial error
144
166
///
145
167
/// As these are status events, they can be converted to [`Event`]s, via [`Into`].
@@ -332,7 +354,7 @@ pub struct Serial<Usart, Pins> {
332
354
}
333
355
334
356
mod split {
335
- use super :: Instance ;
357
+ use super :: { is_event_triggered , Event , Instance } ;
336
358
/// Serial receiver
337
359
#[ derive( Debug ) ]
338
360
#[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
@@ -396,6 +418,14 @@ mod split {
396
418
pub ( crate ) unsafe fn usart_mut ( & mut self ) -> & mut Usart {
397
419
& mut self . usart
398
420
}
421
+
422
+ /// Check if an interrupt event happend.
423
+ #[ inline]
424
+ pub fn is_event_triggered ( & self , event : Event ) -> bool {
425
+ // Safety: We are only reading the ISR register here, which
426
+ // should not affect the RX half
427
+ is_event_triggered ( unsafe { self . usart ( ) } , event)
428
+ }
399
429
}
400
430
401
431
impl < Usart , Pin > Rx < Usart , Pin >
@@ -448,6 +478,14 @@ mod split {
448
478
pub ( crate ) unsafe fn usart_mut ( & mut self ) -> & mut Usart {
449
479
& mut self . usart
450
480
}
481
+
482
+ /// Check if an interrupt event happend.
483
+ #[ inline]
484
+ pub fn is_event_triggered ( & self , event : Event ) -> bool {
485
+ // Safety: We are only reading the ISR register here, which
486
+ // should not affect the TX half
487
+ is_event_triggered ( unsafe { self . usart ( ) } , event)
488
+ }
451
489
}
452
490
}
453
491
@@ -579,7 +617,7 @@ where
579
617
///
580
618
/// ## Embedded HAL
581
619
///
582
- /// To have a more managed way to read from the serial use the [`embeded_hal ::serial::Read`]
620
+ /// To have a more managed way to read from the serial use the [`embedded_hal ::serial::Read`]
583
621
/// trait implementation.
584
622
#[ doc( alias = "RDR" ) ]
585
623
pub fn read_data_register ( & self ) -> Option < u8 > {
@@ -714,23 +752,7 @@ where
714
752
/// Check if an interrupt event happend.
715
753
#[ inline]
716
754
pub fn is_event_triggered ( & self , event : Event ) -> bool {
717
- let isr = self . usart . isr . read ( ) ;
718
- match event {
719
- Event :: TransmitDataRegisterEmtpy => isr. txe ( ) . bit ( ) ,
720
- Event :: CtsInterrupt => isr. ctsif ( ) . bit ( ) ,
721
- Event :: TransmissionComplete => isr. tc ( ) . bit ( ) ,
722
- Event :: ReceiveDataRegisterNotEmpty => isr. rxne ( ) . bit ( ) ,
723
- Event :: OverrunError => isr. ore ( ) . bit ( ) ,
724
- Event :: Idle => isr. idle ( ) . bit ( ) ,
725
- Event :: ParityError => isr. pe ( ) . bit ( ) ,
726
- Event :: LinBreak => isr. lbdf ( ) . bit ( ) ,
727
- Event :: NoiseError => isr. nf ( ) . bit ( ) ,
728
- Event :: FramingError => isr. fe ( ) . bit ( ) ,
729
- Event :: CharacterMatch => isr. cmf ( ) . bit ( ) ,
730
- Event :: ReceiverTimeout => isr. rtof ( ) . bit ( ) ,
731
- // Event::EndOfBlock => isr.eobf().bit(),
732
- // Event::WakeupFromStopMode => isr.wuf().bit(),
733
- }
755
+ is_event_triggered ( & self . usart , event)
734
756
}
735
757
736
758
/// Get an [`EnumSet`] of all fired interrupt events.
@@ -947,7 +969,7 @@ where
947
969
/// up to the interrupt handler.
948
970
///
949
971
/// To read out the content of the read register without internal error handling, use
950
- /// [`Serial::read() `].
972
+ /// [`Serial::read_data_register `].
951
973
/// ...
952
974
// -> According to this API it should be skipped.
953
975
fn read ( & mut self ) -> nb:: Result < u8 , Error > {
@@ -1063,7 +1085,7 @@ where
1063
1085
Usart : Instance + Dma ,
1064
1086
{
1065
1087
/// Fill the buffer with received data using DMA.
1066
- pub fn read_exact < B , C > ( self , buffer : B , mut channel : C ) -> dma :: Transfer < B , C , Self >
1088
+ pub fn read_exact < B , C > ( self , buffer : B , mut channel : C ) -> SerialDmaRx < B , C , Self >
1067
1089
where
1068
1090
Self : dma:: OnChannel < C > ,
1069
1091
B : dma:: WriteBuffer < Word = u8 > + ' static ,
@@ -1077,7 +1099,9 @@ where
1077
1099
)
1078
1100
} ;
1079
1101
1080
- dma:: Transfer :: start_write ( buffer, channel, self )
1102
+ SerialDmaRx {
1103
+ transfer : dma:: Transfer :: start_write ( buffer, channel, self ) ,
1104
+ }
1081
1105
}
1082
1106
}
1083
1107
@@ -1088,13 +1112,148 @@ where
1088
1112
{
1089
1113
}
1090
1114
1115
+ /// Thin wrapper struct over the DMA transfer struct.
1116
+ ///
1117
+ /// This wrapper mostly exposes the [`dma::Transfer`] API but also also exposes
1118
+ /// an API to check for other USART ISR events during on-going transfers.
1119
+ pub struct SerialDmaRx < B : dma:: WriteBuffer < Word = u8 > + ' static , C : dma:: Channel , T : dma:: Target > {
1120
+ transfer : dma:: Transfer < B , C , T > ,
1121
+ }
1122
+
1123
+ impl < B , C , T > SerialDmaRx < B , C , T >
1124
+ where
1125
+ B : dma:: WriteBuffer < Word = u8 > ,
1126
+ C : dma:: Channel ,
1127
+ T : dma:: Target ,
1128
+ {
1129
+ /// Call [`dma::Transfer::stop`].
1130
+ pub fn stop ( self ) -> ( B , C , T ) {
1131
+ self . transfer . stop ( )
1132
+ }
1133
+
1134
+ /// Call [`dma::Transfer::is_complete`].
1135
+ pub fn is_complete ( & self ) -> bool {
1136
+ self . transfer . is_complete ( )
1137
+ }
1138
+
1139
+ /// Call [`dma::Transfer::wait`].
1140
+ pub fn wait ( self ) -> ( B , C , T ) {
1141
+ self . transfer . wait ( )
1142
+ }
1143
+ }
1144
+
1145
+ impl < B , C , Usart , Pin > SerialDmaRx < B , C , Rx < Usart , Pin > >
1146
+ where
1147
+ B : dma:: WriteBuffer < Word = u8 > ,
1148
+ C : dma:: Channel ,
1149
+ Usart : Instance + Dma ,
1150
+ Pin : RxPin < Usart > ,
1151
+ {
1152
+ /// Check if an interrupt event happened.
1153
+ pub fn is_event_triggered ( & self , event : Event ) -> bool {
1154
+ self . transfer . target ( ) . is_event_triggered ( event)
1155
+ }
1156
+ }
1157
+
1158
+ impl < B , C , Usart , Pins > SerialDmaRx < B , C , Serial < Usart , Pins > >
1159
+ where
1160
+ B : dma:: WriteBuffer < Word = u8 > ,
1161
+ C : dma:: Channel ,
1162
+ Usart : Instance + Dma ,
1163
+ {
1164
+ /// Check if an interrupt event happened.
1165
+ pub fn is_event_triggered ( & self , event : Event ) -> bool {
1166
+ self . transfer . target ( ) . is_event_triggered ( event)
1167
+ }
1168
+ }
1169
+
1170
+ /// Thin wrapper struct over the DMA transfer struct.
1171
+ ///
1172
+ /// This wrapper mostly exposes the [`dma::Transfer`] API but also implements
1173
+ /// some additional checks because the conditions for DMA transfer completion
1174
+ /// require that the USART TC ISR flag is set as well. It also exposes an API
1175
+ /// to check for other USART ISR events during ongoing transfers.
1176
+ pub struct SerialDmaTx < B : dma:: ReadBuffer < Word = u8 > + ' static , C : dma:: Channel , T : dma:: Target > {
1177
+ transfer : dma:: Transfer < B , C , T > ,
1178
+ }
1179
+
1180
+ impl < B , C , T > SerialDmaTx < B , C , T >
1181
+ where
1182
+ B : dma:: ReadBuffer < Word = u8 > ,
1183
+ C : dma:: Channel ,
1184
+ T : dma:: Target ,
1185
+ {
1186
+ /// Calls [`dma::Transfer::stop`].
1187
+ pub fn stop ( self ) -> ( B , C , T ) {
1188
+ self . transfer . stop ( )
1189
+ }
1190
+ }
1191
+
1192
+ impl < B , C , Usart , Pin > SerialDmaTx < B , C , Tx < Usart , Pin > >
1193
+ where
1194
+ Usart : Instance + Dma ,
1195
+ C : dma:: Channel ,
1196
+ B : dma:: ReadBuffer < Word = u8 > ,
1197
+ Pin : TxPin < Usart > ,
1198
+ {
1199
+ /// Wrapper function which can be used to check transfer completion.
1200
+ ///
1201
+ /// In addition to checking the transfer completion of the DMA, it also checks that the
1202
+ /// USART Transmission Complete flag was set by the hardware. According to RM0316 29.5.15, this
1203
+ /// is required to avoid corrupting the last transmission before disabling the USART or entering
1204
+ /// stop mode.
1205
+ pub fn is_complete ( & self ) -> bool {
1206
+ let target = self . transfer . target ( ) ;
1207
+ self . transfer . is_complete ( ) && target. is_event_triggered ( Event :: TransmissionComplete )
1208
+ }
1209
+
1210
+ /// Block until the transfer is complete. This function also uses
1211
+ /// [`SerialDmaTx::is_complete`] to check that the USART TC flag was set by
1212
+ /// the hardware.
1213
+ pub fn wait ( self ) -> ( B , C , Tx < Usart , Pin > ) {
1214
+ while !self . is_complete ( ) { }
1215
+ self . stop ( )
1216
+ }
1217
+
1218
+ /// Check if an interrupt event happened.
1219
+ pub fn is_event_triggered ( & self , event : Event ) -> bool {
1220
+ self . transfer . target ( ) . is_event_triggered ( event)
1221
+ }
1222
+ }
1223
+
1224
+ impl < B , C , Usart , Pins > SerialDmaTx < B , C , Serial < Usart , Pins > >
1225
+ where
1226
+ Usart : Instance + Dma ,
1227
+ C : dma:: Channel ,
1228
+ B : dma:: ReadBuffer < Word = u8 > ,
1229
+ {
1230
+ /// Wrapper function which can be used to check transfer completion.
1231
+ ///
1232
+ /// In addition to checking the transfer completion of the DMA, it also checks that the
1233
+ /// USART Transmission Complete flag was set by the hardware. According to RM0316 29.5.15, this
1234
+ /// is required to avoid corrupting the last transmission before disabling the USART or entering
1235
+ /// stop mode.
1236
+ pub fn is_complete ( & self ) -> bool {
1237
+ let target = self . transfer . target ( ) ;
1238
+ self . transfer . is_complete ( ) && target. is_event_triggered ( Event :: TransmissionComplete )
1239
+ }
1240
+
1241
+ /// Block until the transfer is complete. This function also uses
1242
+ /// [`SerialDmaTx::is_complete`] to check that the USART TC flag was set by
1243
+ /// the hardware.
1244
+ pub fn wait ( self ) -> ( B , C , Serial < Usart , Pins > ) {
1245
+ while !self . is_complete ( ) { }
1246
+ self . stop ( )
1247
+ }
1248
+ }
1249
+
1091
1250
impl < Usart , Pin > Tx < Usart , Pin >
1092
1251
where
1093
1252
Usart : Instance + Dma ,
1094
1253
Pin : TxPin < Usart > ,
1095
1254
{
1096
1255
/// Transmit all data in the buffer using DMA.
1097
- pub fn write_all < B , C > ( self , buffer : B , mut channel : C ) -> dma :: Transfer < B , C , Self >
1256
+ pub fn write_all < B , C > ( self , buffer : B , mut channel : C ) -> SerialDmaTx < B , C , Self >
1098
1257
where
1099
1258
Self : dma:: OnChannel < C > ,
1100
1259
B : dma:: ReadBuffer < Word = u8 > + ' static ,
@@ -1108,7 +1267,9 @@ where
1108
1267
)
1109
1268
} ;
1110
1269
1111
- dma:: Transfer :: start_read ( buffer, channel, self )
1270
+ SerialDmaTx {
1271
+ transfer : dma:: Transfer :: start_read ( buffer, channel, self ) ,
1272
+ }
1112
1273
}
1113
1274
}
1114
1275
@@ -1156,7 +1317,7 @@ where
1156
1317
Usart : Instance + Dma ,
1157
1318
{
1158
1319
/// Fill the buffer with received data using DMA.
1159
- pub fn read_exact < B , C > ( self , buffer : B , mut channel : C ) -> dma :: Transfer < B , C , Self >
1320
+ pub fn read_exact < B , C > ( self , buffer : B , mut channel : C ) -> SerialDmaRx < B , C , Self >
1160
1321
where
1161
1322
Self : dma:: OnChannel < C > ,
1162
1323
B : dma:: WriteBuffer < Word = u8 > + ' static ,
@@ -1168,11 +1329,13 @@ where
1168
1329
. set_peripheral_address ( & self . usart . rdr as * const _ as u32 , dma:: Increment :: Disable )
1169
1330
} ;
1170
1331
1171
- dma:: Transfer :: start_write ( buffer, channel, self )
1332
+ SerialDmaRx {
1333
+ transfer : dma:: Transfer :: start_write ( buffer, channel, self ) ,
1334
+ }
1172
1335
}
1173
1336
1174
1337
/// Transmit all data in the buffer using DMA.
1175
- pub fn write_all < B , C > ( self , buffer : B , mut channel : C ) -> dma :: Transfer < B , C , Self >
1338
+ pub fn write_all < B , C > ( self , buffer : B , mut channel : C ) -> SerialDmaTx < B , C , Self >
1176
1339
where
1177
1340
Self : dma:: OnChannel < C > ,
1178
1341
B : dma:: ReadBuffer < Word = u8 > + ' static ,
@@ -1184,7 +1347,9 @@ where
1184
1347
. set_peripheral_address ( & self . usart . tdr as * const _ as u32 , dma:: Increment :: Disable )
1185
1348
} ;
1186
1349
1187
- dma:: Transfer :: start_read ( buffer, channel, self )
1350
+ SerialDmaTx {
1351
+ transfer : dma:: Transfer :: start_read ( buffer, channel, self ) ,
1352
+ }
1188
1353
}
1189
1354
}
1190
1355
0 commit comments