Skip to content

Commit 72f52c0

Browse files
author
Memfault Inc
committed
Memfault Firmware SDK 1.15.0 (Build 10752)
1 parent 6652e81 commit 72f52c0

28 files changed

+551
-45
lines changed

CHANGELOG.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,31 @@ 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.15.0] - 2024-10-13
10+
11+
### 📈 Added
12+
13+
- General:
14+
15+
- **EXPERIMENTAL**: Metrics Sessions now include a built-in metric for the
16+
[Stable Sessions Device Vital](https://docs.memfault.com/docs/platform/memfault-core-metrics#stable-sessions)
17+
(`session.operational_crashes`) which tracks crashes that occurred when a
18+
session is active.
19+
20+
### 🛠️ Changed
21+
22+
- General:
23+
24+
- Minor changes to support compiling with GCC ARM v4.9.3.
25+
26+
### 🐛 Fixed
27+
28+
- Corrected a spelling error, renamed
29+
<!-- spellchecker:off -->
30+
`MEMFAULT_METRIS_KEY_DEFINE_WITH_SESSION_AND_SCALE_VALUE()` to
31+
<!-- spellchecker:on -->
32+
`MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION_AND_SCALE_VALUE()`
33+
934
## [1.14.0] - 2024-10-09
1035

1136
### 📈 Added

VERSION

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
BUILD ID: 10647
2-
GIT COMMIT: 8448e7acf8
3-
VERSION: 1.14.0
1+
BUILD ID: 10752
2+
GIT COMMIT: 1904cdb3cb
3+
VERSION: 1.15.0

components/core/src/memfault_ram_reboot_info_tracking.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,3 +273,31 @@ bool memfault_reboot_tracking_booted(void) {
273273
return ((s_mflt_reboot_info != NULL) &&
274274
(s_mflt_reboot_info->magic == MEMFAULT_REBOOT_INFO_MAGIC));
275275
}
276+
277+
void memfault_reboot_tracking_metrics_session(bool active, uint32_t index) {
278+
if (!prv_check_or_init_struct()) {
279+
return;
280+
}
281+
282+
if (active) {
283+
s_mflt_reboot_info->active_sessions |= (1 << index);
284+
} else {
285+
s_mflt_reboot_info->active_sessions &= ~(1 << index);
286+
}
287+
}
288+
289+
void memfault_reboot_tracking_clear_metrics_sessions(void) {
290+
if (!prv_check_or_init_struct()) {
291+
return;
292+
}
293+
294+
s_mflt_reboot_info->active_sessions = 0;
295+
}
296+
297+
bool memfault_reboot_tracking_metrics_session_was_active(uint32_t index) {
298+
if (!prv_check_or_init_struct()) {
299+
return false;
300+
}
301+
302+
return (s_mflt_reboot_info->active_sessions & (1 << index)) != 0;
303+
}

components/core/src/memfault_reboot_tracking_private.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ typedef MEMFAULT_PACKED_STRUCT MfltRebootInfo {
3737
//! (where no coredump was saved or no user initiated reset took place). Examples
3838
//! of this include brown out resets (BORs) & hardware watchdog resets.
3939
uint32_t reset_reason_reg0;
40+
//! Bitfield tracking sessions that were active prior to reboot
41+
uint32_t active_sessions;
4042
// Reserved for future additions
41-
uint32_t rsvd2[10];
43+
uint32_t rsvd2[9];
4244
}
4345
sMfltRebootInfo;
4446

components/include/memfault/core/reboot_tracking.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,23 @@ int memfault_reboot_tracking_get_unexpected_reboot_occurred(bool *unexpected_reb
184184
//! @returns true if reboot tracking component booted or false if not
185185
bool memfault_reboot_tracking_booted(void);
186186

187+
//! Set or clear the "active" property for a Metrics Session. This is used when
188+
//! a session starts and stops, for tracking which sessions were active when a
189+
//! reboot occurred.
190+
//!
191+
//! @param activate True if the session is active, false if it is not
192+
//! @param index The index of the session
193+
void memfault_reboot_tracking_metrics_session(bool activate, uint32_t index);
194+
195+
//! Clear the reboot tracking data for "active" Metrics Sessions. This is used
196+
//! on reboot to reset the persisted active state of all sessions.
197+
void memfault_reboot_tracking_clear_metrics_sessions(void);
198+
199+
//! Check if a Metrics Session was active when a reboot occurred
200+
//!
201+
//! @param index The index of the session
202+
bool memfault_reboot_tracking_metrics_session_was_active(uint32_t index);
203+
187204
#if MEMFAULT_REBOOT_REASON_CUSTOM_ENABLE == 1
188205
//! Defines a customer specific reboot reason.
189206
//!

components/include/memfault/default_config.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,12 @@ extern "C" {
342342
#define MEMFAULT_METRICS_BATTERY_SOC_PCT_SCALE_VALUE 1
343343
#endif
344344

345+
//! Disable Metrics Sessions at compile time. This saves a small amount of
346+
//! memory but prevents the use of Metrics Sessions.
347+
#ifndef MEMFAULT_METRICS_SESSIONS_ENABLED
348+
#define MEMFAULT_METRICS_SESSIONS_ENABLED 1
349+
#endif
350+
345351
//
346352
// Panics Component Configs
347353
//

components/include/memfault/metrics/ids_impl.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ extern "C" {
5757

5858
//! Sessions have the following built-in keys:
5959
//! - "<session name>__MemfaultSdkMetric_IntervalMs"
60-
#define MEMFAULT_METRICS_SESSION_KEY_DEFINE(session_name) \
61-
kMfltMetricsIndex_##session_name##__##MemfaultSdkMetric_IntervalMs,
60+
//! - "<session name>__operational_crashes"
61+
#define MEMFAULT_METRICS_SESSION_KEY_DEFINE(session_name) \
62+
kMfltMetricsIndex_##session_name##__##MemfaultSdkMetric_IntervalMs, \
63+
kMfltMetricsIndex_##session_name##__##operational_crashes,
6264

6365
#define MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(key_name, value_type, session_name) \
6466
MEMFAULT_METRICS_KEY_DEFINE_(session_name, key_name)

components/include/memfault/metrics/metrics.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ typedef enum MemfaultMetricValueType {
117117
MEMFAULT_METRICS_KEY_DEFINE_TRAP_()
118118

119119
//! Same as 'MEMFAULT_METRICS_KEY_DEFINE_WITH_SCALE_VALUE', with session specified
120-
#define MEMFAULT_METRIS_KEY_DEFINE_WITH_SESSION_AND_SCALE_VALUE(key_name, value_type, session_key, \
121-
scale_value) \
120+
#define MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION_AND_SCALE_VALUE(key_name, value_type, \
121+
session_key, scale_value) \
122122
MEMFAULT_METRICS_KEY_DEFINE_TRAP_()
123123

124124
//! Define a metric session.

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 = 14, .patch = 0 }
24-
#define MEMFAULT_SDK_VERSION_STR "1.14.0"
23+
{ .major = 1, .minor = 15, .patch = 0 }
24+
#define MEMFAULT_SDK_VERSION_STR "1.15.0"
2525

2626
#ifdef __cplusplus
2727
}

components/metrics/src/memfault_metrics.c

Lines changed: 129 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ static MemfaultMetricsSessionEndCb s_session_end_cbs[] = {
9191
max_value, session_key)
9292
#define MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(key_name, value_type, session_key)
9393
#define MEMFAULT_METRICS_SESSION_KEY_DEFINE(key_name) \
94-
MEMFAULT_METRICS_KEY_WITH_SESSION(MemfaultSdkMetric_IntervalMs, key_name),
94+
_MEMFAULT_METRICS_ID_CREATE(MemfaultSdkMetric_IntervalMs, key_name),
9595
#define MEMFAULT_METRICS_KEY_DEFINE_WITH_SCALE_VALUE(key_name, value_type, scale_value)
9696
#define MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION_AND_SCALE_VALUE(key_name, value_type, \
9797
session_key, scale_value)
@@ -111,6 +111,44 @@ static MemfaultMetricId s_memfault_metrics_session_timer_keys[] = {
111111
{ 0 } // dummy entry to prevent empty array
112112
};
113113

114+
#if MEMFAULT_METRICS_SESSIONS_ENABLED
115+
// Generate session key to operational_crashes metric key mapping
116+
#define MEMFAULT_METRICS_KEY_DEFINE(key_name, value_type)
117+
#define MEMFAULT_METRICS_STRING_KEY_DEFINE(key_name, max_length)
118+
#define MEMFAULT_METRICS_STRING_KEY_DEFINE_WITH_SESSION(key_name, max_length, session_key)
119+
#define MEMFAULT_METRICS_KEY_DEFINE_WITH_RANGE(key_name, value_type, min_value, max_value)
120+
#define MEMFAULT_METRICS_KEY_DEFINE_WITH_RANGE_AND_SESSION(key_name, value_type, min_value, \
121+
max_value, session_key)
122+
#define MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(key_name, value_type, session_key)
123+
#define MEMFAULT_METRICS_SESSION_KEY_DEFINE(session_name) \
124+
_MEMFAULT_METRICS_ID_CREATE(operational_crashes, session_name),
125+
#define MEMFAULT_METRICS_KEY_DEFINE_WITH_SCALE_VALUE(key_name, value_type, scale_value)
126+
#define MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION_AND_SCALE_VALUE(key_name, value_type, \
127+
session_key, scale_value)
128+
129+
static MemfaultMetricId s_memfault_metrics_operational_crashes_keys[] = {
130+
#include "memfault/metrics/heartbeat_config.def"
131+
#include MEMFAULT_METRICS_USER_HEARTBEAT_DEFS_FILE
132+
#undef MEMFAULT_METRICS_KEY_DEFINE
133+
#undef MEMFAULT_METRICS_KEY_DEFINE_WITH_RANGE
134+
#undef MEMFAULT_METRICS_STRING_KEY_DEFINE
135+
#undef MEMFAULT_METRICS_STRING_KEY_DEFINE_WITH_SESSION
136+
#undef MEMFAULT_METRICS_SESSION_KEY_DEFINE
137+
#undef MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION
138+
#undef MEMFAULT_METRICS_KEY_DEFINE_WITH_RANGE_AND_SESSION
139+
#undef MEMFAULT_METRICS_SESSION_KEY_DEFINE_
140+
#undef MEMFAULT_METRICS_KEY_DEFINE_WITH_SCALE_VALUE
141+
#undef MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION_AND_SCALE_VALUE
142+
{ 0 } // dummy entry to prevent empty array
143+
};
144+
145+
// Active sessions are tracked in a single 32-bit word in the reboot tracking
146+
// data. This limits the maximum sessions to 32.
147+
MEMFAULT_STATIC_ASSERT(MEMFAULT_ARRAY_SIZE(s_memfault_metrics_operational_crashes_keys) <= 32,
148+
"Too many sessions defined. Max allowed defined sessions is 32.");
149+
150+
#endif
151+
114152
typedef struct MemfaultMetricKVPair {
115153
MemfaultMetricId key;
116154
eMemfaultMetricType type;
@@ -166,9 +204,11 @@ typedef struct MemfaultMetricKVPair {
166204
MEMFAULT_METRICS_KEY_DEFINE_WITH_RANGE_AND_SESSION(key_name, kMemfaultMetricType_String, 0, \
167205
max_length, session_key)
168206

169-
#define MEMFAULT_METRICS_SESSION_KEY_DEFINE(session_name) \
170-
MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(MemfaultSdkMetric_IntervalMs, \
171-
kMemfaultMetricType_Timer, session_name)
207+
#define MEMFAULT_METRICS_SESSION_KEY_DEFINE(session_name) \
208+
MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(MemfaultSdkMetric_IntervalMs, \
209+
kMemfaultMetricType_Timer, session_name) \
210+
MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(operational_crashes, kMemfaultMetricType_Unsigned, \
211+
session_name)
172212

173213
#define MEMFAULT_METRICS_KEY_DEFINE_WITH_SCALE_VALUE(key_name, value_type, scale_value) \
174214
MEMFAULT_KV_PAIR_ENTRY(key_name, value_type, 0, 0, \
@@ -209,7 +249,8 @@ static const sMemfaultMetricKVPair s_memfault_heartbeat_keys[] = {
209249

210250
#define MEMFAULT_METRICS_SESSION_KEY_DEFINE(session_name) \
211251
MEMFAULT_METRICS_KEY_DEFINE(session_name##__##MemfaultSdkMetric_IntervalMs, \
212-
kMemfaultMetricType_Unsigned)
252+
kMemfaultMetricType_Timer) \
253+
MEMFAULT_METRICS_KEY_DEFINE(session_name##__##operational_crashes, kMemfaultMetricType_Unsigned)
213254

214255
#define MEMFAULT_METRICS_KEY_DEFINE_WITH_RANGE_AND_SESSION(key_name, value_type, min_value, \
215256
max_value, session_key) \
@@ -262,8 +303,11 @@ static const sMemfaultMetricKVPair s_memfault_heartbeat_keys[] = {
262303

263304
//! Sessions have the following built-in keys:
264305
//! - "<session name>__MemfaultSdkMetric_IntervalMs"
265-
#define MEMFAULT_METRICS_SESSION_KEY_DEFINE(key_name) \
266-
MEMFAULT_METRICS_KEY_DEFINE(key_name##__##MemfaultSdkMetric_IntervalMs, kMemfaultMetricType_Timer)
306+
//! - "<session name>__operational_crashes"
307+
#define MEMFAULT_METRICS_SESSION_KEY_DEFINE(key_name) \
308+
MEMFAULT_METRICS_KEY_DEFINE(key_name##__##MemfaultSdkMetric_IntervalMs, \
309+
kMemfaultMetricType_Timer) \
310+
MEMFAULT_METRICS_KEY_DEFINE(key_name##__##operational_crashes, kMemfaultMetricType_Unsigned)
267311

268312
#define MEMFAULT_METRICS_KEY_DEFINE_WITH_RANGE_AND_SESSION(key_name, value_type, min_value, \
269313
max_value, session_key) \
@@ -1006,16 +1050,21 @@ int memfault_metrics_heartbeat_read_string(MemfaultMetricId key, char *read_val,
10061050
return rv;
10071051
}
10081052

1009-
int memfault_metrics_session_start(eMfltMetricsSessionIndex session_key) {
1010-
int rv;
1053+
static int prv_metrics_session_start(eMfltMetricsSessionIndex session_key, bool start_timer) {
1054+
int rv = 0;
10111055
memfault_lock();
10121056
{
10131057
// Reset all metrics for the session. Any changes that happened before the
10141058
// session was started don't matter and can be discarded.
10151059
prv_reset_metrics(false, session_key);
10161060

1017-
MemfaultMetricId key = s_memfault_metrics_session_timer_keys[session_key];
1018-
rv = prv_find_timer_metric_and_update(key, kMemfaultTimerOp_Start);
1061+
if (start_timer) {
1062+
MemfaultMetricId key = s_memfault_metrics_session_timer_keys[session_key];
1063+
rv = prv_find_timer_metric_and_update(key, kMemfaultTimerOp_Start);
1064+
}
1065+
1066+
// Mark the session as active for tracking operational_crashes
1067+
memfault_reboot_tracking_metrics_session(true, session_key);
10191068
}
10201069
memfault_unlock();
10211070

@@ -1027,17 +1076,23 @@ int memfault_metrics_session_start(eMfltMetricsSessionIndex session_key) {
10271076
return rv;
10281077
}
10291078

1030-
int memfault_metrics_session_end(eMfltMetricsSessionIndex session_key) {
1079+
int memfault_metrics_session_start(eMfltMetricsSessionIndex session_key) {
1080+
return prv_metrics_session_start(session_key, true);
1081+
}
1082+
1083+
static int prv_metrics_session_end(eMfltMetricsSessionIndex session_key, bool stop_timer) {
10311084
MemfaultMetricsSessionEndCb session_end_cb = s_session_end_cbs[session_key];
10321085
if (session_end_cb != NULL) {
10331086
session_end_cb();
10341087
}
10351088

1036-
int rv;
1089+
int rv = 0;
10371090
memfault_lock();
10381091
{
1039-
MemfaultMetricId key = s_memfault_metrics_session_timer_keys[session_key];
1040-
rv = prv_find_timer_metric_and_update(key, kMemfaultTimerOp_Stop);
1092+
if (stop_timer) {
1093+
MemfaultMetricId key = s_memfault_metrics_session_timer_keys[session_key];
1094+
rv = prv_find_timer_metric_and_update(key, kMemfaultTimerOp_Stop);
1095+
}
10411096

10421097
if (rv == 0) {
10431098
bool serialize_result =
@@ -1046,12 +1101,18 @@ int memfault_metrics_session_end(eMfltMetricsSessionIndex session_key) {
10461101
rv = MEMFAULT_METRICS_STORAGE_TOO_SMALL;
10471102
}
10481103
}
1104+
// Mark the session as inactive for tracking operational_crashes
1105+
memfault_reboot_tracking_metrics_session(false, session_key);
10491106
}
10501107
memfault_unlock();
10511108

10521109
return rv;
10531110
}
10541111

1112+
int memfault_metrics_session_end(eMfltMetricsSessionIndex session_key) {
1113+
return prv_metrics_session_end(session_key, true);
1114+
}
1115+
10551116
void memfault_metrics_session_register_start_cb(eMfltMetricsSessionIndex session_key,
10561117
MemfaultMetricsSessionStartCb session_start_cb) {
10571118
memfault_lock();
@@ -1231,6 +1292,55 @@ void memfault_metrics_heartbeat_debug_trigger(void) {
12311292
prv_heartbeat_timer();
12321293
}
12331294

1295+
#if MEMFAULT_METRICS_SESSIONS_ENABLED
1296+
//! Called on boot, this function checks if the reboot was unexpected. If so,
1297+
//! any session that was active at time of reboot is triggered to record an
1298+
//! `operational_crash=1` metric, and serialized to storage.
1299+
static void prv_session_check_for_unexpected_reboot(void) {
1300+
int rv = -1;
1301+
bool unexpected_reboot;
1302+
1303+
for (eMfltMetricsSessionIndex session_key = (eMfltMetricsSessionIndex)0;
1304+
session_key < (MEMFAULT_ARRAY_SIZE(s_memfault_metrics_operational_crashes_keys));
1305+
session_key++) {
1306+
// This table always ends with a blank entry, so we can stop one iteration
1307+
// early (or if no sessions were defined). Some compilers warn on empty
1308+
// arrays.
1309+
if (session_key == MEMFAULT_ARRAY_SIZE(s_memfault_metrics_operational_crashes_keys) - 1) {
1310+
break;
1311+
}
1312+
1313+
// Only run the check for unexpected reboot once, if it hasn't been already
1314+
// run in this function. Ideally this check would be outside the for loop,
1315+
// but since we can't conditionally compile this whole block based on if
1316+
// any sessions are defined, we have to do it this way.
1317+
if (rv != 0) {
1318+
rv = memfault_reboot_tracking_get_unexpected_reboot_occurred(&unexpected_reboot);
1319+
if ((rv != 0) || !unexpected_reboot) {
1320+
break;
1321+
}
1322+
}
1323+
1324+
// If the session was active at time of reboot, serialize a session with the
1325+
// duration_ms=0 and operational_crashes=1.
1326+
if (memfault_reboot_tracking_metrics_session_was_active(session_key)) {
1327+
// Do not start the session timer, to keep the session duration = 0ms
1328+
prv_metrics_session_start(session_key, false);
1329+
1330+
memfault_metrics_heartbeat_add(s_memfault_metrics_operational_crashes_keys[session_key], 1);
1331+
// Note: the below function clears the reboot tracking bit for this session,
1332+
// since the session is now inactive. A second crash after this won't be
1333+
// recorded as an operational_crash for the session (until the session is
1334+
// activated).
1335+
prv_metrics_session_end(session_key, false);
1336+
}
1337+
}
1338+
1339+
// Unconditionally clear the reboot tracking data for "active sessions".
1340+
memfault_reboot_tracking_clear_metrics_sessions();
1341+
}
1342+
#endif
1343+
12341344
int memfault_metrics_boot(const sMemfaultEventStorageImpl *storage_impl,
12351345
const sMemfaultMetricBootInfo *info) {
12361346
if (storage_impl == NULL || info == NULL) {
@@ -1262,6 +1372,10 @@ int memfault_metrics_boot(const sMemfaultEventStorageImpl *storage_impl,
12621372
return rv;
12631373
}
12641374

1375+
#if MEMFAULT_METRICS_SESSIONS_ENABLED
1376+
prv_session_check_for_unexpected_reboot();
1377+
#endif
1378+
12651379
#if MEMFAULT_PLATFORM_METRICS_CONNECTIVITY_BOOT
12661380
memfault_platform_metrics_connectivity_boot();
12671381
#endif

0 commit comments

Comments
 (0)