33# Variable baud rate bootloader for Artemis Apollo3 modules
44
55# Immediately upon reset the Artemis module will search for the timing character
6- # to auto-detect the baud rate. If a valid baud rate is found the Artemis will
6+ # to auto-detect the baud rate. If a valid baud rate is found the Artemis will
77# respond with the bootloader version packet
88# If the computer receives a well-formatted version number packet at the desired
9- # baud rate it will send a command to begin bootloading. The Artemis shall then
10- # respond with the a command asking for the next frame.
11- # The host will then send a frame packet. If the CRC is OK the Artemis will write
9+ # baud rate it will send a command to begin bootloading. The Artemis shall then
10+ # respond with the a command asking for the next frame.
11+ # The host will then send a frame packet. If the CRC is OK the Artemis will write
1212# that to memory and request the next frame. If the CRC fails the Artemis will
1313# discard that data and send a request to re-send the previous frame.
1414# This cycle repeats until the Artemis receives a done command in place of the
1515# requested frame data command.
16- # The initial baud rate determination must occur within some small timeout. Once
17- # baud rate detection has completed all additional communication will have a
16+ # The initial baud rate determination must occur within some small timeout. Once
17+ # baud rate detection has completed all additional communication will have a
1818# universal timeout value. Once the Artemis has begun requesting data it may no
19- # no longer exit the bootloader. If the host detects a timeout at any point it
20- # will stop bootloading.
19+ # no longer exit the bootloader. If the host detects a timeout at any point it
20+ # will stop bootloading.
2121
2222# Notes about PySerial timeout:
23- # The timeout operates on whole functions - that is to say that a call to
24- # ser.read(10) will return after ser.timeout, just as will ser.read(1) (assuming
23+ # The timeout operates on whole functions - that is to say that a call to
24+ # ser.read(10) will return after ser.timeout, just as will ser.read(1) (assuming
2525# that the necessary bytes were not found)
26- # If there are no incoming bytes (on the line or in the buffer) then two calls to
26+ # If there are no incoming bytes (on the line or in the buffer) then two calls to
2727# ser.read(n) will time out after 2*ser.timeout
2828# Incoming UART data is buffered behind the scenes, probably by the OS.
2929
4646# Commands
4747#
4848# ***********************************************************************************
49- SVL_CMD_VER = 0x01 # version
50- SVL_CMD_BL = 0x02 # enter bootload mode
51- SVL_CMD_NEXT = 0x03 # request next chunk
52- SVL_CMD_FRAME = 0x04 # indicate app data frame
53- SVL_CMD_RETRY = 0x05 # request re-send frame
54- SVL_CMD_DONE = 0x06 # finished - all data sent
49+ SVL_CMD_VER = 0x01 # version
50+ SVL_CMD_BL = 0x02 # enter bootload mode
51+ SVL_CMD_NEXT = 0x03 # request next chunk
52+ SVL_CMD_FRAME = 0x04 # indicate app data frame
53+ SVL_CMD_RETRY = 0x05 # request re-send frame
54+ SVL_CMD_DONE = 0x06 # finished - all data sent
5555
5656barWidthInCharacters = 50 # Width of progress bar, ie [###### % complete
5757
9797
9898def get_crc16 (data ):
9999
100- #Table and code ported from Artemis SVL bootloader
100+ # Table and code ported from Artemis SVL bootloader
101101 crc = 0x0000
102102 data = bytearray (data )
103103 for ch in data :
@@ -108,30 +108,33 @@ def get_crc16(data):
108108 return crc
109109
110110
111-
112111# ***********************************************************************************
113112#
114- # Wait for a packet
113+ # Wait for a packet
115114#
116115# ***********************************************************************************
117116def wait_for_packet (ser ):
118117
119- packet = {'len' :0 , 'cmd' :0 , 'data' :0 , 'crc' :1 , 'timeout' :1 }
118+ packet = {'len' : 0 , 'cmd' : 0 , 'data' : 0 , 'crc' : 1 , 'timeout' : 1 }
120119
121- n = ser .read (2 ) # get the number of bytes
120+ n = ser .read (2 ) # get the number of bytes
122121 if (len (n ) < 2 ):
123122 return packet
124-
125- packet ['len' ] = int .from_bytes (n , byteorder = 'big' , signed = False ) #
123+
124+ packet ['len' ] = int .from_bytes (n , byteorder = 'big' , signed = False ) #
126125 payload = ser .read (packet ['len' ])
127126
128127 if (len (payload ) != packet ['len' ]):
129128 return packet
130-
131- packet ['timeout' ] = 0 # all bytes received, so timeout is not true
132- packet ['cmd' ] = payload [0 ] # cmd is the first byte of the payload
133- packet ['data' ] = payload [1 :packet ['len' ]- 2 ] # the data is the part of the payload that is not cmd or crc
134- packet ['crc' ] = get_crc16 (payload ) # performing the crc on the whole payload should return 0
129+
130+ # all bytes received, so timeout is not true
131+ packet ['timeout' ] = 0
132+ # cmd is the first byte of the payload
133+ packet ['cmd' ] = payload [0 ]
134+ # the data is the part of the payload that is not cmd or crc
135+ packet ['data' ] = payload [1 :packet ['len' ]- 2 ]
136+ # performing the crc on the whole payload should return 0
137+ packet ['crc' ] = get_crc16 (payload )
135138
136139 return packet
137140
@@ -140,22 +143,20 @@ def wait_for_packet(ser):
140143# Send a packet
141144#
142145# ***********************************************************************************
146+
147+
143148def send_packet (ser , cmd , data ):
144149 data = bytearray (data )
145150 num_bytes = 3 + len (data )
146- payload = bytearray (cmd .to_bytes (1 ,'big' ))
151+ payload = bytearray (cmd .to_bytes (1 , 'big' ))
147152 payload .extend (data )
148153 crc = get_crc16 (payload )
149- payload .extend (bytearray (crc .to_bytes (2 ,'big' )))
154+ payload .extend (bytearray (crc .to_bytes (2 , 'big' )))
150155
151- ser .write (num_bytes .to_bytes (2 ,'big' ))
156+ ser .write (num_bytes .to_bytes (2 , 'big' ))
152157 ser .write (bytes (payload ))
153158
154159
155-
156-
157-
158-
159160# ***********************************************************************************
160161#
161162# Setup: signal baud rate, get version, and command BL enter
@@ -166,29 +167,25 @@ def phase_setup(ser):
166167 baud_detect_byte = b'U'
167168
168169 verboseprint ('\n phase:\t setup' )
169-
170- # Handle the serial startup blip
170+
171+ # Handle the serial startup blip
171172 ser .reset_input_buffer ()
172- verboseprint ('\t cleared startup blip' )
173+ verboseprint ('\t cleared startup blip' )
173174
174175 ser .write (baud_detect_byte ) # send the baud detection character
175176
176177 packet = wait_for_packet (ser )
177178 if (packet ['timeout' ] or packet ['crc' ]):
178179 return 1
179-
180- twopartprint ('\t ' ,'Got SVL Bootloader Version: ' +
180+
181+ twopartprint ('\t ' , 'Got SVL Bootloader Version: ' +
181182 str (int .from_bytes (packet ['data' ], 'big' )))
182183 verboseprint ('\t Sending \' enter bootloader\' command' )
183184
184185 send_packet (ser , SVL_CMD_BL , b'' )
185186
186187 # Now enter the bootload phase
187188
188-
189-
190-
191-
192189
193190# ***********************************************************************************
194191#
@@ -222,32 +219,34 @@ def phase_bootload(ser):
222219 bl_done = False
223220 bl_failed = False
224221 while ((not bl_done ) and (not bl_failed )):
225-
226- packet = wait_for_packet (ser ) # wait for indication by Artemis
222+
223+ # wait for indication by Artemis
224+ packet = wait_for_packet (ser )
227225 if (packet ['timeout' ] or packet ['crc' ]):
228226 print ('\n \t error receiving packet' )
229227 print (packet )
230228 print ('\n ' )
231229 bl_failed = True
232230 bl_done = True
233231
234- if ( packet ['cmd' ] == SVL_CMD_NEXT ):
232+ if (packet ['cmd' ] == SVL_CMD_NEXT ):
235233 # verboseprint('\tgot frame request')
236234 curr_frame += 1
237235 resend_count = 0
238- elif ( packet ['cmd' ] == SVL_CMD_RETRY ):
236+ elif (packet ['cmd' ] == SVL_CMD_RETRY ):
239237 verboseprint ('\t \t retrying...' )
240238 resend_count += 1
241- if ( resend_count >= resend_max ):
239+ if (resend_count >= resend_max ):
242240 bl_failed = True
243241 bl_done = True
244242 else :
245243 print ('unknown error' )
246244 bl_failed = True
247245 bl_done = True
248246
249- if ( curr_frame <= total_frames ):
250- frame_data = application [((curr_frame - 1 )* frame_size ):((curr_frame - 1 + 1 )* frame_size )]
247+ if (curr_frame <= total_frames ):
248+ frame_data = application [(
249+ (curr_frame - 1 )* frame_size ):((curr_frame - 1 + 1 )* frame_size )]
251250 if (args .verbose ):
252251 verboseprint ('\t sending frame #' + str (curr_frame ) +
253252 ', length: ' + str (len (frame_data )))
@@ -267,7 +266,7 @@ def phase_bootload(ser):
267266 send_packet (ser , SVL_CMD_DONE , b'' )
268267 bl_done = True
269268
270- if ( bl_failed == False ):
269+ if (bl_failed == False ):
271270 twopartprint ('\n \t ' , 'Upload complete' )
272271 endTime = time .time ()
273272 bps = total_len / (endTime - startTime )
@@ -278,10 +277,6 @@ def phase_bootload(ser):
278277 return bl_failed
279278
280279
281-
282-
283-
284-
285280# ***********************************************************************************
286281#
287282# Help if serial port could not be opened
@@ -294,12 +289,12 @@ def phase_serial_port_help():
294289 for dev in devices :
295290 if (dev .device .upper () == args .port .upper ()):
296291 print (dev .device + " is currently open. Please close any other terminal programs that may be using " +
297- dev .device + " and try again." )
292+ dev .device + " and try again." )
298293 exit ()
299294
300295 # otherwise, give user a list of possible com ports
301296 print (args .port .upper () +
302- " not found but we detected the following serial ports:" )
297+ " not found but we detected the following serial ports:" )
303298 for dev in devices :
304299 if 'CH340' in dev .description :
305300 print (
@@ -329,19 +324,20 @@ def main():
329324
330325 with serial .Serial (args .port , args .baud , timeout = args .timeout ) as ser :
331326
332- t_su = 0.15 # startup time for Artemis bootloader (experimentally determined - 0.095 sec min delay)
327+ # startup time for Artemis bootloader (experimentally determined - 0.095 sec min delay)
328+ t_su = 0.15
333329
334330 time .sleep (t_su ) # Allow Artemis to come out of reset
335331 phase_setup (ser ) # Perform baud rate negotiation
336332
337333 bl_failed = phase_bootload (ser ) # Bootload
338334
339- if ( bl_failed == False ):
335+ if (bl_failed == False ):
340336 break
341337
342338 except :
343339 phase_serial_port_help ()
344-
340+
345341 exit ()
346342
347343
@@ -367,7 +363,7 @@ def main():
367363 action = "store_true" )
368364
369365 parser .add_argument ("-t" , "--timeout" , default = 0.50 , help = "Communication timeout in seconds (default 0.5)" ,
370- type = float )
366+ type = float )
371367
372368 if len (sys .argv ) < 2 :
373369 print ("No port selected. Detected Serial Ports:" )
@@ -390,7 +386,7 @@ def verboseprint(*args):
390386
391387 def twopartprint (verbosestr , printstr ):
392388 if args .verbose :
393- print (verbosestr , end = '' )
389+ print (verbosestr , end = '' )
394390
395391 print (printstr )
396392
0 commit comments