Skip to content

Commit aaa298a

Browse files
author
Memfault Inc
committed
Memfault Firmware SDK 0.37.0 (Build 971)
1 parent cbc518e commit aaa298a

24 files changed

+579
-154
lines changed

.cyignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
cmake
2+
components/_feature_stubs
3+
components/_sortme
24
examples
5+
internal
36
makefile
47
ports/atmel
58
ports/dialog

CHANGES.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,34 @@
1+
### Changes between Memfault SDK 0.37.0 and SDK 0.36.1 - Dec 16, 2022
2+
3+
#### :chart_with_upwards_trend: Improvements
4+
5+
- Built-in Metrics
6+
7+
- Add `MemfaultSdkMetric_UnexpectedRebootDidOccur` metric. This metric uses
8+
the platform's reboot register and any reasons by the SDK function
9+
`memfault_reboot_tracking_mark_reset_imminent` to classify a reboot. When
10+
reboot tracking determines a reboot is unexpected, this metric is set to 1.
11+
Otherwise this metric is 0.
12+
13+
- [ModusToolbox:tm: Software](https://www.infineon.com/cms/en/design-support/tools/sdk/modustoolbox-software/)
14+
15+
- Add log capture during coredump to port
16+
17+
- Demo CLI
18+
- Add `mflt test loadaddr` command. This comamnd is used to test specific
19+
faults due to protected regions
20+
21+
#### :boom: Breaking Changes
22+
23+
- Built-in Metrics
24+
- The built-in metric, `MemfaultSdkMetric_UnexpectedRebootDidOccur`,
25+
classifies all reboot reasons greater than or equal to
26+
`kMfltRebootReason_UnknownError` **or** equal to `kMfltRebootReason_Unknown`
27+
as "unexpected reboots". It is recommended to ensure your platform's
28+
implementation of `memfault_reboot_reason_get` classifies the reboot
29+
register values as accurately and precisely as possible to avoid incorrect
30+
metric values.
31+
132
### Changes between Memfault SDK 0.36.1 and SDK 0.36.0 - Dec 9, 2022
233

334
#### :chart_with_upwards_trend: Improvements

VERSION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
BUILD ID: 874
2-
GIT COMMIT: 5402c68cc
1+
BUILD ID: 971
2+
GIT COMMIT: fdf6fee86

components/core/src/memfault_ram_reboot_info_tracking.c

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,19 @@ MEMFAULT_STATIC_ASSERT(sizeof(sMfltRebootInfo) == MEMFAULT_REBOOT_TRACKING_REGIO
5858

5959
static sMfltRebootInfo *s_mflt_reboot_info;
6060

61+
//! Struct to retrieve reboot reason data from. Matches the fields of sMfltRebootReason
62+
//! as documented in reboot_tracking.h
63+
typedef struct {
64+
eMemfaultRebootReason reboot_reg_reason;
65+
eMemfaultRebootReason prior_stored_reason;
66+
bool is_valid;
67+
} sMfltRebootReasonData;
68+
69+
// Private struct to store reboot reason after reboot tracking is initialized
70+
static sMfltRebootReasonData s_reboot_reason_data = {
71+
.is_valid = false,
72+
};
73+
6174
static bool prv_check_or_init_struct(void) {
6275
if (s_mflt_reboot_info == NULL) {
6376
return false;
@@ -93,11 +106,50 @@ static bool prv_read_reset_info(sMfltResetReasonInfo *info) {
93106
return true;
94107
}
95108

109+
//! Records reboot reasons from reboot register and prior saved reboot
110+
//!
111+
//! Stores both the new reboot reason derived from a platform's reboot register and
112+
//! any previously saved reboot reason. If there is no previously stored reboot reason,
113+
//! the reboot register reason is used.
114+
//!
115+
//! @param reboot_reg_reason New reboot reason from this boot
116+
//! @param prior_stored_reason Prior reboot reason stored in s_mflt_reboot_info
117+
static void prv_record_reboot_reason(eMemfaultRebootReason reboot_reg_reason,
118+
eMemfaultRebootReason prior_stored_reason) {
119+
s_reboot_reason_data.reboot_reg_reason = reboot_reg_reason;
120+
121+
if (prior_stored_reason != (eMemfaultRebootReason)MEMFAULT_REBOOT_REASON_NOT_SET) {
122+
s_reboot_reason_data.prior_stored_reason = prior_stored_reason;
123+
} else {
124+
s_reboot_reason_data.prior_stored_reason = reboot_reg_reason;
125+
}
126+
127+
s_reboot_reason_data.is_valid = true;
128+
}
129+
130+
static bool prv_get_unexpected_reboot_occurred(void) {
131+
// Check prior_stored_reason, reboot is unexpected if prior reason is set and in error range or
132+
// unknown
133+
if (s_reboot_reason_data.prior_stored_reason !=
134+
(eMemfaultRebootReason)MEMFAULT_REBOOT_REASON_NOT_SET) {
135+
if (s_reboot_reason_data.prior_stored_reason == kMfltRebootReason_Unknown ||
136+
s_reboot_reason_data.prior_stored_reason >= kMfltRebootReason_UnknownError) {
137+
return true;
138+
}
139+
}
140+
141+
// Check reboot_reg_reason second, reboot is unexpected if in error range or unknown
142+
return (s_reboot_reason_data.reboot_reg_reason == kMfltRebootReason_Unknown ||
143+
s_reboot_reason_data.reboot_reg_reason >= kMfltRebootReason_UnknownError);
144+
}
145+
96146
static void prv_record_reboot_event(eMemfaultRebootReason reboot_reason,
97147
const sMfltRebootTrackingRegInfo *reg) {
98-
if (reboot_reason >= kMfltRebootReason_UnknownError) {
99-
s_mflt_reboot_info->crash_count++;
100-
}
148+
// Store both the new reason reported by hardware and the current recorded reason
149+
// The combination of these will be used to determine if the bootup was expected
150+
// by the metrics subsystem
151+
// s_mflt_reboot_info can be cleared by any call to memfault_reboot_tracking_collect_reset_info
152+
prv_record_reboot_reason(reboot_reason, s_mflt_reboot_info->last_reboot_reason);
101153

102154
if (s_mflt_reboot_info->last_reboot_reason != MEMFAULT_REBOOT_REASON_NOT_SET) {
103155
// we are already tracking a reboot. We don't overwrite this because generally the first reboot
@@ -132,6 +184,10 @@ void memfault_reboot_tracking_boot(
132184
}
133185

134186
prv_record_reboot_event(reset_reason, NULL);
187+
188+
if (prv_get_unexpected_reboot_occurred()) {
189+
s_mflt_reboot_info->crash_count++;
190+
}
135191
}
136192

137193
void memfault_reboot_tracking_mark_reset_imminent(eMemfaultRebootReason reboot_reason,
@@ -190,3 +246,31 @@ void memfault_reboot_tracking_mark_coredump_saved(void) {
190246

191247
s_mflt_reboot_info->coredump_saved = 1;
192248
}
249+
250+
int memfault_reboot_tracking_get_reboot_reason(sMfltRebootReason *reboot_reason) {
251+
if (reboot_reason == NULL || !s_reboot_reason_data.is_valid) {
252+
return -1;
253+
}
254+
255+
*reboot_reason = (sMfltRebootReason){
256+
.reboot_reg_reason = s_reboot_reason_data.reboot_reg_reason,
257+
.prior_stored_reason = s_reboot_reason_data.prior_stored_reason,
258+
};
259+
260+
return 0;
261+
}
262+
263+
int memfault_reboot_tracking_get_unexpected_reboot_occurred(bool *unexpected_reboot_occurred) {
264+
if (unexpected_reboot_occurred == NULL || !s_reboot_reason_data.is_valid) {
265+
return -1;
266+
}
267+
268+
*unexpected_reboot_occurred = prv_get_unexpected_reboot_occurred();
269+
return 0;
270+
}
271+
272+
void memfault_reboot_tracking_clear_reboot_reason(void) {
273+
s_reboot_reason_data = (sMfltRebootReasonData){
274+
.is_valid = false,
275+
};
276+
}

components/core/src/memfault_reboot_tracking_private.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ typedef struct MfltResetReasonInfo {
2828
//! Clears any crash information which was stored
2929
void memfault_reboot_tracking_clear_reset_info(void);
3030

31+
//! Clears stored reboot reason stored at bootup
32+
void memfault_reboot_tracking_clear_reboot_reason(void);
33+
3134
bool memfault_reboot_tracking_read_reset_info(sMfltResetReasonInfo *info);
3235

3336
#ifdef __cplusplus

components/demo/src/panics/memfault_demo_panics.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//! @brief
77
//! CLI commands which require integration of the "panic" component.
88

9+
#include <inttypes.h>
910
#include <stdlib.h>
1011

1112
#include "memfault/core/arch.h"
@@ -138,7 +139,8 @@ int memfault_demo_cli_cmd_memmanage(MEMFAULT_UNUSED int argc, MEMFAULT_UNUSED ch
138139
// System space, that is, for addresses 0xE0000000 and higher. System space is always marked as
139140
// XN, Execute Never."
140141
//
141-
// So we can trip a MemManage exception by simply attempting to execute any addresss >= 0xE000.0000
142+
// So we can trip a MemManage exception by simply attempting to execute any addresss >=
143+
// 0xE000.0000
142144
void (*bad_func)(void) = (void (*)(void))0xEEEEDEAD;
143145
bad_func();
144146

@@ -164,4 +166,16 @@ int memfault_demo_cli_cmd_usagefault(MEMFAULT_UNUSED int argc, MEMFAULT_UNUSED c
164166
return -1;
165167
}
166168

169+
int memfault_demo_cli_loadaddr(int argc, char *argv[]) {
170+
if (argc < 2) {
171+
MEMFAULT_LOG_ERROR("Usage: loadaddr <addr>");
172+
return -1;
173+
}
174+
uint32_t addr = (uint32_t)strtoul(argv[1], NULL, 0);
175+
uint32_t val = *(uint32_t *)addr;
176+
177+
MEMFAULT_LOG_INFO("Read 0x%08" PRIx32 " from 0x%08" PRIx32, val, (uint32_t)(uintptr_t)addr);
178+
return 0;
179+
}
180+
167181
#endif /* MEMFAULT_COMPILER_ARM */

components/include/memfault/core/reboot_reason_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ extern "C" {
1313
#endif
1414

1515
typedef enum MfltResetReason {
16+
// A reboot reason was not determined either by hardware or a previously marked reboot reason
17+
// This reason is classified as an unexpected reboot when used by the built-in metric
18+
// MemfaultSdkMetric_UnexpectedRebootDidOccur
1619
kMfltRebootReason_Unknown = 0x0000,
1720

1821
//

components/include/memfault/core/reboot_tracking.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,21 @@ typedef struct BootupInfo {
5050
eMemfaultRebootReason reset_reason;
5151
} sResetBootupInfo;
5252

53+
//! Helper structure for storing/retrieving the device's reboot reason
54+
typedef struct MfltRebootType {
55+
//! Stores the reboot reason determined from hardware during the current boot
56+
eMemfaultRebootReason reboot_reg_reason;
57+
//! Stores the reboot reason as read from s_mflt_reboot_info. This could be set in
58+
//! the prior boot from either:
59+
//! * the application using memfault_reboot_tracking_mark_reset_imminent (fault handler, firmware
60+
//! update, etc)
61+
//! * a reason determined from the reboot register at bootup
62+
eMemfaultRebootReason prior_stored_reason;
63+
} sMfltRebootReason;
64+
65+
//! Value used to determine state of reboot tracking data
66+
#define MEMFAULT_REBOOT_REASON_NOT_SET 0xffffffff
67+
5368
#define MEMFAULT_REBOOT_TRACKING_REGION_SIZE 64
5469

5570
//! Sets the memory region used for reboot tracking.
@@ -125,6 +140,25 @@ void memfault_reboot_tracking_reset_crash_count(void);
125140
//! never need to be called by an end user directly
126141
void memfault_reboot_tracking_mark_coredump_saved(void);
127142

143+
//! Get the reported reboot reason from boot
144+
//!
145+
//! Each time the device boots, the reboot reason mapped from the platform reboot register is
146+
//! stored. This can be used either by other subsystems or users of the SDK.
147+
//!
148+
//! @param reboot_reason Pointer to store the reboot reason from boot
149+
//! @return 0 on success or 1 if the reboot reason is invalid
150+
//! or the input parameter is NULL
151+
152+
int memfault_reboot_tracking_get_reboot_reason(sMfltRebootReason *reboot_reason);
153+
154+
//! Returns a boolean representing whether an unexpected reboot occurred from boot
155+
//!
156+
//! This function uses a reboot reason from a reboot register and the prior reboot reason (if
157+
//! present) to determine if a reboot was unexpected.
158+
//!
159+
//! @param unexpected_reboot_occurred Pointer to store boolean marking an unexpected reboot
160+
//! @return 0 on success, or 1 if the result is invalid or the input parameter is NULL
161+
int memfault_reboot_tracking_get_unexpected_reboot_occurred(bool *unexpected_reboot_occurred);
128162

129163
#ifdef __cplusplus
130164
}

components/include/memfault/demo/cli.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ 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+
//! Read a 32-bit memory address and print the value. Can be used to test
43+
//! specific faults due to protected regions
44+
int memfault_demo_cli_loadaddr(int argc, char *argv[]);
45+
4246
#endif /* MEMFAULT_COMPILER_ARM */
4347

4448
//! Command which will generate an assert

components/include/memfault/metrics/heartbeat_config.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
MEMFAULT_METRICS_KEY_DEFINE(MemfaultSdkMetric_IntervalMs, kMemfaultMetricType_Timer)
77
// The number of reboots that have taken place since the last heartbeat was collected
88
MEMFAULT_METRICS_KEY_DEFINE(MemfaultSdkMetric_UnexpectedRebootCount, kMemfaultMetricType_Unsigned)
9+
MEMFAULT_METRICS_KEY_DEFINE_WITH_RANGE(MemfaultSdkMetric_UnexpectedRebootDidOccur, kMemfaultMetricType_Unsigned, 0, 1)

0 commit comments

Comments
 (0)