Skip to content

Commit

Permalink
Memfault Firmware SDK 1.4.3 (Build 4437)
Browse files Browse the repository at this point in the history
  • Loading branch information
Memfault Inc committed Nov 9, 2023
1 parent 50f0e19 commit 2e3d5e5
Show file tree
Hide file tree
Showing 31 changed files with 388 additions and 64 deletions.
74 changes: 73 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,77 @@
# Memfault Firmware SDK Changelog

## [1.4.3] - 2023-11-08

### :rocket: New Features

- General:

- Add a new streamlined Metrics setter API:

- `MEMFAULT_HEARTBEAT_SET_SIGNED(key_name, signed_value)`
- `MEMFAULT_HEARTBEAT_SET_UNSIGNED(key_name, unsigned_value)`
- `MEMFAULT_HEARTBEAT_SET_STRING(key_name, value)`
- `MEMFAULT_HEARTBEAT_TIMER_START(key_name)`
- `MEMFAULT_HEARTBEAT_TIMER_STOP(key_name)`
- `MEMFAULT_HEARTBEAT_ADD(key_name, amount)`

These APIs can be used in place of the original APIs:

- `memfault_metrics_heartbeat_set_signed(MEMFAULT_METRICS_KEY(key_name), signed_value)`
- `memfault_metrics_heartbeat_set_unsigned(MEMFAULT_METRICS_KEY(key_name), unsigned_value)`
- `memfault_metrics_heartbeat_set_string(MEMFAULT_METRICS_KEY(key_name), value)`
- `memfault_metrics_heartbeat_timer_start(MEMFAULT_METRICS_KEY(key_name))`
- `memfault_metrics_heartbeat_timer_stop(MEMFAULT_METRICS_KEY(key_name))`
- `memfault_metrics_heartbeat_add(MEMFAULT_METRICS_KEY(key_name), amount)`

Saving some typing!

- Add the ability to compute FreeRTOS task stack high watermarks when storing
coredumps. This is useful only if the entire RAM (`.data` + `.bss`) cannot
be saved in the coredump. The feature is opt-in with the config flag
`#define MEMFAULT_COREDUMP_COMPUTE_THREAD_STACK_USAGE 1`.

- Add a `heartbeat` command to the [core demo cli](components/demo). This
behaves the same as the commands of the same name already present in the
Zephyr + ESP-IDF port.

- Add a `test_cassert` command to the core demo cli. This command executes a C
stdlib `<assert.h>``assert(0)` call. For platforms that do not implement a
`assert()` handler, a config flag `MEMFAULT_DEMO_DISABLE_CASSERT` can be
defined to `0` to disable the command.

- ESP-IDF:

- Add a new out-of-box metric, `wifi_ap_oui`, which will record the associated
AP's Organizationally Unique Identifier (OUI) in the Memfault heartbeat.

### :chart_with_upwards_trend: Improvements

- General:

- Disable a warning emitted by the ARM C Compiler v5
(`#188-D: enumerated type mixed with another type`) when initializing a
structure in
[`components/core/src/memfault_log.c`:314](https://github.com/memfault/memfault-firmware-sdk/blob/1.4.3/components/core/src/memfault_log.c#L313).

- Improve the quality of Assert backtraces when using the ARM C Compiler v5.
Certain frames in the assert call stack were missing link register
inforation, due to compiler optimizations based on the `noreturn` and
unreachable compiler hints. These hints have been removed for `armcc`, which
should permit full stack unwinding for Assert coredumps generated from
builds on that toolchain.

- Perform an update of the timer when calling the
`memfault_metrics_heartbeat_timer_read()` debug function. Fixes
[#65](https://github.com/memfault/memfault-firmware-sdk/pull/65). Thanks to
@LuskeyNoah for providing this fix!

- ESP-IDF:

- Fix a missing piece enabling the "zero-config" integration (originally added
in `1.4.0`)- the `memfault_platform_port.h` file was still incorrectly
required. This is now fixed.

## [1.4.2] - 2023-11-02

### :chart_with_upwards_trend: Improvements
Expand Down Expand Up @@ -80,7 +152,7 @@

- Add a new Kconfig flag, `MEMFAULT_COREDUMP_STORAGE_MAX_SIZE`, which can be
used to set the Memfault SDK's built-in
[ESP-IDF coredump storage implementation](sdk/embedded/ports/esp_idf/memfault/common/memfault_platform_coredump.c)
[ESP-IDF coredump storage implementation](https://github.com/memfault/memfault-firmware-sdk/blob/master/ports/esp_idf/memfault/common/memfault_platform_coredump.c)
to artificially limit the maximum coredump storage size. This is useful for
situations where the default `memfault_platform_coredump_get_regions()`
function is still desirable, but the coredump maximum size needs to be
Expand Down
6 changes: 3 additions & 3 deletions VERSION
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
BUILD ID: 4292
GIT COMMIT: 7f46de743
VERSION: 1.4.2
BUILD ID: 4437
GIT COMMIT: 3453c1402
VERSION: 1.4.3
11 changes: 11 additions & 0 deletions components/core/src/memfault_log.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,10 +314,21 @@ void memfault_log_export_logs(void) {
#pragma diag_push
#pragma diag_remark 190
#endif
#if defined(__CC_ARM)
#pragma push
// This armcc diagnostic is technically violating the C standard, which
// _explicitly_ requires enums to be type-equivalent to ints. See ISO/IEC
// 9899:TC3 6.2.5.16, and specifically 6.4.4.3, which states: "An
// identifier declared as an enumeration constant has type int."
#pragma diag_suppress 188 // enumerated type mixed with another type
#endif
sMemfaultLog log = {0};
#if defined(__TI_ARM__)
#pragma diag_pop
#endif
#if defined(__CC_ARM)
#pragma pop
#endif

const bool log_found = memfault_log_read(&log);
if (!log_found) {
Expand Down
7 changes: 7 additions & 0 deletions components/demo/src/memfault_demo_shell_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ int memfault_demo_cli_cmd_heartbeat_dump(MEMFAULT_UNUSED int argc, MEMFAULT_UNUS
return 0;
}

int memfault_demo_cli_cmd_heartbeat(MEMFAULT_UNUSED int argc, MEMFAULT_UNUSED char *argv[]) {
memfault_metrics_heartbeat_debug_trigger();
return 0;
}

static const sMemfaultShellCommand s_memfault_shell_commands[] = {
{"clear_core", memfault_demo_cli_cmd_clear_core, "Clear an existing coredump"},
{"drain_chunks", memfault_demo_drain_chunk_data,
Expand All @@ -58,11 +63,13 @@ static const sMemfaultShellCommand s_memfault_shell_commands[] = {
{"coredump_size", memfault_demo_cli_cmd_coredump_size, "Print the coredump storage capacity"},
{"heartbeat_dump", memfault_demo_cli_cmd_heartbeat_dump,
"Dump current Memfault metrics heartbeat state"},
{"heartbeat", memfault_demo_cli_cmd_heartbeat, "Trigger a heartbeat"},
//
// Test commands for validating SDK functionality: https://mflt.io/mcu-test-commands
//

{"test_assert", memfault_demo_cli_cmd_assert, "Trigger memfault assert"},
{"test_cassert", memfault_demo_cli_cmd_cassert, "Trigger C assert"},

#if MEMFAULT_COMPILER_ARM_CORTEX_M
{"test_busfault", memfault_demo_cli_cmd_busfault, "Trigger a busfault"},
Expand Down
19 changes: 19 additions & 0 deletions components/demo/src/panics/memfault_demo_panics.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@
#include "memfault/panics/platform/coredump.h"
#include "memfault_demo_cli_aux_private.h"

// Allow opting out of the cassert demo. Some platforms may not have a libc
// assert implementation.
#if !defined(MEMFAULT_DEMO_DISABLE_CASSERT)
#include <assert.h>
#define MEMFAULT_DEMO_DISABLE_CASSERT 0
#endif

MEMFAULT_NO_OPT
static void do_some_work_base(char *argv[]) {
// An assert that is guaranteed to fail. We perform
Expand Down Expand Up @@ -131,6 +138,18 @@ int memfault_demo_cli_cmd_assert(int argc, char *argv[]) {
return -1;
}

int memfault_demo_cli_cmd_cassert(int argc, char *argv[]) {
(void)argc, (void)argv;

#if MEMFAULT_DEMO_DISABLE_CASSERT
MEMFAULT_LOG_ERROR("C assert demo disabled");
#else
assert(0);
#endif

return -1;
}

#if MEMFAULT_COMPILER_ARM_CORTEX_M

int memfault_demo_cli_cmd_hardfault(MEMFAULT_UNUSED int argc, MEMFAULT_UNUSED char *argv[]) {
Expand Down
7 changes: 4 additions & 3 deletions components/include/memfault/core/platform/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ int memfault_platform_boot(void);
//! Invoked after memfault fault handling has run.
//!
//! The platform should do any final cleanup and reboot the system
#if defined(__ICCARM__)
//! IAR will optimize away link register stores from callsites which makes it
//! impossible for a reliable backtrace to be resolved so we don't use the NORETURN attribute
#if defined(__ICCARM__) || defined(__CC_ARM)
//! IAR and armcc will optimize away link register stores from callsites, which
//! makes it impossible for a reliable backtrace to be resolved, so for those
//! compilers don't apply the NORETURN attribute
#else
MEMFAULT_NORETURN
#endif
Expand Down
6 changes: 6 additions & 0 deletions components/include/memfault/demo/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ int memfault_demo_cli_cmd_prefetchabort(int argc, char *argv[]);
//! Command which will generate an assert
int memfault_demo_cli_cmd_assert(int argc, char *argv[]);

//! Command which will generate a libc assert()
int memfault_demo_cli_cmd_cassert(int argc, char *argv[]);

//! Command to exercise the MEMFAULT_TRACE_EVENT API, capturing a
//! Trace Event with the error reason set to "MemfaultDemoCli_Error".
int memfault_demo_cli_cmd_trace_event_capture(int argc, char *argv[]);
Expand Down Expand Up @@ -114,6 +117,9 @@ int memfault_demo_cli_cmd_export(int argc, char *argv[]);
//! Print current heartbeat metrics
int memfault_demo_cli_cmd_heartbeat_dump(int argc, char *argv[]);

//! Trigger a heartbeat
int memfault_demo_cli_cmd_heartbeat(int argc, char *argv[]);

#ifdef __cplusplus
}
#endif
14 changes: 14 additions & 0 deletions components/include/memfault/metrics/metrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,20 @@ int memfault_metrics_heartbeat_timer_stop(MemfaultMetricId key);
//! @note The metric must be of type kMemfaultMetricType_Unsigned or kMemfaultMetricType_Signed
int memfault_metrics_heartbeat_add(MemfaultMetricId key, int32_t amount);

//! Alternate API that includes the 'MEMFAULT_METRICS_KEY()' expansion
#define MEMFAULT_HEARTBEAT_SET_SIGNED(key_name, signed_value) \
memfault_metrics_heartbeat_set_signed(MEMFAULT_METRICS_KEY(key_name), signed_value)
#define MEMFAULT_HEARTBEAT_SET_UNSIGNED(key_name, unsigned_value) \
memfault_metrics_heartbeat_set_unsigned(MEMFAULT_METRICS_KEY(key_name), unsigned_value)
#define MEMFAULT_HEARTBEAT_SET_STRING(key_name, value) \
memfault_metrics_heartbeat_set_string(MEMFAULT_METRICS_KEY(key_name), value)
#define MEMFAULT_HEARTBEAT_TIMER_START(key_name) \
memfault_metrics_heartbeat_timer_start(MEMFAULT_METRICS_KEY(key_name))
#define MEMFAULT_HEARTBEAT_TIMER_STOP(key_name) \
memfault_metrics_heartbeat_timer_stop(MEMFAULT_METRICS_KEY(key_name))
#define MEMFAULT_HEARTBEAT_ADD(key_name, amount) \
memfault_metrics_heartbeat_add(MEMFAULT_METRICS_KEY(key_name), amount)

//! For debugging purposes: prints the current heartbeat values using
//! MEMFAULT_LOG_DEBUG(). Before printing, any active timer values are computed.
//! Other metrics will print the current values. This can be called from the
Expand Down
4 changes: 2 additions & 2 deletions components/include/memfault/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ typedef struct {
uint8_t patch;
} sMfltSdkVersion;

#define MEMFAULT_SDK_VERSION { .major = 1, .minor = 4, .patch = 2 }
#define MEMFAULT_SDK_VERSION_STR "1.4.2"
#define MEMFAULT_SDK_VERSION { .major = 1, .minor = 4, .patch = 3 }
#define MEMFAULT_SDK_VERSION_STR "1.4.3"

#ifdef __cplusplus
}
Expand Down
1 change: 1 addition & 0 deletions components/metrics/src/memfault_metrics.c
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,7 @@ int memfault_metrics_heartbeat_timer_read(MemfaultMetricId key, uint32_t *read_v
memfault_lock();
{
union MemfaultMetricValue *value;
prv_find_timer_metric_and_update(key, kMemfaultTimerOp_ForceValueUpdate);
rv = prv_find_key_of_type(key, kMemfaultMetricType_Timer, &value);
if (rv == 0) {
*read_val = value->u32;
Expand Down
15 changes: 13 additions & 2 deletions components/panics/src/memfault_fault_handling_arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -561,14 +561,21 @@ static void prv_fault_handling_assert(void *pc, void *lr, eMemfaultRebootReason
memfault_platform_reboot();
}

// ARM compiler 5 requires even more explicit no optimization directives to prevent our assert
// functions from optimizing away the callee saved registers.
#if defined(__CC_ARM)
#pragma push
#pragma optimize O0
#endif

// Note: These functions are annotated as "noreturn" which can be useful for static analysis.
// However, this can also lead to compiler optimizations that make recovering local variables
// difficult (such as ignoring ABI requirements to preserve callee-saved registers)
MEMFAULT_NO_OPT
void memfault_fault_handling_assert(void *pc, void *lr) {
prv_fault_handling_assert(pc, lr, kMfltRebootReason_Assert);

#if (defined(__clang__) && defined(__ti__))
#if (defined(__clang__) && defined(__ti__)) || defined(__CC_ARM)
//! tiarmclang does not respect the no optimization request and will
//! strip the pushing callee saved registers making it impossible to recover
//! an accurate backtrace so we skip over providing the unreachable hint.
Expand All @@ -580,11 +587,15 @@ MEMFAULT_NO_OPT
void memfault_fault_handling_assert_extra(void *pc, void *lr, sMemfaultAssertInfo *extra_info) {
prv_fault_handling_assert(pc, lr, extra_info->assert_reason);

#if (defined(__clang__) && defined(__ti__))
#if (defined(__clang__) && defined(__ti__)) || defined(__CC_ARM)
//! See comment in memfault_fault_handling_assert for more context
#else
MEMFAULT_UNREACHABLE;
#endif
}

#if defined(__CC_ARM)
#pragma pop
#endif

#endif /* MEMFAULT_COMPILER_ARM_CORTEX_M */
2 changes: 2 additions & 0 deletions examples/esp32/apps/memfault_demo_app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ add_custom_command(TARGET ${IDF_PROJECT_EXECUTABLE}
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
# 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
Expand Down
4 changes: 4 additions & 0 deletions examples/esp32/apps/memfault_demo_app/main/cmd_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "freertos/semphr.h"
#include "sdkconfig.h"

#if MEMFAULT_TASK_WATCHDOG_ENABLE
//! cause the task watchdog to fire by deadlocking the example task
static int test_task_watchdog(int argc, char** argv) {
(void)argc, (void)argv;
Expand All @@ -25,13 +26,16 @@ static int test_task_watchdog(int argc, char** argv) {

return 0;
}
#endif

void register_app(void) {
#if MEMFAULT_TASK_WATCHDOG_ENABLE
const esp_console_cmd_t test_watchdog_cmd = {
.command = "test_task_watchdog",
.help = "Demonstrate the task watchdog tripping on a deadlock",
.hint = NULL,
.func = &test_task_watchdog,
};
ESP_ERROR_CHECK(esp_console_cmd_register(&test_watchdog_cmd));
#endif
}
1 change: 1 addition & 0 deletions examples/freertos/FreeRTOSConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ extern void vAssertCalled(const char* file, int line);
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_TIMERS 1
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2)
#define configRECORD_STACK_HIGH_ADDRESS 1

#define configGENERATE_RUN_TIME_STATS 1
#define configUSE_TRACE_FACILITY 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ static sMfltCoredumpRegion s_coredump_regions[MEMFAULT_COREDUMP_MAX_TASK_REGIONS
2 /* active stack(s) */
+ 1 /* _kernel variable */
+ 1 /* __memfault_capture_start */
+ 2 /* s_task_tcbs + s_task_watermarks */
];

extern uint32_t __memfault_capture_bss_end;
Expand Down
2 changes: 2 additions & 0 deletions examples/freertos/memfault/memfault_platform_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@
#define MEMFAULT_COREDUMP_HEAP_STATS_LOCK_ENABLE 0
#define MEMFAULT_METRICS_HEARTBEAT_INTERVAL_SECS 60
#define MEMFAULT_COMPACT_LOG_ENABLE 1

#define MEMFAULT_COREDUMP_COMPUTE_THREAD_STACK_USAGE 1
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@
//!
//! Platform overrides for the default configuration settings in the memfault-firmware-sdk.
//! Default configuration settings can be found in "memfault/config.h"

#define MEMFAULT_DEMO_DISABLE_CASSERT 1
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
//! See License.txt for details
//! Reference implementation of the memfault platform header for Mbed
#include "cmsis.h"

#include "memfault/core/compiler.h"
#include "os_tick.h"

int memfault_platform_boot(void) {
return 0;
Expand All @@ -17,3 +17,10 @@ MEMFAULT_NORETURN void memfault_platform_reboot(void) {
NVIC_SystemReset();
MEMFAULT_UNREACHABLE;
}

//! Example implementation. Re-define or verify this works for your platform.
uint64_t memfault_platform_get_time_since_boot_ms(void) {
const uint64_t tick_count = OS_Tick_GetCount();
const uint32_t ticks_per_sec = OS_Tick_GetClock();
return (1000 * tick_count) / ticks_per_sec;
}
7 changes: 6 additions & 1 deletion ports/esp_idf/memfault/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,11 @@ if(DEFINED ENV{IDF_VERSION})
# This method is an alternative to #include within FreeRTOSConfig.h which esp-idf
# makes very difficult to do.
get_filename_component(freertos_trace_header ${MEMFAULT_SDK_ROOT}/ports/include/memfault/ports/freertos_trace.h ABSOLUTE)
target_compile_options(${freertos_lib} INTERFACE -include ${freertos_trace_header})
target_compile_options(${freertos_lib} INTERFACE
"-DMEMFAULT_METRICS_USER_HEARTBEAT_DEFS_FILE=\"memfault_esp_metrics_heartbeat_config.def\""
"-DMEMFAULT_PLATFORM_CONFIG_FILE=\"memfault_esp_idf_port_config.h\""
"-DMEMFAULT_TRACE_REASON_USER_DEFS_FILE=\"memfault_trace_reason_esp_idf_port_config.def\""
-include ${freertos_trace_header}
)
endif()
endif()
Loading

0 comments on commit 2e3d5e5

Please sign in to comment.