Skip to content

Commit

Permalink
refresh app + update Memfault SDK to 1.11.4
Browse files Browse the repository at this point in the history
  • Loading branch information
noahp committed Sep 12, 2024
1 parent 26d2511 commit 5dba719
Show file tree
Hide file tree
Showing 25 changed files with 1,258 additions and 236 deletions.
54 changes: 36 additions & 18 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,33 @@ if(DEFINED IDF_VERSION_MAJOR)
endif()
endif()

# Look for the Memfault SDK in a subdirectory first
get_filename_component(memfault_firmare_sdk_dir third-party/memfault-firmware-sdk ABSOLUTE)
if(NOT EXISTS ${memfault_firmare_sdk_dir})
get_filename_component(memfault_firmare_sdk_dir ../../../../ ABSOLUTE)
# Look for the Memfault SDK in a subdirectory first, when this app is used
# standalone (not from within the Memfault SDK)
get_filename_component(memfault_firmware_sdk_dir third-party/memfault-firmware-sdk ABSOLUTE)
if(NOT EXISTS ${memfault_firmware_sdk_dir})
get_filename_component(memfault_firmware_sdk_dir ../../../../ ABSOLUTE)
endif()
include(${memfault_firmare_sdk_dir}/ports/esp_idf/memfault.cmake)
include(${memfault_firmware_sdk_dir}/ports/esp_idf/memfault.cmake)

# NOTE: This include also applies global compiler options, make sure
# this happens first before defining other targets!
# The esp-idf project() macro creates a project_name.elf target:
include($ENV{IDF_PATH}/tools/cmake/project.cmake)

# Wrap the mbedtls netif read/write functions, for instrumentation.
# These MUST be before the project() function below, or they are ignored
if(IDF_VERSION_MAJOR VERSION_GREATER_EQUAL 4)
idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=mbedtls_net_send,--wrap=mbedtls_net_recv" APPEND)
endif()

project(${PROJECT_NAME})

# Enable a compilation error if any deprecated APIs are used. This helps detect
# bleeding edge changes in the ESP-IDF.
if (IDF_VERSION_MAJOR VERSION_GREATER_EQUAL 5)
idf_build_set_property(COMPILE_OPTIONS "-Werror=deprecated-declarations" APPEND)
endif()

# Check for invalid partition table configurations
if (
CONFIG_APP_MEMFAULT_TRANSPORT_HTTP AND
Expand All @@ -50,16 +64,20 @@ if (INVALID_PARTITION_TABLE)
)
endif()

# Add the Memfault Build ID so each build can have a unique version.
set(IDF_PROJECT_EXECUTABLE ${PROJECT_NAME}.elf)
add_custom_command(TARGET ${IDF_PROJECT_EXECUTABLE}
POST_BUILD
# Compute and insert the build id
COMMAND python ${memfault_firmare_sdk_dir}/scripts/fw_build_id.py ${IDF_PROJECT_EXECUTABLE}
# Save a copy of the ELF that includes the 'log_fmt' section
BYPRODUCTS ${IDF_PROJECT_EXECUTABLE}.memfault_log_fmt
COMMAND ${CMAKE_COMMAND} -E copy ${IDF_PROJECT_EXECUTABLE} ${IDF_PROJECT_EXECUTABLE}.memfault_log_fmt
COMMAND ${CMAKE_COMMAND} -E echo "*** NOTE: the symbol file to upload to app.memfault.com is ${IDF_PROJECT_EXECUTABLE}.memfault_log_fmt ***"
# Remove the 'log_fmt' compact log section, which confuses elf2image
COMMAND ${CMAKE_OBJCOPY} --remove-section log_fmt ${IDF_PROJECT_EXECUTABLE}
)
if (CONFIG_MEMFAULT)
# Add the Memfault Build ID so each build can have a unique version.
set(IDF_PROJECT_EXECUTABLE ${PROJECT_NAME}.elf)
add_custom_command(TARGET ${IDF_PROJECT_EXECUTABLE}
POST_BUILD
# Compute and insert the build id
COMMAND python ${memfault_firmware_sdk_dir}/scripts/fw_build_id.py ${IDF_PROJECT_EXECUTABLE}
# Save a copy of the ELF that includes the 'log_fmt' section
BYPRODUCTS ${IDF_PROJECT_EXECUTABLE}.memfault_log_fmt
# Compress debug sections; this reduces the elf file size from ~10MB -> ~4.8MB
COMMAND ${CMAKE_OBJCOPY} --compress-debug-sections ${IDF_PROJECT_EXECUTABLE}
COMMAND ${CMAKE_COMMAND} -E copy ${IDF_PROJECT_EXECUTABLE} ${IDF_PROJECT_EXECUTABLE}.memfault_log_fmt
COMMAND ${CMAKE_COMMAND} -E echo "*** NOTE: the symbol file to upload to app.memfault.com is ${IDF_PROJECT_EXECUTABLE}.memfault_log_fmt ***"
# Remove the 'log_fmt' compact log section, which confuses elf2image
COMMAND ${CMAKE_OBJCOPY} --remove-section log_fmt ${IDF_PROJECT_EXECUTABLE}
)
endif() # NOT CONFIG_MEMFAULT_DISABLE
64 changes: 36 additions & 28 deletions main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,41 +1,49 @@
list(APPEND
COMPONENT_SRCS
cmd_app.c
cmd_system.c
console_example_main.c
button.c
led.c
main.c
)

if (CONFIG_APP_MEMFAULT_TRANSPORT_HTTP)
list(APPEND COMPONENT_SRCS app_memfault_transport_http.c)
elseif(CONFIG_APP_MEMFAULT_TRANSPORT_MQTT)
list(APPEND COMPONENT_SRCS app_memfault_transport_mqtt.c)
endif()

# the 'cmd_wifi.c' implementation is different for ESP-IDF v5+
if("${IDF_VERSION_MAJOR}" VERSION_GREATER_EQUAL 5)
if (CONFIG_MEMFAULT)
list(APPEND
COMPONENT_SRCS
cmd_wifi.c
cmd_app.c
cmd_system.c
ota_session_metrics.c
)
else()
list(APPEND
COMPONENT_SRCS
cmd_wifi_legacy.c
)
endif()

# include settings.c only on idf >= 4
if("${IDF_VERSION_MAJOR}" VERSION_GREATER_EQUAL 4)
list(APPEND
COMPONENT_SRCS
settings.c
if (CONFIG_APP_MEMFAULT_TRANSPORT_HTTP)
list(APPEND COMPONENT_SRCS app_memfault_transport_http.c)
elseif(CONFIG_APP_MEMFAULT_TRANSPORT_MQTT)
list(APPEND COMPONENT_SRCS app_memfault_transport_mqtt.c)
endif()

# the 'cmd_wifi.c' implementation is different for ESP-IDF v5+
if("${IDF_VERSION_MAJOR}" VERSION_GREATER_EQUAL 5)
list(APPEND
COMPONENT_SRCS
cmd_wifi.c
)
else()
list(APPEND
COMPONENT_SRCS
cmd_wifi_legacy.c
)
endif()

# include settings.c only on idf >= 4
if("${IDF_VERSION_MAJOR}" VERSION_GREATER_EQUAL 4)
list(APPEND
COMPONENT_SRCS
settings.c
)
endif()

set(COMPONENT_ADD_INCLUDEDIRS
.
config
)
endif()

set(COMPONENT_ADD_INCLUDEDIRS
.
memfault
)

register_component()
25 changes: 22 additions & 3 deletions main/Kconfig.projbuild
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,25 @@ menu "Memfault App Configuration"

config STORE_HISTORY
bool "Store command history in flash"
default y
default n
help
Linenoise line editing library provides functions to save and load
command history. If this option is enabled, initalizes a FAT filesystem
command history. If this option is enabled, initializes a FAT filesystem
and uses it to store command history.
Note that this adds a ~22kB heap allocation on system boot.

config MEMFAULT_APP_OTA
bool "Enable automatic periodic check+update for OTA"
default y
depends on MEMFAULT
help
Enables the Memfault OTA subsystem. This will periodically check for
updates and apply them if available.

config MEMFAULT_APP_WIFI_AUTOJOIN
bool "Enable automatic WiFi connection"
default y
depends on MEMFAULT
help
Automatically join if credentials are configured.

Expand All @@ -30,6 +33,7 @@ choice APP_MEMFAULT_TRANSPORT
config APP_MEMFAULT_TRANSPORT_MQTT
bool "MQTT"
select MQTT_PROTOCOL_5
depends on !MEMFAULT_HTTP_PERIODIC_UPLOAD
endchoice

if APP_MEMFAULT_TRANSPORT_MQTT
Expand Down Expand Up @@ -78,7 +82,22 @@ config BLINK_GPIO
GPIO number (IOxx) to blink on and off or the RMT signal for the addressable LED.
Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to blink.

# esp32c3 specific settings
config BUTTON_GPIO
int "Input pin for the EN button on the dev board"
# https://dl.espressif.com/dl/schematics/esp32_devkitc_v4_sch.pdf
# https://dl.espressif.com/dl/schematics/esp-idf/SCH_ESP32-S2-DEVKITC-1_V1_20220817.pdf
# https://dl.espressif.com/dl/schematics/SCH_ESP32-S3-DevKitC-1_V1.1_20221130.pdf
default 0 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
# https://dl.espressif.com/dl/schematics/SCH_ESP32-C3-DEVKITC-02_V1_1_20210126A.pdf
# https://dl.espressif.com/dl/schematics/SCH_ESP32-C3-DEVKITM-1_V1_20200915A.pdf
# https://docs.espressif.com/projects/esp-dev-kits/en/latest/_static/esp32-c6-devkitc-1/schematics/esp32-c6-devkitc-1-schematics_v1.4.pdf
default 9 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C6
default 0
help
GPIO pin number for the BOOT button. Used to trigger a crash for testing.


# esp32c3/c6 specific settings
if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C6
# Default optimize for size due to increase in binary size
# This can be changed in root -> Compiler Options
Expand Down
2 changes: 1 addition & 1 deletion main/app_memfault_transport_http.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include "app_memfault_transport.h"
#include "memfault/esp_port/http_client.h"

void app_memfault_transport_init(void) {}
void app_memfault_transport_init(void) { }

int app_memfault_transport_send_chunks(void) {
return memfault_esp_port_http_client_post_data();
Expand Down
18 changes: 9 additions & 9 deletions main/app_memfault_transport_mqtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ static esp_mqtt_client_handle_t s_mqtt_client = NULL;
static esp_mqtt5_publish_property_config_t s_publish_property = {
.topic_alias = 1,
};
static char s_topic_string[128] = {0};
static char s_topic_string[128] = { 0 };

static uint8_t s_chunk_data[1024] = {0};
static uint8_t s_chunk_data[1024] = { 0 };

static void mqtt_event_handler(MEMFAULT_UNUSED void *handler_args,
MEMFAULT_UNUSED esp_event_base_t base,
Expand Down Expand Up @@ -59,7 +59,7 @@ static void prv_close_client(void) {
if (rv) {
ESP_LOGW(TAG, "Failed to destroy client[%d]", rv);
}
memfault_metrics_heartbeat_timer_stop(MEMFAULT_METRICS_KEY(mqtt_conn_uptime));
MEMFAULT_METRIC_TIMER_STOP(mqtt_conn_uptime);

s_mqtt_client = NULL;
}
Expand Down Expand Up @@ -91,14 +91,14 @@ static int prv_create_client(void) {
rv = xSemaphoreTake(s_mqtt_connected, (1000 * 10) / portTICK_PERIOD_MS);
if (rv != pdTRUE) {
ESP_LOGE(TAG, "MQTT client failed to connect[%d]", rv);
memfault_metrics_heartbeat_timer_start(MEMFAULT_METRICS_KEY(mqtt_conn_downtime));
MEMFAULT_METRIC_TIMER_START(mqtt_conn_downtime);
prv_close_client();
return -1;
}

// Update connection metrics when connected
memfault_metrics_heartbeat_timer_stop(MEMFAULT_METRICS_KEY(mqtt_conn_downtime));
memfault_metrics_heartbeat_timer_start(MEMFAULT_METRICS_KEY(mqtt_conn_uptime));
MEMFAULT_METRIC_TIMER_STOP(mqtt_conn_downtime);
MEMFAULT_METRIC_TIMER_START(mqtt_conn_uptime);

// Set topic alias before publishing
rv = esp_mqtt5_client_set_publish_property(s_mqtt_client, &s_publish_property);
Expand All @@ -109,7 +109,7 @@ static int prv_create_client(void) {
}

static const char *prv_get_device_serial(void) {
sMemfaultDeviceInfo info = {0};
sMemfaultDeviceInfo info = { 0 };
memfault_platform_get_device_info(&info);
return info.device_serial;
}
Expand Down Expand Up @@ -161,8 +161,8 @@ int app_memfault_transport_send_chunks(void) {
break;
}

memfault_metrics_heartbeat_add(MEMFAULT_METRICS_KEY(mqtt_publish_bytes), chunk_size);
memfault_metrics_heartbeat_add(MEMFAULT_METRICS_KEY(mqtt_publish_count), 1);
MEMFAULT_METRIC_ADD(mqtt_publish_bytes, chunk_size);
MEMFAULT_METRIC_ADD(mqtt_publish_count, 1);
ESP_LOGD(TAG, "chunk[%d], len[%zu] published to %s", rv, chunk_size, s_topic_string);
}

Expand Down
86 changes: 86 additions & 0 deletions main/button.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//! @file
//!
//! Copyright (c) Memfault, Inc.
//! See License.txt for details
//!
//! Button setup and handling

#include "button.h"

#include "driver/gpio.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "esp_system.h"

static const char *TAG = "button";

static void IRAM_ATTR prv_gpio_isr_handler(void *arg) {
uint32_t gpio_num = (uint32_t)arg;

// dereference a null point to trigger a crash
volatile uint32_t *ptr = NULL;
*ptr = gpio_num;
}

// The flex glitch filter is only available on 5.1. Skip it for earlier SDKs.
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)
#include "driver/gpio_filter.h"
static void prv_button_glitch_filter_enable(void) {
#if SOC_GPIO_FLEX_GLITCH_FILTER_NUM > 0
gpio_glitch_filter_handle_t filter;
gpio_flex_glitch_filter_config_t filter_cfg = {
.clk_src = GLITCH_FILTER_CLK_SRC_DEFAULT,
.gpio_num = CONFIG_BUTTON_GPIO,
.window_thres_ns = 500,
.window_width_ns = 500,
};
esp_err_t err = gpio_new_flex_glitch_filter(&filter_cfg, &filter);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to create glitch filter: %s", esp_err_to_name(err));
return;
}

err = gpio_glitch_filter_enable(filter);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to enable glitch filter: %s", esp_err_to_name(err));
return;
}
#endif
}
#else // ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)
static void prv_button_glitch_filter_enable(void) {
// No-op
}
#endif // ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)

void button_setup(void) {
// configure the button as an input
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_NEGEDGE,
.mode = GPIO_MODE_INPUT,
.pin_bit_mask = 1ULL << CONFIG_BUTTON_GPIO,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.pull_up_en = GPIO_PULLUP_ENABLE,
};
esp_err_t err = gpio_config(&io_conf);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to configure button: %s", esp_err_to_name(err));
return;
}

prv_button_glitch_filter_enable();

// install gpio isr service
err = gpio_install_isr_service(0);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to install gpio isr service: %s", esp_err_to_name(err));
return;
}

// install isr handler for specific gpio pin
err = gpio_isr_handler_add(CONFIG_BUTTON_GPIO, prv_gpio_isr_handler, (void *)CONFIG_BUTTON_GPIO);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to add isr handler for button: %s", esp_err_to_name(err));
return;
}
}
10 changes: 10 additions & 0 deletions main/button.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//! @file
//!
//! Copyright (c) Memfault, Inc.
//! See License.txt for details
//!
//! Button setup and handling

#pragma once

void button_setup(void);
Loading

0 comments on commit 5dba719

Please sign in to comment.