44//! sending/decoding of commands, and provides higher-level operations with the
55//! device.
66
7- use std:: { io:: BufWriter , thread:: sleep, time:: Duration } ;
7+ use std:: { io:: BufWriter , iter :: zip , thread:: sleep, time:: Duration } ;
88
99use binrw:: { io:: Cursor , BinRead , BinReaderExt } ;
10- use log:: { debug, info } ;
10+ use log:: debug;
1111use serialport:: UsbPortInfo ;
1212use slip_codec:: SlipDecoder ;
1313
14- use self :: encoder:: SlipEncoder ;
14+ #[ cfg( unix) ]
15+ use self :: reset:: UnixTightReset ;
16+ use self :: {
17+ encoder:: SlipEncoder ,
18+ reset:: { construct_reset_strategy_sequence, ClassicReset , ResetStrategy , UsbJtagSerialReset } ,
19+ } ;
1520use crate :: {
1621 command:: { Command , CommandType } ,
1722 error:: { ConnectionError , Error , ResultExt , RomError , RomErrorKind } ,
1823 interface:: Interface ,
1924} ;
2025
21- const DEFAULT_CONNECT_ATTEMPTS : usize = 7 ;
26+ mod reset;
27+
28+ const MAX_CONNECT_ATTEMPTS : usize = 7 ;
29+ const MAX_SYNC_ATTEMPTS : usize = 5 ;
2230pub ( crate ) const USB_SERIAL_JTAG_PID : u16 = 0x1001 ;
2331
2432/// A response from a target device following a command
@@ -50,29 +58,30 @@ impl Connection {
5058
5159 /// Initialize a connection with a device
5260 pub fn begin ( & mut self ) -> Result < ( ) , Error > {
53- let mut extra_delay = false ;
54- for _ in 0 .. DEFAULT_CONNECT_ATTEMPTS {
55- if self . connect_attempt ( extra_delay ) . is_err ( ) {
56- extra_delay = !extra_delay ;
57-
58- info ! (
59- "Unable to connect, retrying with {} delay..." ,
60- if extra_delay { "extra" } else { "default" }
61- ) ;
62- } else {
63- return Ok ( ( ) ) ;
61+ let port_name = self . serial . serial_port ( ) . name ( ) . unwrap_or_default ( ) ;
62+ let reset_sequence = construct_reset_strategy_sequence ( & port_name , self . port_info . pid ) ;
63+
64+ for ( _ , reset_strategy ) in zip ( 0 .. MAX_CONNECT_ATTEMPTS , reset_sequence . iter ( ) . cycle ( ) ) {
65+ match self . connect_attempt ( reset_strategy ) {
66+ Ok ( _ ) => {
67+ return Ok ( ( ) ) ;
68+ }
69+ Err ( e ) => {
70+ debug ! ( "Failed to reset, error {:#?}, retrying" , e ) ;
71+ }
6472 }
6573 }
6674
6775 Err ( Error :: Connection ( ConnectionError :: ConnectionFailed ) )
6876 }
6977
7078 /// Try to connect to a device
71- fn connect_attempt ( & mut self , extra_delay : bool ) -> Result < ( ) , Error > {
72- self . reset_to_flash ( extra_delay ) ? ;
73-
74- for _ in 0 ..5 {
79+ # [ allow ( clippy :: borrowed_box ) ]
80+ fn connect_attempt ( & mut self , reset_strategy : & Box < dyn ResetStrategy > ) -> Result < ( ) , Error > {
81+ reset_strategy . reset ( & mut self . serial ) ? ;
82+ for _ in 0 ..MAX_SYNC_ATTEMPTS {
7583 self . flush ( ) ?;
84+
7685 if self . sync ( ) . is_ok ( ) {
7786 return Ok ( ( ) ) ;
7887 }
@@ -86,12 +95,14 @@ impl Connection {
8695 self . with_timeout ( CommandType :: Sync . timeout ( ) , |connection| {
8796 connection. command ( Command :: Sync ) ?;
8897 connection. flush ( ) ?;
98+
8999 sleep ( Duration :: from_millis ( 10 ) ) ;
90- for _ in 0 ..7 {
100+
101+ for _ in 0 ..MAX_CONNECT_ATTEMPTS {
91102 match connection. read_response ( ) ? {
92103 Some ( response) if response. return_op == CommandType :: Sync as u8 => {
93104 if response. status == 1 {
94- let _error = connection. flush ( ) ;
105+ connection. flush ( ) . ok ( ) ;
95106 return Err ( Error :: RomError ( RomError :: new (
96107 CommandType :: Sync ,
97108 RomErrorKind :: from ( response. error ) ,
@@ -115,47 +126,26 @@ impl Connection {
115126
116127 // Reset the device
117128 pub fn reset ( & mut self ) -> Result < ( ) , Error > {
118- let pid = self . port_info . pid ;
119- Ok ( reset_after_flash ( & mut self . serial , pid) ?)
129+ reset_after_flash ( & mut self . serial , self . port_info . pid ) ?;
130+
131+ Ok ( ( ) )
120132 }
121133
122134 // Reset the device to flash mode
123135 pub fn reset_to_flash ( & mut self , extra_delay : bool ) -> Result < ( ) , Error > {
124136 if self . port_info . pid == USB_SERIAL_JTAG_PID {
125- self . serial . write_data_terminal_ready ( false ) ?;
126- self . serial . write_request_to_send ( false ) ?;
127-
128- sleep ( Duration :: from_millis ( 100 ) ) ;
129-
130- self . serial . write_data_terminal_ready ( true ) ?;
131- self . serial . write_request_to_send ( false ) ?;
132-
133- sleep ( Duration :: from_millis ( 100 ) ) ;
134-
135- self . serial . write_request_to_send ( true ) ?;
136- self . serial . write_data_terminal_ready ( false ) ?;
137- self . serial . write_request_to_send ( true ) ?;
138-
139- sleep ( Duration :: from_millis ( 100 ) ) ;
140-
141- self . serial . write_data_terminal_ready ( false ) ?;
142- self . serial . write_request_to_send ( false ) ?;
137+ UsbJtagSerialReset . reset ( & mut self . serial )
143138 } else {
144- self . serial . write_data_terminal_ready ( false ) ?;
145- self . serial . write_request_to_send ( true ) ?;
146-
147- sleep ( Duration :: from_millis ( 100 ) ) ;
148-
149- self . serial . write_data_terminal_ready ( true ) ?;
150- self . serial . write_request_to_send ( false ) ?;
151-
152- let millis = if extra_delay { 500 } else { 50 } ;
153- sleep ( Duration :: from_millis ( millis) ) ;
139+ #[ cfg( unix) ]
140+ if UnixTightReset :: new ( extra_delay)
141+ . reset ( & mut self . serial )
142+ . is_ok ( )
143+ {
144+ return Ok ( ( ) ) ;
145+ }
154146
155- self . serial . write_data_terminal_ready ( false ) ? ;
147+ ClassicReset :: new ( extra_delay ) . reset ( & mut self . serial )
156148 }
157-
158- Ok ( ( ) )
159149 }
160150
161151 /// Set timeout for the serial port
@@ -177,11 +167,10 @@ impl Connection {
177167 }
178168
179169 /// Run a command with a timeout defined by the command type
180- pub fn with_timeout < T , F : FnMut ( & mut Connection ) -> Result < T , Error > > (
181- & mut self ,
182- timeout : Duration ,
183- mut f : F ,
184- ) -> Result < T , Error > {
170+ pub fn with_timeout < T , F > ( & mut self , timeout : Duration , mut f : F ) -> Result < T , Error >
171+ where
172+ F : FnMut ( & mut Connection ) -> Result < T , Error > ,
173+ {
185174 let old_timeout = {
186175 let serial = self . serial . serial_port_mut ( ) ;
187176 let old_timeout = serial. timeout ( ) ;
0 commit comments