@@ -187,21 +187,41 @@ impl Serial {
187187 /// # Errors
188188 ///
189189 /// - [`Status::DEVICE_ERROR`]: serial device reported an error
190- pub fn read_exact ( & mut self , buffer : & mut [ u8 ] ) -> Result < ( ) > {
190+ pub fn read_exact ( & mut self , buffer : & mut [ u8 ] ) -> Result < ( ) , usize /* read bytes */ > {
191+ let stall_duration = if self . io_mode ( ) . baud_rate == 0 {
192+ Duration :: from_millis ( 1 ) } else {
193+ let ms = 1_000_000 / self . io_mode ( ) . baud_rate ;
194+ Duration :: from_millis ( ms)
195+ } ;
196+ // Endless loop protection.
197+ let max_timeout_count = buffer. len ( ) * 5 ;
198+
199+ let mut timeout_count = 0 ;
191200 let mut remaining_buffer = buffer;
201+
202+ let move_buffer_by_n = |n| {
203+ remaining_buffer = & mut remaining_buffer[ n..] ;
204+ } ;
205+
206+
192207 // We retry on timeout and only return other errors
193208 while !remaining_buffer. is_empty ( ) {
194209 match self . read ( remaining_buffer) {
195210 Ok ( _) => {
196211 break ;
197212 }
198- Err ( err) if err. status ( ) == Status :: TIMEOUT => {
199- let n = * err. data ( ) ;
200- remaining_buffer = & mut remaining_buffer[ n..] ;
201- boot:: stall ( Duration :: from_millis ( 1 ) ) ;
213+ Err ( err) if err. status ( ) == Status :: TIMEOUT && timeout_count < max_timeout_count => {
214+ timeout_count += 1 ;
215+ move_buffer_by_n ( * err. data ( ) /* n */ ) ;
216+ boot:: stall ( stall_duration) ;
217+ } ,
218+ Err ( err) if err. status ( ) == Status :: TIMEOUT && timeout_count >= max_timeout_count => {
219+ move_buffer_by_n ( * err. data ( ) /* n */ ) ;
220+ let n_total = buffer. len ( ) - remaining_buffer. len ( ) ;
221+ return Err ( Error :: new ( Status :: TIMEOUT , n_total) ) ;
202222 }
203223 err => {
204- return Err ( Error :: from ( err. status ( ) ) ) ;
224+ return err
205225 }
206226 }
207227 }
0 commit comments