FTM responder long term stability

Weigen Qiu
Posts: 11
Joined: Thu Jul 02, 2020 8:40 pm

FTM responder long term stability

Postby Weigen Qiu » Mon Nov 08, 2021 12:33 am

Hello,

I have spent some time testing the FTM functionality of the ESP32C3 chip. I created a FTM responder with the code in official ftm example, and created the ftm initiator with the attached code.

in the first few minutes, the ftm reports were successfully received, but eventually, the ftm responder stopped responding, and the initiator started receiving reports with error status (FTM_STATUS_CONF_REJECTED).

Does anyone have the same issue? and how should I resolve this issue?
any help is appreciated.
Thanks

Update: I also tested the ftm responder code with ESP32S2 board, and received the same results. It looks like some kind of memory leak issue.

  1. #include <errno.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include "nvs_flash.h"
  6. //#include "cmd_system.h"
  7. #include "argtable3/argtable3.h"
  8. #include "freertos/FreeRTOS.h"
  9. #include "freertos/event_groups.h"
  10. #include "esp_event.h"
  11. #include "esp_log.h"
  12. #include "esp_err.h"
  13. #include "esp_wifi.h"
  14. #include "esp_console.h"
  15. #include "esp_task_wdt.h"
  16.  
  17.  
  18. #define MAX_ANCHORS 8
  19.  
  20.  
  21. static const char *TAG_STA = "ftm_tag";
  22.  
  23.  
  24. static EventGroupHandle_t wifi_event_group;
  25. const int CONNECTED_BIT = BIT0;
  26. const int DISCONNECTED_BIT = BIT1;
  27.  
  28. static EventGroupHandle_t ftm_event_group;
  29. const int FTM_REPORT_BIT = BIT0;
  30. const int FTM_FAILURE_BIT = BIT1;
  31. wifi_ftm_report_entry_t *g_ftm_report;
  32. uint8_t g_ftm_report_num_entries;
  33.  
  34. uint16_t g_scan_ap_num;
  35. wifi_ap_record_t *g_ap_list_buffer;
  36.  
  37.  
  38. wifi_ap_record_t anchors[MAX_ANCHORS];
  39. uint8_t num_anchors, current_anchor;
  40.  
  41. uint8_t just_reboot= 0;
  42.  
  43.  
  44. ESP_EVENT_DEFINE_BASE(END_SCAN_OR_FTM_EVENT);
  45.  
  46.  
  47. static void wifi_connected_handler(void *arg, esp_event_base_t event_base,
  48.                                    int32_t event_id, void *event_data)
  49. {
  50.     xEventGroupClearBits(wifi_event_group, DISCONNECTED_BIT);
  51.     xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
  52. }
  53.  
  54. static void disconnect_handler(void *arg, esp_event_base_t event_base,
  55.                                int32_t event_id, void *event_data)
  56. {
  57.     xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
  58.     xEventGroupSetBits(wifi_event_group, DISCONNECTED_BIT);
  59. }
  60.  
  61. static void ftm_report_handler(void *arg, esp_event_base_t event_base,
  62.                                int32_t event_id, void *event_data)
  63. {
  64.     wifi_event_ftm_report_t *event = (wifi_event_ftm_report_t *) event_data;
  65.  
  66.     ESP_LOGI(TAG_STA, "FTM HANDLER");
  67.     if (event->status == FTM_STATUS_SUCCESS) {
  68.  
  69.         g_ftm_report = event->ftm_report_data;
  70.         g_ftm_report_num_entries = event->ftm_report_num_entries;
  71.  
  72.         xEventGroupSetBits(ftm_event_group, FTM_REPORT_BIT);
  73.     } else {
  74.  
  75.         if (event->status == FTM_STATUS_UNSUPPORTED){
  76.                     ESP_LOGI(TAG_STA, "FTM procedure with Peer("MACSTR") failed! (Status - FTM_STATUS_UNSUPPORTED)",
  77.                  MAC2STR(event->peer_mac));
  78.         } else if (event->status == FTM_STATUS_CONF_REJECTED){
  79.                     ESP_LOGI(TAG_STA, "FTM procedure with Peer("MACSTR") failed! (Status - FTM_STATUS_CONF_REJECTED)",
  80.                  MAC2STR(event->peer_mac));
  81.         } else if (event->status == FTM_STATUS_NO_RESPONSE){
  82.                     ESP_LOGI(TAG_STA, "FTM procedure with Peer("MACSTR") failed! (Status - FTM_STATUS_NO_RESPONSE)",
  83.                  MAC2STR(event->peer_mac));
  84.         } else if (event->status == FTM_STATUS_FAIL){
  85.                     ESP_LOGI(TAG_STA, "FTM procedure with Peer("MACSTR") failed! (Status - FTM_STATUS_FAIL)",
  86.                  MAC2STR(event->peer_mac));
  87.         }
  88.  
  89.         xEventGroupSetBits(ftm_event_group, FTM_FAILURE_BIT);
  90.     }
  91.  
  92. }
  93.  
  94.  
  95. static bool wifi_perform_scan(const char *ssid, bool internal)
  96. {
  97.     wifi_scan_config_t scan_config = { 0 };
  98.     scan_config.ssid = (uint8_t *) ssid;
  99.     uint8_t i;
  100.  
  101.     ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
  102.     ESP_ERROR_CHECK( esp_wifi_scan_start(&scan_config, true) );
  103.  
  104.     esp_wifi_scan_get_ap_num(&g_scan_ap_num);
  105.     if (g_scan_ap_num == 0) {
  106.         ESP_LOGI(TAG_STA, "No matching AP found");
  107.         return false;
  108.     }
  109.  
  110.     if (g_ap_list_buffer) {
  111.         free(g_ap_list_buffer);
  112.     }
  113.     g_ap_list_buffer = malloc(g_scan_ap_num * sizeof(wifi_ap_record_t));
  114.     if (g_ap_list_buffer == NULL) {
  115.         ESP_LOGE(TAG_STA, "Failed to malloc buffer to print scan results");
  116.         return false;
  117.     }
  118.  
  119.     if (esp_wifi_scan_get_ap_records(&g_scan_ap_num, (wifi_ap_record_t *)g_ap_list_buffer) == ESP_OK) {
  120.        
  121.         num_anchors = 0;
  122.         for (i = 0; i < g_scan_ap_num; i++) {
  123.             if (num_anchors<MAX_ANCHORS && g_ap_list_buffer[i].ftm_responder){
  124.                 anchors[num_anchors] = g_ap_list_buffer[i];
  125.                 num_anchors+=1;
  126.             }
  127.             ESP_LOGI(TAG_STA, "[%s][rssi=%d]""%s", g_ap_list_buffer[i].ssid, g_ap_list_buffer[i].rssi, g_ap_list_buffer[i].ftm_responder ? "[FTM Responder]" : "");
  128.         }
  129.     }
  130.    
  131.     ESP_LOGI(TAG_STA, "Scan done %d anchors found", num_anchors);
  132.     return true;
  133. }
  134.  
  135.  
  136. static int do_ftm(wifi_ap_record_t *ap_record){
  137.  
  138.     ESP_LOGI(TAG_STA, "Doing FTM");
  139.      //esp_task_wdt_reset();
  140.  
  141.     wifi_ftm_initiator_cfg_t ftmi_cfg = {
  142.         .frm_count = 16,
  143.         .burst_period = 2,
  144.     };
  145.  
  146.     if (ap_record) {
  147.         ESP_LOGI(TAG_STA,"Starting FTM with " MACSTR " on channel %d\n", MAC2STR(ap_record->bssid),ap_record->primary);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
  148.         memcpy(ftmi_cfg.resp_mac, ap_record->bssid, 6);
  149.         ftmi_cfg.channel = ap_record->primary;
  150.     } else {
  151.         ESP_LOGE(TAG_STA, "NOT AP RECORD");
  152.         ESP_ERROR_CHECK(esp_event_post( END_SCAN_OR_FTM_EVENT, 0, NULL, 0,pdMS_TO_TICKS(100)));
  153.         return 0;
  154.     }
  155.  
  156.     if (ESP_OK != esp_wifi_ftm_initiate_session(&ftmi_cfg)) {
  157.         ESP_LOGE(TAG_STA, "Failed to start FTM session");
  158.         ESP_ERROR_CHECK(esp_event_post( END_SCAN_OR_FTM_EVENT, 0, NULL, 0,pdMS_TO_TICKS(100)));
  159.         return 0;
  160.     }
  161.  
  162.     return 0;
  163. }
  164.  
  165. static int proccess_next_anchor(){
  166.  
  167.     current_anchor+=1;
  168.     if (current_anchor>=num_anchors){
  169.         current_anchor = 0;
  170.     }
  171.  
  172.     ESP_LOGI(TAG_STA, "Proccess_next_anchor %d", current_anchor);
  173.     return do_ftm(&anchors[current_anchor]);
  174.  
  175. }
  176.  
  177. void initialise_wifi(void)
  178. {
  179.     static bool initialized = false;
  180.  
  181.     if (initialized) {
  182.         return;
  183.     }
  184.  
  185.     ESP_ERROR_CHECK(esp_netif_init());
  186.     wifi_event_group = xEventGroupCreate();
  187.     ftm_event_group = xEventGroupCreate();
  188.     ESP_ERROR_CHECK( esp_event_loop_create_default() );
  189.     wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  190.     ESP_ERROR_CHECK(esp_wifi_init(&cfg));
  191.     ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
  192.                     WIFI_EVENT_STA_CONNECTED,
  193.                     &wifi_connected_handler,
  194.                     NULL,
  195.                     NULL));
  196.     ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
  197.                     WIFI_EVENT_STA_DISCONNECTED,
  198.                     &disconnect_handler,
  199.                     NULL,
  200.                     NULL));
  201.     ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
  202.                     WIFI_EVENT_FTM_REPORT,
  203.                     &ftm_report_handler,
  204.                     NULL,
  205.                     NULL));
  206.     ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM) );
  207.     ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL) );
  208.     ESP_ERROR_CHECK(esp_wifi_start() );
  209.     initialized = true;
  210. }
  211.  
  212.  
  213. void app_main(void)
  214. {
  215.    
  216.     const TickType_t xTicksToWaitFTM = 500 / portTICK_PERIOD_MS;
  217.     esp_err_t ret = nvs_flash_init();
  218.    
  219.     if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
  220.         ESP_ERROR_CHECK(nvs_flash_erase());
  221.         ret = nvs_flash_init();
  222.     }
  223.     ESP_ERROR_CHECK( ret );
  224.  
  225.     initialise_wifi();
  226.  
  227.     num_anchors = 0;
  228.     current_anchor = -1;
  229.     wifi_perform_scan(NULL, false);
  230.  
  231.     for (;;){
  232.         proccess_next_anchor();
  233.         EventBits_t bits = xEventGroupWaitBits(ftm_event_group, FTM_REPORT_BIT | FTM_FAILURE_BIT,
  234.                                           pdFALSE, pdFALSE, xTicksToWaitFTM);
  235.        
  236.         if (bits & FTM_REPORT_BIT){  
  237.             free(g_ftm_report);
  238.             g_ftm_report = NULL;
  239.             g_ftm_report_num_entries = 0;
  240.             vTaskDelay(20);
  241.         } else if (bits & FTM_FAILURE_BIT){  
  242.             xEventGroupClearBits(ftm_event_group, FTM_FAILURE_BIT);
  243.        
  244.             g_ftm_report = NULL;
  245.             g_ftm_report_num_entries = 0;
  246.             //hard_restart();
  247.             //esp_restart();
  248.         } else {
  249.             //esp_restart();
  250.             //wifi_perform_scan(NULL, false);
  251.             vTaskDelay(20);
  252.  
  253.         }
  254.  
  255.         xEventGroupClearBits(ftm_event_group, FTM_REPORT_BIT);
  256.         //xEventGroupClearBits(ftm_event_group, FTM_FAILURE_BIT);
  257.         vTaskDelay(200);
  258.         //esp_task_wdt_reset();
  259.     }
  260. }

ESP_Sprite
Posts: 9757
Joined: Thu Nov 26, 2015 4:08 am

Re: FTM responder long term stability

Postby ESP_Sprite » Mon Nov 08, 2021 4:49 am

I don;t see anything obvious wrong in your code, but if you suspect a memory leak, a way to confirm it is to periodically print the return value of xPortGetFreeHeapSize()... if that consistently goes down, you may indeed have a leak on your hands.

Weigen Qiu
Posts: 11
Joined: Thu Jul 02, 2020 8:40 pm

Re: FTM responder long term stability

Postby Weigen Qiu » Mon Nov 08, 2021 5:52 am

ESP_Sprite wrote:
Mon Nov 08, 2021 4:49 am
I don;t see anything obvious wrong in your code, but if you suspect a memory leak, a way to confirm it is to periodically print the return value of xPortGetFreeHeapSize()... if that consistently goes down, you may indeed have a leak on your hands.
I am not concerned with a memory leak on the initiator side ( the attached code). Actually the problem is on the responder side (the responder not responding to a ftm request after some time), which means the memory leak might happens inside the wifi driver, not the app code.

User avatar
ESP_krzychb
Posts: 400
Joined: Sat Oct 01, 2016 9:05 am
Contact:

Re: FTM responder long term stability

Postby ESP_krzychb » Mon Nov 08, 2021 9:04 am

Weigen Qiu wrote: Does anyone have the same issue? and how should I resolve this issue?
Hi @Weigen Qiu, I suggest opening an issue on ESP-IDF GitHub and linking to https://github.com/espressif/esp-idf/issues/7702 that looks like a similar issue but for ESP32-S2.

Weigen Qiu
Posts: 11
Joined: Thu Jul 02, 2020 8:40 pm

Re: FTM responder long term stability

Postby Weigen Qiu » Mon Nov 08, 2021 3:02 pm

ESP_krzychb wrote:
Mon Nov 08, 2021 9:04 am
Weigen Qiu wrote: Does anyone have the same issue? and how should I resolve this issue?
Hi @Weigen Qiu, I suggest opening an issue on ESP-IDF GitHub and linking to https://github.com/espressif/esp-idf/issues/7702 that looks like a similar issue but for ESP32-S2.
Thanks ESP_krzychb, for pointing to the related issue. I think what I have experienced is very similar to the ftm rate limit behaviour of the wifi driver, which other people have reported.

Who is online

Users browsing this forum: Majestic-12 [Bot] and 387 guests