@@ -58,6 +58,19 @@ MEMFAULT_STATIC_ASSERT(sizeof(sMfltRebootInfo) == MEMFAULT_REBOOT_TRACKING_REGIO
58
58
59
59
static sMfltRebootInfo * s_mflt_reboot_info ;
60
60
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
+
61
74
static bool prv_check_or_init_struct (void ) {
62
75
if (s_mflt_reboot_info == NULL ) {
63
76
return false;
@@ -93,11 +106,50 @@ static bool prv_read_reset_info(sMfltResetReasonInfo *info) {
93
106
return true;
94
107
}
95
108
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
+
96
146
static void prv_record_reboot_event (eMemfaultRebootReason reboot_reason ,
97
147
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 );
101
153
102
154
if (s_mflt_reboot_info -> last_reboot_reason != MEMFAULT_REBOOT_REASON_NOT_SET ) {
103
155
// 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(
132
184
}
133
185
134
186
prv_record_reboot_event (reset_reason , NULL );
187
+
188
+ if (prv_get_unexpected_reboot_occurred ()) {
189
+ s_mflt_reboot_info -> crash_count ++ ;
190
+ }
135
191
}
136
192
137
193
void memfault_reboot_tracking_mark_reset_imminent (eMemfaultRebootReason reboot_reason ,
@@ -190,3 +246,31 @@ void memfault_reboot_tracking_mark_coredump_saved(void) {
190
246
191
247
s_mflt_reboot_info -> coredump_saved = 1 ;
192
248
}
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
+ }
0 commit comments