Skip to content

Commit 0005373

Browse files
author
Memfault Inc
committed
Memfault Firmware SDK 1.9.0 (Build 7848)
1 parent b7d5c1c commit 0005373

File tree

60 files changed

+1079
-146
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1079
-146
lines changed

CHANGELOG.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,73 @@ 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.9.0] - 2024-05-10
10+
11+
### :chart_with_upwards_trend: Improvements
12+
13+
- General:
14+
15+
- Correctly compile out the
16+
[non-volatile event storage feature](https://docs.memfault.com/docs/mcu/metrics-api/#non-volatile-event-storage)
17+
when `MEMFAULT_EVENT_STORAGE_NV_SUPPORT_ENABLED` is set to `0`. This feature
18+
was previously not fully disabled, leaving some unused code in the final
19+
executable. This is a minor code size improvement (approximately 300 bytes)
20+
when the system is disabled (default).
21+
22+
- Zephyr:
23+
24+
- Improve support for
25+
[event timestamps](https://docs.memfault.com/docs/mcu/event-timestamps)
26+
using Zephyr RTC devices, by adding support for RTC nodes identified using
27+
`DT_ALIAS()` in addition to `DT_NODELABEL()`. Thanks to @corytodd for
28+
providing the fix in
29+
[#68](https://github.com/memfault/memfault-firmware-sdk/issues/68)!
30+
31+
- Add a Memfault HTTP OTA client backend for Zephyr MCUBoot platforms. This is
32+
enabled with the `CONFIG_MEMFAULT_ZEPHYR_FOTA_BACKEND_MCUBOOT` Kconfig flag.
33+
The OTA process is triggered by calling the `memfault_zephyr_fota_start()`
34+
function, which is also exposed in the shell via the
35+
`mflt get_latest_release` command.
36+
37+
- Add basic support for Xtensa targets in the Memfault Zephyr port. This
38+
specifically targets the ESP32-S3 SOC.
39+
40+
- Add a success message when the Zephyr HTTP client posts data to Memfault.
41+
42+
- ESP-IDF:
43+
44+
- Wrap calls to `esp_event_loop_create_default()` to prevent crashes if called
45+
multiple times. This feature is enabled by default and is disabled with
46+
`CONFIG_MEMFAULT_WRAP_EVENT_LOOP_CREATE_DEFAULT=n`
47+
48+
- Add an example
49+
[Session Metric](https://docs.memfault.com/docs/mcu/metrics-api/#session-metrics)
50+
to the [ESP32 example app](examples/esp32), which tracks statistics during
51+
the ESP32 OTA session (bytes sent + received, etc).
52+
53+
- nRF Connect SDK:
54+
55+
- Enable periodic upload, `CONFIG_MEMFAULT_HTTP_PERIODIC_UPLOAD=y`, by default
56+
for nRF91x builds
57+
58+
- Default to `CONFIG_MEMFAULT_HTTP_PERIODIC_UPLOAD_USE_DEDICATED_WORKQUEUE`
59+
when periodic upload is enabled
60+
61+
- Improve the stability of the
62+
[nRF9160 sample app](examples/nrf-connect-sdk/nrf9160), by increasing the
63+
`CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE` to `2048`.
64+
65+
### :boom: Breaking Changes
66+
67+
- Zephyr:
68+
69+
- Add a built-in implementation of `g_mflt_http_client_config` for Zephyr
70+
devices using the Memfault HTTP client, which holds the
71+
[Memfault Project Key](https://mflt.io/project-key) set via the Kconfig
72+
symbol `CONFIG_MEMFAULT_PROJECT_KEY`. Users updating from a previous version
73+
will have to set this Kconfig symbol when building, and any existing
74+
implementation of `g_mflt_http_client_config` should be removed.
75+
976
## [1.8.1] - 2024-04-24
1077

1178
### :chart_with_upwards_trend: Improvements

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ If you are using `git`, the Memfault SDK is typically added to a project as a
8080
submodule:
8181

8282
```
83-
$ git submodule add git@github.com:memfault/memfault-firmware-sdk.git $YOUR_PROJECT/third_party/memfault/memfault-firmware-sdk
83+
$ git submodule add https://github.com/memfault/memfault-firmware-sdk.git $YOUR_PROJECT/third_party/memfault/memfault-firmware-sdk
8484
```
8585

8686
This makes it easy to track the history of the Memfault SDK. You should not need

VERSION

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
BUILD ID: 7582
2-
GIT COMMIT: ece044b45b
3-
VERSION: 1.8.1
1+
BUILD ID: 7848
2+
GIT COMMIT: e5e934d26b
3+
VERSION: 1.9.0

components/core/src/memfault_event_storage.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ MEMFAULT_WEAK void memfault_lock(void) { }
4242

4343
MEMFAULT_WEAK void memfault_unlock(void) { }
4444

45+
#if MEMFAULT_EVENT_STORAGE_NV_SUPPORT_ENABLED
4546
MEMFAULT_WEAK void memfault_event_storage_request_persist_callback(
4647
MEMFAULT_UNUSED const sMemfaultEventStoragePersistCbStatus *status) { }
4748

@@ -53,6 +54,7 @@ MEMFAULT_WEAK const sMemfaultNonVolatileEventStorageImpl
5354
g_memfault_platform_nv_event_storage_impl = {
5455
.enabled = prv_nonvolatile_event_storage_enabled,
5556
};
57+
#endif
5658

5759
typedef struct {
5860
bool write_in_progress;
@@ -76,6 +78,7 @@ static sMfltCircularBuffer s_event_storage;
7678
static sMemfaultEventStorageWriteState s_event_storage_write_state;
7779
static sMemfaultEventStorageReadState s_event_storage_read_state;
7880

81+
#if MEMFAULT_EVENT_STORAGE_NV_SUPPORT_ENABLED
7982
static void prv_invoke_request_persist_callback(void) {
8083
sMemfaultEventStoragePersistCbStatus status;
8184
memfault_lock();
@@ -91,6 +94,7 @@ static void prv_invoke_request_persist_callback(void) {
9194

9295
memfault_event_storage_request_persist_callback(&status);
9396
}
97+
#endif
9498

9599
static size_t prv_get_total_event_size(sMemfaultEventStorageReadState *state) {
96100
if (state->num_events == 0) {
@@ -298,9 +302,11 @@ static void prv_event_storage_storage_finish_write(bool rollback) {
298302

299303
// reset the write state
300304
s_event_storage_write_state = (sMemfaultEventStorageWriteState){ 0 };
305+
#if MEMFAULT_EVENT_STORAGE_NV_SUPPORT_ENABLED
301306
if (!rollback) {
302307
prv_invoke_request_persist_callback();
303308
}
309+
#endif
304310
}
305311

306312
static size_t prv_get_size_cb(void) {
@@ -323,6 +329,7 @@ const sMemfaultEventStorageImpl *memfault_events_storage_boot(void *buf, size_t
323329
return &s_event_storage_impl;
324330
}
325331

332+
#if MEMFAULT_EVENT_STORAGE_NV_SUPPORT_ENABLED
326333
static bool prv_save_event_to_persistent_storage(void) {
327334
size_t total_size;
328335
if (!prv_has_data_ram(&total_size)) {
@@ -375,7 +382,6 @@ int memfault_event_storage_persist(void) {
375382
return events_saved;
376383
}
377384

378-
#if MEMFAULT_EVENT_STORAGE_NV_SUPPORT_ENABLED
379385
static void prv_nv_event_storage_mark_read_cb(void) {
380386
g_memfault_platform_nv_event_storage_impl.consume();
381387

components/demo/src/panics/memfault_demo_panics.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -189,18 +189,6 @@ int memfault_demo_cli_cmd_usagefault(MEMFAULT_UNUSED int argc, MEMFAULT_UNUSED c
189189
return -1;
190190
}
191191

192-
int memfault_demo_cli_loadaddr(int argc, char *argv[]) {
193-
if (argc < 2) {
194-
MEMFAULT_LOG_ERROR("Usage: loadaddr <addr>");
195-
return -1;
196-
}
197-
uint32_t addr = (uint32_t)strtoul(argv[1], NULL, 0);
198-
uint32_t val = *(uint32_t *)addr;
199-
200-
MEMFAULT_LOG_INFO("Read 0x%08" PRIx32 " from 0x%08" PRIx32, val, (uint32_t)(uintptr_t)addr);
201-
return 0;
202-
}
203-
204192
#endif // MEMFAULT_COMPILER_ARM_CORTEX_M
205193

206194
#if MEMFAULT_COMPILER_ARM_V7_A_R
@@ -223,3 +211,15 @@ int memfault_demo_cli_cmd_prefetchabort(MEMFAULT_UNUSED int argc, MEMFAULT_UNUSE
223211
}
224212

225213
#endif // MEMFAULT_COMPILER_ARM_V7_A_R
214+
215+
int memfault_demo_cli_loadaddr(int argc, char *argv[]) {
216+
if (argc < 2) {
217+
MEMFAULT_LOG_ERROR("Usage: loadaddr <addr>");
218+
return -1;
219+
}
220+
uint32_t addr = (uint32_t)strtoul(argv[1], NULL, 0);
221+
uint32_t val = *(uint32_t *)addr;
222+
223+
MEMFAULT_LOG_INFO("Read 0x%08" PRIx32 " from 0x%08" PRIx32, val, (uint32_t)(uintptr_t)addr);
224+
return 0;
225+
}

components/include/memfault/core/compiler_gcc.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,18 @@ extern "C" {
6161
&&_l; \
6262
});
6363
#define MEMFAULT_BREAKPOINT(val) __asm__("break 0,0")
64+
#elif defined(__riscv)
65+
#define MEMFAULT_GET_LR(_a) _a = __builtin_return_address(0)
66+
// Take advantage of "Locally Declared Labels" to get a PC
67+
// https://gcc.gnu.org/onlinedocs/gcc/Local-Labels.html#Local-Labels
68+
#define MEMFAULT_GET_PC(_a) \
69+
_a = ({ \
70+
__label__ _l; \
71+
_l: \
72+
&&_l; \
73+
});
74+
// Trigger a breakpoint exception (similar to bkpt instruction in ARM)
75+
#define MEMFAULT_BREAKPOINT(val) __asm volatile("ebreak")
6476
#elif defined(MEMFAULT_UNITTEST) || \
6577
defined(__APPLE__) // Memfault iOS SDK also #includes this header
6678
#define MEMFAULT_GET_LR(_a) _a = 0

components/include/memfault/core/event_storage.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include <stddef.h>
2323
#include <stdint.h>
2424

25+
#include "memfault/config.h"
26+
2527
// The unity test framework (http://www.throwtheswitch.org/unity) fails to generate mocks when
2628
// opaque pointers are used in a header. To work around, the problem, we pull in the full internal
2729
// definition for "sMemfaultEventStorageImpl" when the unity framework is being used.
@@ -66,6 +68,7 @@ typedef struct MemfaultEventStorageInfo {
6668
size_t bytes_free;
6769
} sMemfaultEventStorageInfo;
6870

71+
#if MEMFAULT_EVENT_STORAGE_NV_SUPPORT_ENABLED
6972
typedef struct MemfaultEventStoragePersistCbStatus {
7073
//! Summarizes the utilization of the RAM buffer passed in memfault_events_storage_boot()
7174
sMemfaultEventStorageInfo volatile_storage;
@@ -97,6 +100,8 @@ void memfault_event_storage_request_persist_callback(
97100
//! @return number of events saved or <0 for unexpected errors
98101
int memfault_event_storage_persist(void);
99102

103+
#endif
104+
100105
//! Simple API call to retrieve the number of bytes used in the allocated event storage buffer.
101106
//! Returns zero if the storage has not been allocated.
102107
size_t memfault_event_storage_bytes_used(void);

components/include/memfault/demo/cli.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ int memfault_demo_cli_cmd_memmanage(int argc, char *argv[]);
3939
//! Command which will generate a UsageFault on Cortex-M hardware
4040
int memfault_demo_cli_cmd_usagefault(int argc, char *argv[]);
4141

42+
#endif // MEMFAULT_COMPILER_ARM_CORTEX_M
43+
4244
//! Read a 32-bit memory address and print the value. Can be used to test
4345
//! specific faults due to protected regions
4446
int memfault_demo_cli_loadaddr(int argc, char *argv[]);
4547

46-
#endif // MEMFAULT_COMPILER_ARM_CORTEX_M
47-
4848
#if MEMFAULT_COMPILER_ARM_V7_A_R
4949
//! Trigger a data abort on an ARMv7-A/R chip
5050
int memfault_demo_cli_cmd_dataabort(int argc, char *argv[]);

components/include/memfault/version.h

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

22-
#define MEMFAULT_SDK_VERSION { .major = 1, .minor = 8, .patch = 1 }
23-
#define MEMFAULT_SDK_VERSION_STR "1.8.1"
22+
#define MEMFAULT_SDK_VERSION { .major = 1, .minor = 9, .patch = 0 }
23+
#define MEMFAULT_SDK_VERSION_STR "1.9.0"
2424

2525
#ifdef __cplusplus
2626
}

components/panics/src/memfault_fault_handling_riscv.c

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "memfault/panics/arch/riscv/riscv.h"
1818
#include "memfault/panics/coredump.h"
1919
#include "memfault/panics/coredump_impl.h"
20+
#include "memfault/panics/fault_handling.h"
2021

2122
const sMfltCoredumpRegion *memfault_coredump_get_arch_regions(size_t *num_regions) {
2223
*num_regions = 0;
@@ -42,6 +43,60 @@ void memfault_arch_fault_handling_assert(void *pc, void *lr, eMemfaultRebootReas
4243
prv_fault_handling_assert(pc, lr, reason);
4344
}
4445

46+
// For non-esp-idf riscv implementations, provide a full assert handler and
47+
// other utilities.
48+
#if defined(__ZEPHYR__) && defined(CONFIG_SOC_FAMILY_ESP32)
49+
#include <hal/cpu_hal.h>
50+
#include <zephyr/kernel.h>
51+
52+
void memfault_platform_halt_if_debugging(void) {
53+
if (cpu_ll_is_debugger_attached()) {
54+
MEMFAULT_BREAKPOINT();
55+
}
56+
}
57+
58+
bool memfault_arch_is_inside_isr(void) {
59+
// Use the Zephyr-specific implementation.
60+
//
61+
// It's not clear if there's a RISC-V standard way to check if the CPU is in
62+
// an exception mode. The mcause register comes close but it won't tell us if
63+
// a trap was taken due to a non-interrupt cause:
64+
// https://five-embeddev.com/riscv-isa-manual/latest/machine.html#sec:mcause
65+
return k_is_in_isr();
66+
}
67+
68+
static void prv_fault_handling_assert_native(void *pc, void *lr, eMemfaultRebootReason reason) {
69+
prv_fault_handling_assert(pc, lr, reason);
70+
71+
#if MEMFAULT_ASSERT_HALT_IF_DEBUGGING_ENABLED
72+
memfault_platform_halt_if_debugging();
73+
#endif
74+
75+
// dereference a null pointer to trigger fault
76+
*(uint32_t *)0 = 0x77;
77+
78+
// We just trap'd into the fault handler logic so it should never be possible to get here but if
79+
// we do the best thing that can be done is rebooting the system to recover it.
80+
memfault_platform_reboot();
81+
}
82+
83+
MEMFAULT_NO_OPT void memfault_fault_handling_assert_extra(void *pc, void *lr,
84+
sMemfaultAssertInfo *extra_info) {
85+
prv_fault_handling_assert_native(pc, lr, extra_info->assert_reason);
86+
87+
MEMFAULT_UNREACHABLE;
88+
}
89+
90+
MEMFAULT_NO_OPT void memfault_fault_handling_assert(void *pc, void *lr) {
91+
prv_fault_handling_assert_native(pc, lr, kMfltRebootReason_Assert);
92+
93+
MEMFAULT_UNREACHABLE;
94+
}
95+
96+
#elif !defined(ESP_PLATFORM)
97+
#error "Unsupported RISC-V platform, please contact [email protected]"
98+
#endif // !defined(ESP_PLATFORM) && defined(__ZEPHYR__)
99+
45100
void memfault_fault_handler(const sMfltRegState *regs, eMemfaultRebootReason reason) {
46101
if (s_crash_reason == kMfltRebootReason_Unknown) {
47102
// TODO confirm this works correctly- we should have the correct
@@ -56,7 +111,8 @@ void memfault_fault_handler(const sMfltRegState *regs, eMemfaultRebootReason rea
56111
};
57112

58113
sCoredumpCrashInfo info = {
59-
.stack_address = (void *)regs->sp,
114+
// Zephyr fault shim saves the stack pointer in s[0]
115+
.stack_address = (void *)regs->s[0],
60116
.trace_reason = save_info.trace_reason,
61117
.exception_reg_state = regs,
62118
};
@@ -66,6 +122,11 @@ void memfault_fault_handler(const sMfltRegState *regs, eMemfaultRebootReason rea
66122
if (coredump_saved) {
67123
memfault_reboot_tracking_mark_coredump_saved();
68124
}
125+
126+
#if !MEMFAULT_FAULT_HANDLER_RETURN
127+
memfault_platform_reboot();
128+
MEMFAULT_UNREACHABLE;
129+
#endif
69130
}
70131

71132
size_t memfault_coredump_storage_compute_size_required(void) {

0 commit comments

Comments
 (0)