Skip to content

Commit 53f70b2

Browse files
author
Memfault Inc
committed
Memfault Firmware SDK 1.24.0 (Build 13888)
1 parent fa2cd22 commit 53f70b2

30 files changed

+564
-46
lines changed

CHANGELOG.md

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,96 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to
77
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
88

9-
## [1.23.1] - 2024-04-17
9+
## [1.24.0] - 2025-05-06
10+
11+
### 📈 Added
12+
13+
- General:
14+
15+
- Add a new API, `memfault_log_get_unsent_count()`, which returns the log
16+
count and size in bytes of unsent logs in the log buffer. This can be used
17+
inside `memfault_log_handle_saved_callback()` for example to drain the
18+
packetized logs when a certain watermark is reached.
19+
20+
- ESP-IDF:
21+
22+
- Add a Kconfig option, `CONFIG_MEMFAULT_TIME_SINCE_BOOT_CUSTOM`, which when
23+
set `=n`, enables using a custom implementation of
24+
`memfault_platform_get_time_since_boot_ms()`.
25+
26+
- Add 2 new metrics for tracking raw network bytes rx / tx. These metrics
27+
track network IO traffic on the default netif:
28+
29+
- `network_rx_bytes`
30+
- `network_tx_bytes`
31+
32+
These metrics are enabled by default, and can be disabled with
33+
`CONFIG_MEMFAULT_METRICS_NETWORK_IO=n`
34+
35+
### 🛠️ Changed
36+
37+
- FreeRTOS (including ESP-IDF):
38+
39+
- Rename the thread stack usage measurement variable included in coredumps
40+
when `MEMFAULT_COREDUMP_COMPUTE_THREAD_STACK_USAGE` is enabled from
41+
`high_watermark` to `stack_unused`. This change is to make the
42+
implementation more readable. The Memfault backend is updated to process
43+
both the old and new formats.
44+
45+
- FreeRTOS-detected stack overflows (via `vApplicationStackOverflowHook`) will
46+
now be correctly tagged as `Stack Overflow` for the trace reason in
47+
Memfault, instead of `Assert`.
48+
49+
### 🐛 Fixed
50+
51+
- Zephyr:
52+
53+
- Fix a null dereference when calling
54+
`memfault_coredump_storage_compute_size_required()` (eg the shell command
55+
`mflt coredump_size`).
56+
57+
- General:
58+
59+
- For the emlib WDOG port implementation,
60+
[`ports/emlib/wdog_software_watchdog.c`](ports/emlib/wdog_software_watchdog.c),
61+
enable the WDOG when in EM1 mode for series2 chips.
62+
63+
- Added support for `MEMFAULT_REBOOT_REASON_CLEAR` in the
64+
[`ports/nrf5_sdk/resetreas_reboot_tracking.c`](ports/nrf5_sdk/resetreas_reboot_tracking.c)
65+
implementation, by default enabled (like other ports). This permits opting
66+
out of the auto-clearing of the `NRF_POWER->RESETREAS` register, in case the
67+
user needs it after the function runs.
68+
69+
- FreeRTOS (including ESP-IDF):
70+
71+
- Fix incorrect computation of per-thread stack usage metrics
72+
(`MEMFAULT_FREERTOS_COLLECT_THREAD_METRICS`). Before this fix, the returned
73+
values had 2 errors:
74+
75+
1. the value is the _unused_ stack space, not the used stack space
76+
2. on platforms where `sizeof(StackType_t)` is not 1 byte, the numerator
77+
when computing percentage is incorrectly scaled down by
78+
`sizeof(StackType_t)`, resulting in significant under-reporting of the
79+
stack usage percentage.
80+
81+
Users can apply device and software version filtering on dashboards to
82+
filter out reports from devices that are running an old version of the SDK.
83+
84+
- ESP-IDF:
85+
86+
- Fix a potential issue that would cause the wrong implementation of
87+
`memfault_platform_time_get_current()` to be included in the final link,
88+
when `CONFIG_MEMFAULT_SYSTEM_TIME=y` is enabled (default).
89+
90+
### 🛠️ Changed
91+
92+
- ESP-IDF:
93+
94+
- `CONFIG_MEMFAULT_ENABLE_REBOOT_DIAG_DUMP` now defaults to `y` instead of
95+
`n`, to print out the reboot reason on boot. Disable it with
96+
`CONFIG_MEMFAULT_ENABLE_REBOOT_DIAG_DUMP=n`.
97+
98+
## [1.23.1] - 2025-04-17
1099

11100
### 🐛 Fixed
12101

@@ -15,7 +104,7 @@ and this project adheres to
15104
[CircleCI's v2 container runtime](https://discuss.circleci.com/t/docker-executor-infrastructure-upgrade/52282),
16105
which uses `cgroupv2` instead of `cgroupv1`.
17106

18-
## [1.23.0] - 2024-04-16
107+
## [1.23.0] - 2025-04-16
19108

20109
### 📈 Added
21110

VERSION

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
BUILD ID: 13641
2-
GIT COMMIT: 5f0dd98704
3-
VERSION: 1.23.1
1+
BUILD ID: 13888
2+
GIT COMMIT: 58d5865404
3+
VERSION: 1.24.0

components/core/src/memfault_event_storage.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@
3434
// memfault/core/platform/event.h
3535
//
3636

37+
#if MEMFAULT_EVENT_STORAGE_STUB_SYSTEM_TIME
3738
MEMFAULT_WEAK bool memfault_platform_time_get_current(MEMFAULT_UNUSED sMemfaultCurrentTime *time) {
3839
return false;
3940
}
41+
#endif
4042

4143
MEMFAULT_WEAK void memfault_lock(void) { }
4244

components/core/src/memfault_log_data_source.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,15 @@ static bool prv_log_is_sent(uint8_t hdr) {
3737

3838
typedef struct {
3939
size_t num_logs;
40+
size_t bytes;
4041
} sMfltLogCountingCtx;
4142

4243
static bool prv_log_iterate_counting_callback(sMfltLogIterator *iter) {
4344
sMfltLogCountingCtx *const ctx = (sMfltLogCountingCtx *)(iter->user_ctx);
4445
if (!prv_log_is_sent(iter->entry.hdr)) {
4546
++ctx->num_logs;
47+
// tally the size of the log message
48+
ctx->bytes += iter->entry.len + sizeof(iter->entry.hdr);
4649
}
4750
return true;
4851
}
@@ -303,4 +306,15 @@ size_t memfault_log_data_source_count_unsent_logs(void) {
303306
return ctx.num_logs;
304307
}
305308

309+
sMfltLogUnsentCount memfault_log_get_unsent_count(void) {
310+
sMfltLogCountingCtx ctx = { 0 };
311+
sMfltLogIterator iter = { .user_ctx = &ctx };
312+
memfault_log_iterate(prv_log_iterate_counting_callback, &iter);
313+
314+
return (sMfltLogUnsentCount){
315+
.num_logs = ctx.num_logs,
316+
.bytes = ctx.bytes,
317+
};
318+
}
319+
306320
#endif /* MEMFAULT_LOG_DATA_SOURCE_ENABLED */

components/include/memfault/core/log.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,14 @@ uint32_t memfault_log_get_dropped_count(void);
241241
//! Return the count of lines that have been written to the logging buffer.
242242
uint32_t memfault_log_get_recorded_count(void);
243243

244+
typedef struct {
245+
size_t num_logs;
246+
size_t bytes;
247+
} sMfltLogUnsentCount;
248+
249+
//! Return the number of unsent logs and their total size
250+
sMfltLogUnsentCount memfault_log_get_unsent_count(void);
251+
244252
#ifdef __cplusplus
245253
}
246254
#endif

components/include/memfault/default_config.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,14 @@ extern "C" {
206206

207207
#endif /* MEMFAULT_EVENT_STORAGE_READ_BATCHING_ENABLED */
208208

209+
//! Include a stub, weakly defined implementation of
210+
//! memfault_platform_time_get_current(). Most build systems will be able to
211+
//! override the symbol with a custom implementation at link time, but some will
212+
//! need to exclude the weak definition entirely.
213+
#ifndef MEMFAULT_EVENT_STORAGE_STUB_SYSTEM_TIME
214+
#define MEMFAULT_EVENT_STORAGE_STUB_SYSTEM_TIME 1
215+
#endif
216+
209217
//! The max size of a chunk. Should be a size suitable to write to transport
210218
//! data is being dumped over.
211219
#ifndef MEMFAULT_DATA_EXPORT_CHUNK_MAX_LEN

components/include/memfault/version.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ typedef struct {
2020
} sMfltSdkVersion;
2121

2222
#define MEMFAULT_SDK_VERSION \
23-
{ .major = 1, .minor = 23, .patch = 1 }
24-
#define MEMFAULT_SDK_VERSION_STR "1.23.1"
23+
{ .major = 1, .minor = 24, .patch = 0 }
24+
#define MEMFAULT_SDK_VERSION_STR "1.24.0"
2525

2626
#ifdef __cplusplus
2727
}

components/panics/src/memfault_fault_handling_arm.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,17 @@ size_t memfault_coredump_storage_compute_size_required(void) {
5151
.trace_reason = kMfltRebootReason_UnknownError,
5252
};
5353

54+
const sMfltRegState exception_regs = {
55+
// spoof the EXC_RETURN value as "PSP active", to avoid checking PSP
56+
// register when computing size. it's unused in bare metal applications.
57+
.exc_return = 1 << 2,
58+
};
59+
5460
sCoredumpCrashInfo info = {
5561
// we'll just pass the current stack pointer, value shouldn't matter
5662
.stack_address = (void *)&core_regs,
5763
.trace_reason = save_info.trace_reason,
58-
.exception_reg_state = NULL,
64+
.exception_reg_state = &exception_regs,
5965
};
6066
save_info.regions = memfault_platform_coredump_get_regions(&info, &save_info.num_regions);
6167

examples/esp32/apps/memfault_demo_app/main/main.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,13 @@ static void prv_load_memfault_settings_from_nvs(void) {
410410
(s_mflt_device_url_len > 1) ? s_mflt_device_url : NULL;
411411
}
412412
}
413+
414+
#if defined(CONFIG_MEMFAULT_TIME_SINCE_BOOT_CUSTOM)
415+
uint64_t memfault_platform_get_time_since_boot_ms(void) {
416+
const int64_t time_since_boot_us = esp_timer_get_time();
417+
return (uint64_t)(time_since_boot_us / 1000) /* us per ms */;
418+
}
419+
#endif
413420
#endif // defined(CONFIG_MEMFAULT)
414421

415422
// This task started by cpu_start.c::start_cpu0_default().

examples/esp32/apps/memfault_demo_app/sdkconfig.defaults

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,6 @@ CONFIG_MEMFAULT_HTTP_PERIODIC_UPLOAD=y
5353
# Upload logs. Not recommended for production.
5454
CONFIG_MEMFAULT_HTTP_PERIODIC_UPLOAD_LOGS=y
5555

56-
# Pretty-print reboot reason
57-
CONFIG_MEMFAULT_ENABLE_REBOOT_DIAG_DUMP=y
58-
5956
# Support older ESP32-C3 variants
6057
CONFIG_ESP32C3_REV_MIN_2=y
6158

examples/freertos/Makefile

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,24 @@ SIZE ?= $(shell $(CC) -print-prog-name=size)
4949
READELF ?= $(shell $(CC) -print-prog-name=readelf)
5050

5151
# Check if FreeRTOS location set, add rule to download if not
52+
FREERTOS_DIR ?=
5253
ifeq ($(FREERTOS_DIR),)
5354
FREERTOS_DIR = FreeRTOS-Kernel
5455
FREERTOS_VER = V11.2.0
56+
FREERTOS_SHA = 0adc196d4bd52a2d91102b525b0aafc1e14a2386
5557

56-
$(FREERTOS_DIR)/.clonedone:
57-
$(info FREERTOS_DIR does not exist, downloading local copy)
58+
# Verify the FreeRTOS directory is present and matches expected SHA
59+
FREERTOS_STALE = \
60+
$(shell \
61+
if ! (echo "$(FREERTOS_SHA)" | diff -q $(FREERTOS_DIR)/.git/HEAD - > /dev/null 2>&1); then \
62+
echo FREERTOS_STALE; \
63+
fi \
64+
)
65+
.PHONY: FREERTOS_STALE
66+
$(FREERTOS_DIR)/.git/HEAD: $(FREERTOS_STALE)
67+
$(info FREERTOS_DIR needs updating, deleting stale copy (if present) and fetching from git)
68+
rm -rf $(FREERTOS_DIR)
5869
git -c advice.detachedHead=false clone --branch $(FREERTOS_VER) --depth 1 https://github.com/FreeRTOS/FreeRTOS-Kernel.git $(FREERTOS_DIR)
59-
# sad check for clone completion, :(
60-
touch $@
6170

6271
.DEFAULT_GOAL :=
6372
endif
@@ -174,7 +183,7 @@ endif
174183
all: $(ELF)
175184

176185
# Require clone to complete as prereq for sources
177-
$(SRCS): $(FREERTOS_DIR)/.clonedone
186+
$(SRCS): $(FREERTOS_DIR)/.git/HEAD
178187

179188
# Store computed cflags in a file; it's a prerequisite for all objects. Use a
180189
# shell hack to check if the current cflags are different from the stored file,

examples/freertos/src/FreeRTOSConfig.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ extern void vAssertCalled(const char *file, int line);
8787
* to exclude the API function. */
8888

8989
#if MEMFAULT_TEST_USE_PORT_TEMPLATE != 1
90-
#define configCHECK_FOR_STACK_OVERFLOW 1
90+
#define configCHECK_FOR_STACK_OVERFLOW 2
9191
#else
9292
#define configCHECK_FOR_STACK_OVERFLOW 0
9393
#endif

examples/freertos/src/console.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,38 @@ static int prv_assert_with_reason(int argc, char *argv[]) {
168168
return 0;
169169
}
170170

171+
static int prv_get_log_count(int argc, char *argv[]) {
172+
(void)argc, (void)argv;
173+
174+
sMfltLogUnsentCount log_count = memfault_log_get_unsent_count();
175+
printf("Number of logs: %u\nSize: %u bytes\n", (unsigned int)log_count.num_logs,
176+
(unsigned int)log_count.bytes);
177+
178+
return 0;
179+
}
180+
181+
static int prv_stack_overflow(int argc, char *argv[]) {
182+
(void)argc, (void)argv;
183+
TaskHandle_t task_handle = xTaskGetCurrentTaskHandle();
184+
MEMFAULT_LOG_INFO("Triggering stack overflow test on task %p / %s", (void *)task_handle,
185+
pcTaskGetName(task_handle));
186+
// get the current address- it should be ~ the address of the above variable,
187+
// offset it by 4 words to hopefully prevent clobbering our current variables.
188+
// we'll write from this address, so the stack watermark will be updated.
189+
volatile uint32_t *stack_start = ((volatile uint32_t *)&task_handle) - 4;
190+
volatile uint32_t *stack_current = stack_start;
191+
192+
// starting at the stack start address, write decrementing values. this should crash!
193+
for (; stack_current > (stack_start - CONSOLE_INPUT_STACK_SIZE); stack_current--) {
194+
*stack_current = 0xDEADBEEF;
195+
// sleep a bit
196+
vTaskDelay((10) / portTICK_PERIOD_MS);
197+
}
198+
199+
MEMFAULT_LOG_ERROR("Stack overflow test failed, stack overflow was not triggered!");
200+
return 0;
201+
}
202+
171203
static const sMemfaultShellCommand s_freertos_example_shell_extension_list[] = {
172204
{
173205
.command = "freertos_vassert",
@@ -208,6 +240,16 @@ static const sMemfaultShellCommand s_freertos_example_shell_extension_list[] = {
208240
.command = "assert_with_reason",
209241
.handler = prv_assert_with_reason,
210242
.help = "Execute an assert with a custom reason code",
243+
},
244+
{
245+
.command = "log_count",
246+
.handler = prv_get_log_count,
247+
.help = "Get the number and size of unsent logs",
248+
},
249+
{
250+
.command = "stack_overflow",
251+
.handler = prv_stack_overflow,
252+
.help = "Trigger a stack overflow",
211253
}
212254
};
213255
#endif

examples/freertos/src/memfault/memfault_platform_port.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ void memfault_platform_log_raw(const char *fmt, ...) {
8585
va_end(args);
8686
}
8787

88+
//! Route the 'export' command to output via printf, so we don't drop messages
89+
//! from logging in a big burst.
90+
void memfault_data_export_base64_encoded_chunk(const char *base64_chunk) {
91+
printf("%s\n", base64_chunk);
92+
}
93+
8894
bool memfault_platform_time_get_current(sMemfaultCurrentTime *time_output) {
8995
#if MEMFAULT_EXAMPLE_USE_REAL_TIME
9096
// Get time from time.h

ports/emlib/wdog_software_watchdog.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ static void prv_build_configuration(WDOG_Init_TypeDef *cfg, uint32_t persel) {
6262
.enable = true,
6363
// freeze watchdog when a debugger halts the system
6464
.debugRun = false,
65+
#if defined(_WDOG_CFG_EM1RUN_MASK)
66+
.em1Run = true,
67+
#endif
6568
.em2Run = true,
6669
.em3Run = true,
6770
.em4Block = false,

0 commit comments

Comments
 (0)