44
55// The "X" commands are for external flash
66
7- use crate :: errors;
7+ use crate :: errors:: { self , InternalError , TockError } ;
88use bytes:: BytesMut ;
99use errors:: TockloaderError ;
1010use std:: time:: Duration ;
@@ -17,6 +17,8 @@ pub const SYNC_MESSAGE: [u8; 3] = [0x00, 0xFC, 0x05];
1717// "This was chosen as it is infrequent in .bin files" - immesys
1818pub const ESCAPE_CHAR : u8 = 0xFC ;
1919
20+ pub const DEFAULT_TIMEOUT : Duration = Duration :: from_millis ( 500 ) ;
21+
2022#[ allow( dead_code) ]
2123pub enum Command {
2224 // Commands from this tool to the bootloader
@@ -99,46 +101,77 @@ impl From<u8> for Response {
99101pub async fn toggle_bootloader_entry_dtr_rts (
100102 port : & mut SerialStream ,
101103) -> Result < ( ) , TockloaderError > {
102- port. write_data_terminal_ready ( true )
103- . map_err ( TockloaderError :: SerialInitializationError ) ?;
104- port. write_request_to_send ( true )
105- . map_err ( TockloaderError :: SerialInitializationError ) ?;
104+ port. write_data_terminal_ready ( true ) ?;
105+ port. write_request_to_send ( true ) ?;
106106
107107 tokio:: time:: sleep ( Duration :: from_millis ( 100 ) ) . await ;
108108
109- port. write_data_terminal_ready ( false )
110- . map_err ( TockloaderError :: SerialInitializationError ) ?;
109+ port. write_data_terminal_ready ( false ) ?;
111110
112111 tokio:: time:: sleep ( Duration :: from_millis ( 500 ) ) . await ;
113112
114- port. write_request_to_send ( false )
115- . map_err ( TockloaderError :: SerialInitializationError ) ?;
113+ port. write_request_to_send ( false ) ?;
116114
117115 Ok ( ( ) )
118116}
119117
118+ async fn read_bytes (
119+ port : & mut SerialStream ,
120+ bytes_to_read : usize ,
121+ timeout : Duration ,
122+ ) -> Result < BytesMut , TockloaderError > {
123+ let mut ret = BytesMut :: with_capacity ( bytes_to_read) ;
124+ let mut read_bytes = 0 ;
125+
126+ tokio:: time:: timeout ( timeout, async {
127+ while read_bytes < bytes_to_read {
128+ read_bytes += port
129+ . read_buf ( & mut ret)
130+ . await
131+ . map_err ( |e| TockloaderError :: Serial ( e. into ( ) ) ) ?;
132+ }
133+ Ok ( ret)
134+ } )
135+ . await
136+ . map_err ( |_| TockError :: BootloaderTimeout ) ?
137+ }
138+
139+ async fn write_bytes (
140+ port : & mut SerialStream ,
141+ bytes : & [ u8 ] ,
142+ timeout : Duration ,
143+ ) -> Result < ( ) , TockloaderError > {
144+ let mut bytes_written = 0 ;
145+
146+ tokio:: time:: timeout ( timeout, async {
147+ while bytes_written != bytes. len ( ) {
148+ bytes_written += port
149+ . write_buf ( & mut & bytes[ bytes_written..] )
150+ . await
151+ . map_err ( |e| TockloaderError :: Serial ( e. into ( ) ) ) ?;
152+ }
153+ Ok ( ( ) )
154+ } )
155+ . await
156+ . map_err ( |_| TockError :: BootloaderTimeout ) ?
157+ }
158+
120159#[ allow( dead_code) ]
121160pub async fn ping_bootloader_and_wait_for_response (
122161 port : & mut SerialStream ,
123- ) -> Result < Response , TockloaderError > {
162+ ) -> Result < ( ) , TockloaderError > {
124163 let ping_pkt = [ ESCAPE_CHAR , Command :: Ping as u8 ] ;
125164
126- let mut ret = BytesMut :: with_capacity ( 200 ) ;
127-
128165 for _ in 0 ..30 {
129- let mut bytes_written = 0 ;
130- while bytes_written != ping_pkt. len ( ) {
131- bytes_written += port. write_buf ( & mut & ping_pkt[ bytes_written..] ) . await ?;
132- }
133- let mut read_bytes = 0 ;
134- while read_bytes < 2 {
135- read_bytes += port. read_buf ( & mut ret) . await ?;
136- }
166+ write_bytes ( port, & ping_pkt, DEFAULT_TIMEOUT ) . await ?;
167+ let ret = read_bytes ( port, 2 , DEFAULT_TIMEOUT ) . await ?;
168+
137169 if ret[ 1 ] == Response :: Pong as u8 {
138- return Ok ( Response :: from ( ret [ 1 ] ) ) ;
170+ return Ok ( ( ) ) ;
139171 }
140172 }
141- Ok ( Response :: from ( ret[ 1 ] ) )
173+
174+ Err ( InternalError :: BootloaderNotPresent . into ( ) )
142175}
143176
144177#[ allow( dead_code) ]
@@ -174,46 +207,37 @@ pub async fn issue_command(
174207 }
175208
176209 // Write the command message
177- let mut bytes_written = 0 ;
178- while bytes_written != message. len ( ) {
179- bytes_written += port. write_buf ( & mut & message[ bytes_written..] ) . await ?;
180- }
210+ write_bytes ( port, & message, DEFAULT_TIMEOUT ) . await ?;
181211
182212 // Response has a two byte header, then response_len bytes
183- let bytes_to_read = 2 + response_len;
184- let mut ret = BytesMut :: with_capacity ( 2 ) ;
213+ let header = read_bytes ( port, 2 , DEFAULT_TIMEOUT ) . await ?;
185214
186- // We are waiting for 2 bytes to be read
187- let mut read_bytes = 0 ;
188- while read_bytes < 2 {
189- read_bytes += port. read_buf ( & mut ret) . await ?;
215+ if header[ 0 ..2 ] != [ ESCAPE_CHAR , response_code as u8 ] {
216+ return Err ( TockError :: BootloaderBadHeader ( header[ 0 ] , header[ 1 ] ) . into ( ) ) ;
190217 }
191218
192- if ret[ 0 ] != ESCAPE_CHAR {
193- return Err ( TockloaderError :: BootloaderError ( ret[ 0 ] ) ) ;
194- }
195-
196- if ret[ 1 ] != response_code. clone ( ) as u8 {
197- return Err ( TockloaderError :: BootloaderError ( ret[ 1 ] ) ) ;
198- }
199-
200- let mut new_data: Vec < u8 > = Vec :: new ( ) ;
201- let mut value = 2 ;
202-
203219 if response_len != 0 {
204- while bytes_to_read > value {
205- value += port. read_buf ( & mut new_data) . await ?;
206- }
220+ let input = read_bytes ( port, response_len, DEFAULT_TIMEOUT ) . await ?;
221+ let mut result = Vec :: with_capacity ( input. len ( ) ) ;
207222
208223 // De-escape and add array of read in the bytes
209- for i in 0 ..( new_data. len ( ) - 1 ) {
210- if new_data[ i] == ESCAPE_CHAR && new_data[ i + 1 ] == ESCAPE_CHAR {
211- new_data. remove ( i + 1 ) ;
224+
225+ // TODO(george-cosma): Extract this into a function and unit test this.
226+ let mut i = 0 ;
227+ while i < input. len ( ) {
228+ if i + 1 < input. len ( ) && input[ i] == ESCAPE_CHAR && input[ i + 1 ] == ESCAPE_CHAR {
229+ // Found consecutive ESCAPE_CHAR bytes, add only one
230+ result. push ( ESCAPE_CHAR ) ;
231+ i += 2 ; // Skip both bytes
232+ } else {
233+ // Not consecutive ESCAPE_CHAR, add the current byte
234+ result. push ( input[ i] ) ;
235+ i += 1 ;
212236 }
213237 }
214238
215- ret. extend_from_slice ( & new_data) ;
239+ Ok ( ( Response :: from ( header[ 1 ] ) , result) )
240+ } else {
241+ Ok ( ( Response :: from ( header[ 1 ] ) , vec ! [ ] ) )
216242 }
217-
218- Ok ( ( Response :: from ( ret[ 1 ] ) , ret[ 2 ..] . to_vec ( ) ) )
219243}
0 commit comments