@@ -178,7 +178,48 @@ def _get_provided_nrf51_bl_version(self, flash_artifacts: List[FlashArtifact]):
178
178
179
179
return provided_nrf_bl_version
180
180
181
- def flash (self , filename : str , targets : List [Target ], cf = None , enable_console_log : Optional [bool ] = False ):
181
+ def _get_boot_delay (self , cf : Optional [Crazyflie ] = None ) -> float :
182
+ """
183
+ Determines the boot delay for the Crazyflie.
184
+ This method calculates the boot delay based on the presence of specific decks.
185
+ If the AI deck is attached, a longer boot delay is used.
186
+ @return: The boot delay in seconds. Returns -1 if no deck memory is found.
187
+ @rtype: float
188
+ @raises RuntimeError: If there is a failure in reading the decks.
189
+ """
190
+
191
+ if cf is not None and cf .link :
192
+ cf .close_link ()
193
+
194
+ try :
195
+ with SyncCrazyflie (self .clink , cf = Crazyflie ()) as scf :
196
+ deck_mems = scf .cf .mem .get_mems (MemoryElement .TYPE_DECK_MEMORY )
197
+ deck_mems_count = len (deck_mems )
198
+ if deck_mems_count == 0 :
199
+ return - 1
200
+
201
+ mgr = deck_memory .SyncDeckMemoryManager (deck_mems [0 ])
202
+ try :
203
+ decks = mgr .query_decks ()
204
+ except RuntimeError as e :
205
+ if self .progress_cb :
206
+ message = f'Failed to read decks: { str (e )} '
207
+ self .progress_cb (message , 0 )
208
+ logger .error (message )
209
+ time .sleep (2 )
210
+ raise RuntimeError (message )
211
+
212
+ if any (deck .name in ['bcAI:gap8' , 'bcAI:esp' ] for deck in decks .values ()):
213
+ return 5.0
214
+ except Exception as e :
215
+ # If we fail to connect to the Crazyflie in firmware mode, we assume the AI-deck is attached
216
+ print (f'Failed to connect to Crazyflie in firmware mode: { str (e )} . Setting boot delay to 5.0 seconds' )
217
+ return 5.0 # AI-deck may be attached
218
+
219
+ return 0.0
220
+
221
+ def flash (self , filename : str , targets : List [Target ], cf = None , enable_console_log : Optional [bool ] = False ,
222
+ boot_delay : Optional [float ] = 0.0 ):
182
223
# Separate flash targets from decks
183
224
platform = self ._get_platform_id ()
184
225
flash_targets = [t for t in targets if t .platform == platform ]
@@ -276,23 +317,21 @@ def flash(self, filename: str, targets: List[Target], cf=None, enable_console_lo
276
317
self .progress_cb ('Restarting firmware to update decks.' , int (0 ))
277
318
278
319
# Reset to firmware mode
279
- self .reset_to_firmware (boot_delay = 5.0 )
320
+ self .reset_to_firmware (boot_delay = boot_delay )
280
321
self .close ()
281
322
time .sleep (2 )
282
323
283
324
# Flash all decks and reboot after each deck
284
325
current_index = 0
285
326
while current_index != - 1 :
286
327
current_index = self ._flash_deck_incrementally (deck_artifacts , deck_targets , current_index ,
287
- enable_console_log = enable_console_log )
328
+ enable_console_log = enable_console_log ,
329
+ boot_delay = boot_delay )
288
330
if self .progress_cb :
289
331
self .progress_cb ('Deck updated! Restarting...' , int (100 ))
290
332
if current_index != - 1 :
291
333
PowerSwitch (self .clink ).reboot_to_fw ()
292
- if any (deck .target in ['bcAI:gap8' , 'bcAI:esp' ] for deck in deck_targets ):
293
- time .sleep (7 )
294
- else :
295
- time .sleep (2 )
334
+ time .sleep (2.0 + boot_delay )
296
335
297
336
# Put the crazyflie back in Bootloader mode to exit the function in the same state we entered it
298
337
self .start_bootloader (warm_boot = True , cf = cf )
@@ -321,6 +360,9 @@ def flash_full(self, cf: Optional[Crazyflie] = None,
321
360
Flash .zip or bin .file to list of targets.
322
361
Reset to firmware when done.
323
362
"""
363
+ # Get the required boot delay
364
+ boot_delay = self ._get_boot_delay (cf = cf )
365
+
324
366
if progress_cb is not None :
325
367
self .progress_cb = progress_cb
326
368
if terminate_flash_cb is not None :
@@ -336,7 +378,7 @@ def flash_full(self, cf: Optional[Crazyflie] = None,
336
378
info_cb (self .protocol_version , connected )
337
379
338
380
if filename is not None :
339
- self .flash (filename , targets , cf , enable_console_log = enable_console_log )
381
+ self .flash (filename , targets , cf , enable_console_log = enable_console_log , boot_delay = boot_delay )
340
382
self .reset_to_firmware (boot_delay = 5.0 )
341
383
342
384
def _get_flash_artifacts_from_zip (self , filename ):
@@ -549,7 +591,7 @@ def console_callback(self, text: str):
549
591
print (text , end = '' )
550
592
551
593
def _flash_deck_incrementally (self , artifacts : List [FlashArtifact ], targets : List [Target ], start_index : int ,
552
- enable_console_log : Optional [bool ] = False ):
594
+ enable_console_log : Optional [bool ] = False , boot_delay = 0.0 ):
553
595
flash_all_targets = len (targets ) == 0
554
596
if self .progress_cb :
555
597
self .progress_cb ('Identifying deck to be updated' , 0 )
@@ -604,10 +646,7 @@ def _flash_deck_incrementally(self, artifacts: List[FlashArtifact], targets: Lis
604
646
self .progress_cb (f'Updating deck { deck .name } ' , 0 )
605
647
606
648
# Test and wait for the deck to be started
607
- if any (deck .name in ['bcAI:gap8' , 'bcAI:esp' ] for deck in decks .values ()):
608
- timeout_time = time .time () + 9
609
- else :
610
- timeout_time = time .time () + 4
649
+ timeout_time = time .time () + 4. + boot_delay
611
650
while not deck .is_started :
612
651
if time .time () > timeout_time :
613
652
raise RuntimeError (f'Deck { deck .name } did not start' )
@@ -634,10 +673,7 @@ def _flash_deck_incrementally(self, artifacts: List[FlashArtifact], targets: Lis
634
673
continue
635
674
636
675
# Wait for bootloader to be ready
637
- if any (deck .name in ['bcAI:gap8' , 'bcAI:esp' ] for deck in decks .values ()):
638
- timeout_time = time .time () + 9
639
- else :
640
- timeout_time = time .time () + 4
676
+ timeout_time = time .time () + 4. + boot_delay
641
677
while not deck .is_bootloader_active :
642
678
if time .time () > timeout_time :
643
679
raise RuntimeError (f'Deck { deck .name } did not enter bootloader mode' )
0 commit comments