@@ -140,6 +140,28 @@ pub enum Event {
140140 // WakeupFromStopMode,
141141}
142142
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+
143165/// Serial error
144166///
145167/// As these are status events, they can be converted to [`Event`]s, via [`Into`].
@@ -332,7 +354,7 @@ pub struct Serial<Usart, Pins> {
332354}
333355
334356mod split {
335- use super :: Instance ;
357+ use super :: { is_event_triggered , Event , Instance } ;
336358 /// Serial receiver
337359 #[ derive( Debug ) ]
338360 #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
@@ -396,6 +418,14 @@ mod split {
396418 pub ( crate ) unsafe fn usart_mut ( & mut self ) -> & mut Usart {
397419 & mut self . usart
398420 }
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+ }
399429 }
400430
401431 impl < Usart , Pin > Rx < Usart , Pin >
@@ -448,6 +478,14 @@ mod split {
448478 pub ( crate ) unsafe fn usart_mut ( & mut self ) -> & mut Usart {
449479 & mut self . usart
450480 }
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+ }
451489 }
452490}
453491
@@ -579,7 +617,7 @@ where
579617 ///
580618 /// ## Embedded HAL
581619 ///
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`]
583621 /// trait implementation.
584622 #[ doc( alias = "RDR" ) ]
585623 pub fn read_data_register ( & self ) -> Option < u8 > {
@@ -714,23 +752,7 @@ where
714752 /// Check if an interrupt event happend.
715753 #[ inline]
716754 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)
734756 }
735757
736758 /// Get an [`EnumSet`] of all fired interrupt events.
@@ -947,7 +969,7 @@ where
947969 /// up to the interrupt handler.
948970 ///
949971 /// To read out the content of the read register without internal error handling, use
950- /// [`Serial::read() `].
972+ /// [`Serial::read_data_register `].
951973 /// ...
952974 // -> According to this API it should be skipped.
953975 fn read ( & mut self ) -> nb:: Result < u8 , Error > {
@@ -1063,7 +1085,7 @@ where
10631085 Usart : Instance + Dma ,
10641086{
10651087 /// 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 >
10671089 where
10681090 Self : dma:: OnChannel < C > ,
10691091 B : dma:: WriteBuffer < Word = u8 > + ' static ,
@@ -1077,7 +1099,9 @@ where
10771099 )
10781100 } ;
10791101
1080- dma:: Transfer :: start_write ( buffer, channel, self )
1102+ SerialDmaRx {
1103+ transfer : dma:: Transfer :: start_write ( buffer, channel, self ) ,
1104+ }
10811105 }
10821106}
10831107
@@ -1088,13 +1112,148 @@ where
10881112{
10891113}
10901114
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+
10911250impl < Usart , Pin > Tx < Usart , Pin >
10921251where
10931252 Usart : Instance + Dma ,
10941253 Pin : TxPin < Usart > ,
10951254{
10961255 /// 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 >
10981257 where
10991258 Self : dma:: OnChannel < C > ,
11001259 B : dma:: ReadBuffer < Word = u8 > + ' static ,
@@ -1108,7 +1267,9 @@ where
11081267 )
11091268 } ;
11101269
1111- dma:: Transfer :: start_read ( buffer, channel, self )
1270+ SerialDmaTx {
1271+ transfer : dma:: Transfer :: start_read ( buffer, channel, self ) ,
1272+ }
11121273 }
11131274}
11141275
@@ -1156,7 +1317,7 @@ where
11561317 Usart : Instance + Dma ,
11571318{
11581319 /// 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 >
11601321 where
11611322 Self : dma:: OnChannel < C > ,
11621323 B : dma:: WriteBuffer < Word = u8 > + ' static ,
@@ -1168,11 +1329,13 @@ where
11681329 . set_peripheral_address ( & self . usart . rdr as * const _ as u32 , dma:: Increment :: Disable )
11691330 } ;
11701331
1171- dma:: Transfer :: start_write ( buffer, channel, self )
1332+ SerialDmaRx {
1333+ transfer : dma:: Transfer :: start_write ( buffer, channel, self ) ,
1334+ }
11721335 }
11731336
11741337 /// 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 >
11761339 where
11771340 Self : dma:: OnChannel < C > ,
11781341 B : dma:: ReadBuffer < Word = u8 > + ' static ,
@@ -1184,7 +1347,9 @@ where
11841347 . set_peripheral_address ( & self . usart . tdr as * const _ as u32 , dma:: Increment :: Disable )
11851348 } ;
11861349
1187- dma:: Transfer :: start_read ( buffer, channel, self )
1350+ SerialDmaTx {
1351+ transfer : dma:: Transfer :: start_read ( buffer, channel, self ) ,
1352+ }
11881353 }
11891354}
11901355
0 commit comments