From dbe84b934757ce8ed78cf7840ff1b701f5657fe9 Mon Sep 17 00:00:00 2001 From: Memfault Inc Date: Tue, 31 Jan 2023 21:23:28 +0000 Subject: [PATCH] Memfault Firmware SDK 0.37.2 (Build 1352) --- CHANGES.md | 19 +++++++ VERSION | 4 +- components/include/memfault/version.h | 2 +- examples/esp32/README.md | 3 +- .../apps/memfault_demo_app/main/cmd_wifi.c | 36 ++++++++------ .../main/console_example_main.c | 26 +++++++--- .../common/memfault_platform_http_client.c | 5 +- ports/zephyr/common/memfault_platform_http.c | 23 +++++---- scripts/fw_build_id.py | 6 ++- scripts/memfault_gdb.py | 49 ++++++++++++------- scripts/mflt-build-id/pyproject.toml | 4 +- .../test_elf_file_helper.py | 2 +- .../tests_mflt_build_id/test_fw_build_id.py | 5 +- 13 files changed, 122 insertions(+), 62 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index e067fa952..4795b6550 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,22 @@ +### Changes between Memfault SDK 0.37.2 and SDK 0.37.1 - Jan 31, 2023 + +#### :chart_with_upwards_trend: Improvements + +- Zephyr: + - Support building with `CONFIG_POSIX_API=y` in the Zephyr port HTTP client +- ESP-IDF: + - Reduce the spamminess of the esp32 example app logging +- Update [`scripts/memfault_gdb.py`](scripts/memfault_gdb.py): + - When explicitly listing a region to insert into the coredump via + `memfault coredump --region x y`, now support parseable GDB expressions for + the range arguments instead of requiring integer values. Thanks to @alvarop + for this patch + [#43](https://github.com/memfault/memfault-firmware-sdk/pull/43) ! + - Use the `info all-registers` command when dumping registers, instead of the + deprecated `info registers all` command, which works better on certain + arch/monitor setups. Thanks to @alvarop for this patch + [#44](https://github.com/memfault/memfault-firmware-sdk/pull/44) ! + ### Changes between Memfault SDK 0.37.1 and SDK 0.37.0 - Jan 17, 2023 #### :chart_with_upwards_trend: Improvements diff --git a/VERSION b/VERSION index 85f370d9b..2c1d8b8ee 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ -BUILD ID: 1184 -GIT COMMIT: b60ef08d3 +BUILD ID: 1352 +GIT COMMIT: a083eca61 diff --git a/components/include/memfault/version.h b/components/include/memfault/version.h index e33b237ab..458d3ca38 100644 --- a/components/include/memfault/version.h +++ b/components/include/memfault/version.h @@ -19,7 +19,7 @@ typedef struct { uint8_t patch; } sMfltSdkVersion; -#define MEMFAULT_SDK_VERSION { .major = 0, .minor = 37, .patch = 1 } +#define MEMFAULT_SDK_VERSION { .major = 0, .minor = 37, .patch = 2 } #ifdef __cplusplus } diff --git a/examples/esp32/README.md b/examples/esp32/README.md index 0e8cd0c0c..97bd36f60 100644 --- a/examples/esp32/README.md +++ b/examples/esp32/README.md @@ -10,7 +10,8 @@ The Memfault SDK has been tested to be compatible with these versions of ESP-IDF: - v3.x release series -- v4.x release series through v4.4.2 +- v4.x release series + v5.x release series through v5.0 Other versions may be also be compatible but have not been verified by Memfault. diff --git a/examples/esp32/apps/memfault_demo_app/main/cmd_wifi.c b/examples/esp32/apps/memfault_demo_app/main/cmd_wifi.c index 9be22e2dc..7625a7fc7 100644 --- a/examples/esp32/apps/memfault_demo_app/main/cmd_wifi.c +++ b/examples/esp32/apps/memfault_demo_app/main/cmd_wifi.c @@ -75,11 +75,11 @@ static void event_handler(void *arg, esp_event_base_t event_base, if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) { esp_wifi_connect(); s_retry_num++; - ESP_LOGI(TAG, "retry to connect to the AP"); + ESP_LOGD(TAG, "retry to connect to the AP"); } else { xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); } - ESP_LOGI(TAG, "connect to the AP fail"); + ESP_LOGD(TAG, "connect to the AP fail"); } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); @@ -89,23 +89,27 @@ static void event_handler(void *arg, esp_event_base_t event_base, } bool wifi_join(const char *ssid, const char *pass) { - s_wifi_event_group = xEventGroupCreate(); + static bool one_time_init = false; + if (!one_time_init) { + one_time_init = true; - ESP_ERROR_CHECK(esp_netif_init()); + s_wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - esp_netif_create_default_wifi_sta(); + ESP_ERROR_CHECK(esp_netif_init()); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + esp_netif_create_default_wifi_sta(); - esp_event_handler_instance_t instance_any_id; - esp_event_handler_instance_t instance_got_ip; - ESP_ERROR_CHECK(esp_event_handler_instance_register( - WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, &instance_any_id)); - ESP_ERROR_CHECK(esp_event_handler_instance_register( - IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, &instance_got_ip)); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + esp_event_handler_instance_t instance_any_id; + esp_event_handler_instance_t instance_got_ip; + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, + &event_handler, NULL, &instance_any_id)); + ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, + &event_handler, NULL, &instance_got_ip)); + } wifi_config_t wifi_config = { .sta = { @@ -124,7 +128,7 @@ bool wifi_join(const char *ssid, const char *pass) { ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); - ESP_LOGI(TAG, "wifi_init_sta finished."); + ESP_LOGD(TAG, "wifi_init_sta finished."); /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or * connection failed for the maximum number of re-tries (WIFI_FAIL_BIT). The @@ -139,7 +143,7 @@ bool wifi_join(const char *ssid, const char *pass) { ESP_LOGI(TAG, "connected to ap SSID:%s ", ssid); return true; } else if (bits & WIFI_FAIL_BIT) { - ESP_LOGI(TAG, "Failed to connect to SSID:%s", pass); + ESP_LOGD(TAG, "Failed to connect to SSID:%s", pass); } else { ESP_LOGE(TAG, "UNEXPECTED EVENT"); } diff --git a/examples/esp32/apps/memfault_demo_app/main/console_example_main.c b/examples/esp32/apps/memfault_demo_app/main/console_example_main.c index b42ec7755..cdf246ff0 100644 --- a/examples/esp32/apps/memfault_demo_app/main/console_example_main.c +++ b/examples/esp32/apps/memfault_demo_app/main/console_example_main.c @@ -189,10 +189,10 @@ void memfault_esp_port_wifi_autojoin(void) { MEMFAULT_LOG_DEBUG("No WiFi credentials found"); return; } - MEMFAULT_LOG_INFO("Starting WiFi Autojoin ..."); + MEMFAULT_LOG_DEBUG("Starting WiFi Autojoin ..."); bool result = wifi_join(ssid, pass); if (!result) { - MEMFAULT_LOG_ERROR("Failed to join WiFi network"); + MEMFAULT_LOG_DEBUG("Failed to join WiFi network"); } } @@ -204,16 +204,26 @@ static void prv_poster_task(void *args) { const TickType_t delay_ms = (1000 * interval_sec) / portTICK_PERIOD_MS; MEMFAULT_LOG_INFO("Data poster task up and running every %" PRIu32 "s.", interval_sec); - while (true) { - MEMFAULT_LOG_DEBUG("Checking for memfault data to send"); - int err = memfault_esp_port_http_client_post_data(); - // if the check-in succeeded, set green, otherwise clear. - // gives a quick eyeball check that the app is alive and well - led_set_color((err == 0) ? kLedColor_Green : kLedColor_Red); + while (true) { + // count the number of times this task has run memfault_metrics_heartbeat_add(MEMFAULT_METRICS_KEY(PosterTaskNumSchedules), 1); + // attempt to autojoin wifi, if configured memfault_esp_port_wifi_autojoin(); + + // if connected, post any memfault data + if (memfault_esp_port_wifi_connected()) { + MEMFAULT_LOG_DEBUG("Checking for memfault data to send"); + int err = memfault_esp_port_http_client_post_data(); + // if the check-in succeeded, set green, otherwise clear. + // gives a quick eyeball check that the app is alive and well + led_set_color((err == 0) ? kLedColor_Green : kLedColor_Red); + } + + // check for OTA update prv_memfault_ota(); + + // sleep vTaskDelay(delay_ms); } } diff --git a/ports/esp_idf/memfault/common/memfault_platform_http_client.c b/ports/esp_idf/memfault/common/memfault_platform_http_client.c index 96fe4ae18..f1d520122 100644 --- a/ports/esp_idf/memfault/common/memfault_platform_http_client.c +++ b/ports/esp_idf/memfault/common/memfault_platform_http_client.c @@ -123,7 +123,10 @@ sMfltHttpClient *memfault_platform_http_client_create(void) { int memfault_platform_http_client_destroy(sMfltHttpClient *_client) { esp_http_client_handle_t client = (esp_http_client_handle_t)_client; - esp_err_t err = esp_http_client_cleanup(client); + esp_err_t err = esp_http_client_close(client); + if (err == ESP_OK) { + err = esp_http_client_cleanup(client); + } if (err == ESP_OK) { return 0; } diff --git a/ports/zephyr/common/memfault_platform_http.c b/ports/zephyr/common/memfault_platform_http.c index 4ad73fb25..8e1cfefc3 100644 --- a/ports/zephyr/common/memfault_platform_http.c +++ b/ports/zephyr/common/memfault_platform_http.c @@ -4,19 +4,13 @@ //! See License.txt for details //! -#include "memfault/ports/zephyr/http.h" -#include "memfault/ports/zephyr/root_cert_storage.h" - #include -#include -#include -#include - #include #include - -#include #include +#include +#include +#include #include #include "memfault/core/compiler.h" @@ -27,6 +21,17 @@ #include "memfault/http/root_certs.h" #include "memfault/http/utils.h" #include "memfault/panics/assert.h" +#include "memfault/ports/zephyr/http.h" +#include "memfault/ports/zephyr/root_cert_storage.h" + +#if defined(CONFIG_POSIX_API) + #include + #include + #include + #include +#else + #include +#endif #if defined(CONFIG_MEMFAULT_HTTP_USES_MBEDTLS) diff --git a/scripts/fw_build_id.py b/scripts/fw_build_id.py index 08a34f7df..726d49e56 100644 --- a/scripts/fw_build_id.py +++ b/scripts/fw_build_id.py @@ -18,7 +18,9 @@ # Released SDK: sys.path.insert(0, bundled_mflt_build_id_src_dir) -from mflt_build_id import * # noqa +from mflt_build_id import * # noqa: E402,F401,F403,M900 if __name__ == "__main__": - main() # noqa + from mflt_build_id import main # noqa: M900 + + main() diff --git a/scripts/memfault_gdb.py b/scripts/memfault_gdb.py index aaeb5c454..95f56e208 100644 --- a/scripts/memfault_gdb.py +++ b/scripts/memfault_gdb.py @@ -60,9 +60,9 @@ # Note: not using `requests` but using the built-in http.client instead, so # there will be no additional dependencies other than Python itself. try: - from httplib import HTTPConnection, HTTPSConnection # noqa: I251 - from Queue import Queue # noqa: I251 - from urlparse import urlparse, urlunparse # noqa: I251 + from httplib import HTTPConnection, HTTPSConnection + from Queue import Queue + from urlparse import urlparse, urlunparse except ImportError: from http.client import HTTPConnection, HTTPSConnection from queue import Queue @@ -145,7 +145,7 @@ def _pc_in_vector_table(register_list, exception_number, analytics_props): exc_handler, _ = _read_register(0x0 + vtor + (exception_number * 4)) exc_handler &= ~0x1 # Clear thumb bit return exc_handler == curr_pc - except Exception: # noqa + except Exception: analytics_props["pc_in_vtor_check_error"] = {"traceback": traceback.format_exc()} return False @@ -347,7 +347,7 @@ def get_current_registers(self, gdb_thread, analytics_props): try: for core_id in range(0, self.num_cores): result.append(self._read_registers(core_id, gdb_thread, analytics_props)) - except Exception: # noqa + except Exception: analytics_props["core_reg_collection_error"] = {"traceback": traceback.format_exc()} return result @@ -458,7 +458,7 @@ def add_platform_specific_sections(self, cd_writer, inferior, analytics_props): section.data = inferior.read_memory(section.addr, section.size) cd_writer.add_section(section) analytics_props["{}_ok".format(short_name)] = True - except Exception: # noqa + except Exception: analytics_props["{}_collection_error".format(short_name)] = { "traceback": traceback.format_exc() } @@ -466,7 +466,7 @@ def add_platform_specific_sections(self, cd_writer, inferior, analytics_props): try: cd_writer.armv67_mpu = self._try_collect_mpu_settings() print("Collected MPU config") - except Exception: # noqa + except Exception: analytics_props["mpu_collection_error"] = {"traceback": traceback.format_exc()} def guess_ram_regions(self, elf_sections): @@ -489,9 +489,19 @@ def get_current_registers(self, gdb_thread, analytics_props): # best way. Call this, rip out the first element in each row...that's the register name # - # NOTE: We use the "all" argument below because on some versions of gdb "msp, psp, etc" are not considered part of them - # core set. This will also dump all the fpu registers which we don't collect but thats fine - info_reg_all_list = gdb.execute("info reg all", to_string=True) + # NOTE: Using the 'all-registers' command below, because on some + # versions of gdb "msp, psp, etc" are not considered part of them core + # set. This will also dump all the fpu registers which we don't collect + # but thats fine. 'info all-registers' is the preferred command, where + # 'info reg [all]' is arch-specific, see: + # https://sourceware.org/gdb/onlinedocs/gdb/Registers.html + try: + info_reg_all_list = gdb.execute("info all-registers", to_string=True) + except gdb.error: + # Some versions of gdb don't support 'all' and return an error, fall + # back to 'info reg' + info_reg_all_list = gdb.execute("info reg", to_string=True) + return (lookup_registers_from_list(self, info_reg_all_list, analytics_props),) @@ -539,7 +549,7 @@ def _try_read_register(arch, frame, lookup_name, register_list, analytics_props, _add_reg_collection_error_analytic( arch, analytics_props, lookup_name, " value" ) - except Exception: # noqa + except Exception: _add_reg_collection_error_analytic( arch, analytics_props, lookup_name, traceback.format_exc() ) @@ -600,7 +610,7 @@ def _search_list_for_alt_name(reg, found_registers): # if we can't patch the registers, we'll just fallback to the active state try: check_and_patch_reglist_for_fault(register_list, analytics_props) - except Exception: # noqa + except Exception: analytics_props["fault_register_recover_error"] = {"traceback": traceback.format_exc()} pass @@ -786,7 +796,7 @@ def _http(method, base_uri, path, headers=None, body=None): body = response.read() try: json_body = loads(body) - except Exception: # noqa + except Exception: json_body = None conn.close() return status, reason, json_body @@ -1063,7 +1073,7 @@ def settings_load(): try: with open(MEMFAULT_CONFIG.json_path, "rb") as f: return load(f) - except Exception: # noqa + except Exception: return {} @@ -1438,7 +1448,10 @@ def parse_args(self, unicode_args, config): ) def _auto_int(x): - return int(x, 0) + try: + return int(x, 0) + except ValueError: + return int(gdb.parse_and_eval(x)) parser.add_argument( "--region", @@ -1696,7 +1709,7 @@ def run(self): # Throttle a bit sleep(0.2) - except Exception: # noqa + except Exception: pass # Never fail due to analytics requests erroring out @@ -1711,12 +1724,12 @@ def _track_script_sourced(): from platform import mac_ver mac_version = mac_ver()[0] - except Exception: # noqa + except Exception: mac_version = "" try: gdb_version = gdb.execute("show version", to_string=True).strip().split("\n")[0] - except Exception: # noqa + except Exception: gdb_version = "" ANALYTICS.track( diff --git a/scripts/mflt-build-id/pyproject.toml b/scripts/mflt-build-id/pyproject.toml index 1f05ac471..24f04f20b 100644 --- a/scripts/mflt-build-id/pyproject.toml +++ b/scripts/mflt-build-id/pyproject.toml @@ -12,7 +12,7 @@ packages = [ mflt_build_id = 'mflt_build_id:main' [tool.poetry.dependencies] -python = "^3.6" +python = "^3.6" # must match memfault-cli pyelftools = ">=0.26,<=0.28" [tool.poetry.dev-dependencies] @@ -23,7 +23,7 @@ wasmer = "0.3.0" [tool.black] line-length = 100 -target-version = ['py38'] +target-version = ['py36'] include = '\.pyi?$' [tool.isort] diff --git a/scripts/mflt-build-id/tests_mflt_build_id/test_elf_file_helper.py b/scripts/mflt-build-id/tests_mflt_build_id/test_elf_file_helper.py index 0fc752811..99f87910e 100644 --- a/scripts/mflt-build-id/tests_mflt_build_id/test_elf_file_helper.py +++ b/scripts/mflt-build-id/tests_mflt_build_id/test_elf_file_helper.py @@ -15,7 +15,7 @@ script_dir = os.path.dirname(test_dir) sys.path.append(script_dir) -from mflt_build_id import ELFFileHelper # noqa isort:skip +from mflt_build_id import ELFFileHelper # noqa: E402 # isort:skip class TestELFFileHelper: diff --git a/scripts/mflt-build-id/tests_mflt_build_id/test_fw_build_id.py b/scripts/mflt-build-id/tests_mflt_build_id/test_fw_build_id.py index 1e0514df6..41146e452 100644 --- a/scripts/mflt-build-id/tests_mflt_build_id/test_fw_build_id.py +++ b/scripts/mflt-build-id/tests_mflt_build_id/test_fw_build_id.py @@ -17,7 +17,10 @@ sys.path.append(script_dir) -from mflt_build_id import BuildIdInspectorAndPatcher, MemfaultBuildIdTypes # noqa isort:skip +from mflt_build_id import ( # noqa: E402 # isort:skip + BuildIdInspectorAndPatcher, + MemfaultBuildIdTypes, +) @pytest.fixture()