@@ -533,32 +533,56 @@ void common_hal_wifi_radio_set_ipv4_address_ap(wifi_radio_obj_t *self, mp_obj_t
533
533
common_hal_wifi_radio_start_dhcp_server (self ); // restart access point DHCP
534
534
}
535
535
536
+ static void ping_success_cb (esp_ping_handle_t hdl , void * args ) {
537
+ wifi_radio_obj_t * self = (wifi_radio_obj_t * )args ;
538
+ esp_ping_get_profile (hdl , ESP_PING_PROF_TIMEGAP , & self -> ping_elapsed_time , sizeof (self -> ping_elapsed_time ));
539
+ }
540
+
536
541
mp_int_t common_hal_wifi_radio_ping (wifi_radio_obj_t * self , mp_obj_t ip_address , mp_float_t timeout ) {
537
542
esp_ping_config_t ping_config = ESP_PING_DEFAULT_CONFIG ();
538
543
ipaddress_ipaddress_to_esp_idf (ip_address , & ping_config .target_addr );
539
544
ping_config .count = 1 ;
540
545
546
+ // We must fetch ping information using the callback mechanism, because the session storage is freed when
547
+ // the ping session is done, even before esp_ping_delete_session().
548
+ esp_ping_callbacks_t ping_callbacks = {
549
+ .on_ping_success = ping_success_cb ,
550
+ .cb_args = (void * )self ,
551
+ };
552
+
541
553
size_t timeout_ms = timeout * 1000 ;
542
554
555
+ // ESP-IDF creates a task to do the ping session. It shuts down when done, but only after a one second delay.
556
+ // Calling common_hal_wifi_radio_ping() too fast will cause resource exhaustion.
543
557
esp_ping_handle_t ping ;
544
- CHECK_ESP_RESULT (esp_ping_new_session (& ping_config , NULL , & ping ));
558
+ if (esp_ping_new_session (& ping_config , & ping_callbacks , & ping ) != ESP_OK ) {
559
+ // Wait for old task to go away and then try again.
560
+ // Empirical testing shows we have to wait at least two seconds, despite the task
561
+ // having a one-second timeout.
562
+ common_hal_time_delay_ms (2000 );
563
+ // Return if interrupted now, to show the interruption as KeyboardInterrupt instead of the
564
+ // IDF error.
565
+ if (mp_hal_is_interrupted ()) {
566
+ return (uint32_t )(-1 );
567
+ }
568
+ CHECK_ESP_RESULT (esp_ping_new_session (& ping_config , & ping_callbacks , & ping ));
569
+ }
570
+
545
571
esp_ping_start (ping );
546
572
547
- uint32_t received = 0 ;
548
- uint32_t total_time_ms = 0 ;
573
+ // Use all ones as a flag that the elapsed time was not set (ping failed or timed out).
574
+ self -> ping_elapsed_time = (uint32_t )(-1 );
575
+
549
576
uint32_t start_time = common_hal_time_monotonic_ms ();
550
- while (received == 0 && (common_hal_time_monotonic_ms () - start_time < timeout_ms ) && !mp_hal_is_interrupted ()) {
577
+ while ((self -> ping_elapsed_time == (uint32_t )(-1 )) &&
578
+ (common_hal_time_monotonic_ms () - start_time < timeout_ms ) &&
579
+ !mp_hal_is_interrupted ()) {
551
580
RUN_BACKGROUND_TASKS ;
552
- esp_ping_get_profile (ping , ESP_PING_PROF_DURATION , & total_time_ms , sizeof (total_time_ms ));
553
- esp_ping_get_profile (ping , ESP_PING_PROF_REPLY , & received , sizeof (received ));
554
- }
555
- uint32_t elapsed_time = 0xffffffff ;
556
- if (received > 0 ) {
557
- esp_ping_get_profile (ping , ESP_PING_PROF_TIMEGAP , & elapsed_time , sizeof (elapsed_time ));
558
581
}
582
+ esp_ping_stop (ping );
559
583
esp_ping_delete_session (ping );
560
584
561
- return elapsed_time ;
585
+ return ( mp_int_t ) self -> ping_elapsed_time ;
562
586
}
563
587
564
588
void common_hal_wifi_radio_gc_collect (wifi_radio_obj_t * self ) {
0 commit comments