Skip to content

Commit 7d3396b

Browse files
author
Memfault Inc
committed
Memfault Firmware SDK 0.30.0 (Build 421632)
1 parent b7eea3b commit 7d3396b

32 files changed

+1730
-403
lines changed

CHANGES.md

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,28 @@
1+
### Changes between Memfault SDK 0.30.0 and SDK 0.29.1 - Mar 31, 2022
2+
3+
#### :rocket: New Features
4+
5+
- Added a Task Watchdog optional module. This can be used to monitor and trigger
6+
a fault in the case of a task or thread that becomes stuck. See information in
7+
[components/include/memfault/core/task_watchdog.h](components/include/memfault/core/task_watchdog.h)
8+
for how to configure and use the module
9+
10+
#### :chart_with_upwards_trend: Improvements
11+
12+
- Fix compilation when building for a Zephyr target that does not have the
13+
`CONFIG_ARM_MPU` flag enabled
14+
- Fix compilation errors to enable compatibility with Zephyr v3.0.0
15+
116
### Changes between Memfault SDK 0.29.1 and SDK 0.29.0 - Mar 16, 2022
217

318
#### :house: Internal
419

5-
- Updated Memfault Diagnostic GATT Service (MDS) based on feedback. This service can
6-
be used to transparently forward data collected by the SDK to a Bluetooth Low
7-
Energy gateway and proxied to the cloud. See
20+
- Updated Memfault Diagnostic GATT Service (MDS) based on feedback. This service
21+
can be used to transparently forward data collected by the SDK to a Bluetooth
22+
Low Energy gateway and proxied to the cloud. See
823
[ports/include/memfault/ports/ble/mds.h](ports/include/memfault/ports/ble/mds.h#L1)
9-
- Updated Mbed OS invoke commands to be more resilient against python package conflicts
24+
- Updated Mbed OS invoke commands to be more resilient against python package
25+
conflicts
1026

1127
#### :boom: Breaking Changes
1228

VERSION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
BUILD ID: 412506
2-
GIT COMMIT: f81a4f865
1+
BUILD ID: 421632
2+
GIT COMMIT: 92115a2ee
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//! @file
2+
//!
3+
//! Copyright (c) Memfault, Inc.
4+
//! See License.txt for details
5+
//!
6+
//! Task watchdog implementation.
7+
8+
#include "memfault/core/task_watchdog.h"
9+
#include "memfault/core/task_watchdog_impl.h"
10+
11+
//! non-module definitions
12+
13+
#include <stdbool.h>
14+
#include <stddef.h>
15+
#include <stdint.h>
16+
17+
#include "memfault/config.h"
18+
#include "memfault/core/compiler.h"
19+
#include "memfault/core/math.h"
20+
#include "memfault/core/platform/core.h"
21+
#include "memfault/panics/assert.h"
22+
23+
#if MEMFAULT_TASK_WATCHDOG_ENABLE
24+
25+
sMemfaultTaskWatchdogInfo g_memfault_task_channel_info;
26+
27+
//! Catch if the timeout is set to an incompatible literal
28+
static const uint32_t s_watchdog_timeout_ms = MEMFAULT_TASK_WATCHDOG_TIMEOUT_INTERVAL_MS;
29+
30+
void memfault_task_watchdog_init(void) {
31+
g_memfault_task_channel_info = (struct MemfaultTaskWatchdogInfo){0};
32+
}
33+
34+
static bool prv_memfault_task_watchdog_expired(struct MemfaultTaskWatchdogChannel channel,
35+
uint64_t current_time_ms) {
36+
const bool active = channel.state == kMemfaultTaskWatchdogChannelState_Started;
37+
// const bool expired = (channel.fed_time_ms + s_watchdog_timeout_ms) < current_time_ms;
38+
const bool expired = (current_time_ms - channel.fed_time_ms) > s_watchdog_timeout_ms;
39+
40+
return active && expired;
41+
}
42+
43+
static size_t prv_memfault_task_watchdog_do_check(void) {
44+
const uint32_t time_since_boot_ms = memfault_platform_get_time_since_boot_ms();
45+
46+
size_t expired_channels_count = 0;
47+
for (size_t i = 0; i < MEMFAULT_ARRAY_SIZE(g_memfault_task_channel_info.channels); i++) {
48+
if (prv_memfault_task_watchdog_expired(g_memfault_task_channel_info.channels[i],
49+
time_since_boot_ms)) {
50+
expired_channels_count++;
51+
}
52+
}
53+
54+
return expired_channels_count;
55+
}
56+
57+
void memfault_task_watchdog_check_all(void) {
58+
size_t expired_channels_count = prv_memfault_task_watchdog_do_check();
59+
60+
// if any channel reached expiration, trigger a panic
61+
if (expired_channels_count > 0) {
62+
MEMFAULT_SOFTWARE_WATCHDOG();
63+
} else {
64+
memfault_task_watchdog_platform_refresh_callback();
65+
}
66+
}
67+
68+
void memfault_task_watchdog_bookkeep(void) {
69+
// only update the internal structure, don't trigger callbacks
70+
(void)prv_memfault_task_watchdog_do_check();
71+
}
72+
73+
void memfault_task_watchdog_start(eMemfaultTaskWatchdogChannel channel_id) {
74+
g_memfault_task_channel_info.channels[channel_id].fed_time_ms =
75+
memfault_platform_get_time_since_boot_ms();
76+
g_memfault_task_channel_info.channels[channel_id].state =
77+
kMemfaultTaskWatchdogChannelState_Started;
78+
}
79+
80+
void memfault_task_watchdog_feed(eMemfaultTaskWatchdogChannel channel_id) {
81+
g_memfault_task_channel_info.channels[channel_id].fed_time_ms =
82+
memfault_platform_get_time_since_boot_ms();
83+
}
84+
85+
void memfault_task_watchdog_stop(eMemfaultTaskWatchdogChannel channel_id) {
86+
g_memfault_task_channel_info.channels[channel_id].state =
87+
kMemfaultTaskWatchdogChannelState_Stopped;
88+
}
89+
90+
//! Callback which is called when there are no expired tasks; can be used for
91+
//! example to reset a hardware watchdog
92+
MEMFAULT_WEAK void memfault_task_watchdog_platform_refresh_callback(void) {}
93+
94+
#else // MEMFAULT_TASK_WATCHDOG_ENABLE
95+
96+
void memfault_task_watchdog_bookkeep(void) {}
97+
98+
#endif // MEMFAULT_TASK_WATCHDOG_ENABLE

components/include/memfault/components.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ extern "C" {
4040
#include "memfault/core/platform/system_time.h"
4141
#include "memfault/core/reboot_reason_types.h"
4242
#include "memfault/core/reboot_tracking.h"
43+
#include "memfault/core/task_watchdog.h"
4344
#include "memfault/core/sdk_assert.h"
4445
#include "memfault/core/trace_event.h"
4546
#include "memfault/core/data_packetizer.h"
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#pragma once
2+
3+
//! @file
4+
//!
5+
//! Copyright (c) Memfault, Inc.
6+
//! See License.txt for details
7+
//!
8+
//! @brief
9+
//! Task watchdog API.
10+
//!
11+
//! This module implements a task watchdog that can be used to detect stuck RTOS
12+
//! tasks.
13+
//!
14+
//! Example usage:
15+
//!
16+
//! // Initialize the task watchdog system on system start
17+
//! memfault_task_watchdog_init();
18+
//!
19+
//! // In a task loop
20+
//! void example_task_loop(void) {
21+
//! while(1) {
22+
//! rtos_wait_for_task_to_wake_up();
23+
//!
24+
//! // Example: Use the task watchdog to monitor a block of work
25+
//! MEMFAULT_TASK_WATCHDOG_START(example_task_loop_channel_id);
26+
//! // do work that should be monitored by the watchdog
27+
//! MEMFAULT_TASK_WATCHDOG_STOP(example_task_loop_channel_id);
28+
//!
29+
//! // Example: Use the task watchdog to monitor a repeated operation
30+
//! MEMFAULT_TASK_WATCHDOG_START(example_task_loop_channel_id);
31+
//! // feeding the watchdog is only necessary if in some long-running task
32+
//! // that runs the risk of expiring the timeout, but is not expected to be
33+
//! // stuck in between calls
34+
//! for (size_t i = 0; i < 100; i++) {
35+
//! MEMFAULT_TASK_WATCHDOG_FEED(example_task_loop_channel_id);
36+
//! run_slow_repeated_task();
37+
//! }
38+
//! MEMFAULT_TASK_WATCHDOG_STOP(example_task_loop_channel_id);
39+
//!
40+
//! rtos_put_task_to_sleep();
41+
//! }
42+
//! }
43+
//!
44+
//! // In either a standalone timer, or a periodic background task, call the
45+
//! // memfault_task_watchdog_check_all function
46+
//! void example_task_watchdog_timer_cb(void) {
47+
//! memfault_task_watchdog_check_all();
48+
//! }
49+
//!
50+
//! // Call memfault_task_watchdog_bookkeep() in
51+
//! // memfault_platform_coredump_save_begin()- this updates all the task
52+
//! // channel timeouts, in the event that the task monitor wasn't able to run
53+
//! // for some reason. Also might be appropriate to refresh other system
54+
//! // watchdogs prior to executing the coredump save.
55+
//! bool memfault_platform_coredump_save_begin(void) {
56+
//! memfault_task_watchdog_bookkeep();
57+
//! // may also need to refresh other watchdogs here, for example:
58+
//! memfault_task_watchdog_platform_refresh_callback();
59+
//! return true;
60+
//! }
61+
62+
#include <stddef.h>
63+
64+
#include "memfault/config.h"
65+
66+
#ifdef __cplusplus
67+
extern "C" {
68+
#endif
69+
70+
//! Declare the task watchdog channel IDs. These shouldn't be used directly, but
71+
//! should be passed to the MEMFAULT_TASK_WATCHDOG_START etc. functions with the
72+
//! name declared in the memfault_task_watchdog_config.def file.
73+
#define MEMFAULT_TASK_WATCHDOG_CHANNEL_DEFINE(channel_) kMemfaultTaskWatchdogChannel_##channel_,
74+
typedef enum {
75+
#if MEMFAULT_TASK_WATCHDOG_ENABLE
76+
#include "memfault_task_watchdog_config.def"
77+
#else
78+
// define one channel to prevent the compiler from complaining about a zero-length array
79+
MEMFAULT_TASK_WATCHDOG_CHANNEL_DEFINE(placeholder_)
80+
#endif
81+
kMemfaultTaskWatchdogChannel_NumChannels,
82+
} eMemfaultTaskWatchdogChannel;
83+
#undef MEMFAULT_TASK_WATCHDOG_CHANNEL_DEFINE
84+
#define MEMFAULT_TASK_WATCHDOG_CHANNEL_DEFINE(channel_) kMemfaultTaskWatchdogChannel_##channel_
85+
86+
//! Initialize (or reset) the task watchdog system. This will stop and reset all
87+
//! internal bookkeeping for all channels.
88+
void memfault_task_watchdog_init(void);
89+
90+
//! This function should be called periodically (for example, around the
91+
//! MEMFAULT_TASK_WATCHDOG_TIMEOUT_INTERVAL_MS period). It checks if any task
92+
//! watchdog channel has reached the timeout interval. If so, it will trigger a
93+
//! task watchdog assert.
94+
void memfault_task_watchdog_check_all(void);
95+
96+
//! As in `memfault_task_watchdog_check_all`, but only updates the internal
97+
//! bookkeeping, and does not trigger any callbacks or asserts.
98+
//!
99+
//! Intended to be called just prior to coredump capture when the system is in
100+
//! the fault_handler.
101+
void memfault_task_watchdog_bookkeep(void);
102+
103+
//! Start a task watchdog channel. After being started, a channel will now be
104+
//! eligible for expiration. Also resets the timeout interval for the channel.
105+
#define MEMFAULT_TASK_WATCHDOG_START(channel_id_) \
106+
memfault_task_watchdog_start(MEMFAULT_TASK_WATCHDOG_CHANNEL_DEFINE(channel_id_))
107+
108+
//! Reset the timeout interval for a task watchdog channel.
109+
#define MEMFAULT_TASK_WATCHDOG_FEED(channel_id_) \
110+
memfault_task_watchdog_feed(MEMFAULT_TASK_WATCHDOG_CHANNEL_DEFINE(channel_id_))
111+
112+
//! Stop a task watchdog channel. After being stopped, a channel will no longer
113+
//! be eligible for expiration and is reset
114+
#define MEMFAULT_TASK_WATCHDOG_STOP(channel_id_) \
115+
memfault_task_watchdog_stop(MEMFAULT_TASK_WATCHDOG_CHANNEL_DEFINE(channel_id_))
116+
117+
//! These functions should not be used directly, but instead through the macros
118+
//! above.
119+
void memfault_task_watchdog_start(eMemfaultTaskWatchdogChannel channel_id);
120+
void memfault_task_watchdog_feed(eMemfaultTaskWatchdogChannel channel_id);
121+
void memfault_task_watchdog_stop(eMemfaultTaskWatchdogChannel channel_id);
122+
123+
//! Optional weakly defined function to perform any additional actions during
124+
//! `memfault_task_watchdog_check_all` when no channels have expired
125+
void memfault_task_watchdog_platform_refresh_callback(void);
126+
127+
#ifdef __cplusplus
128+
}
129+
#endif
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#pragma once
2+
3+
//! @file
4+
//!
5+
//! Copyright (c) Memfault, Inc.
6+
//! See License.txt for details
7+
//!
8+
//! @brief
9+
//!
10+
//! Task watchdog APIs intended for use within the memfault-firmware-sdk
11+
12+
#include <stdbool.h>
13+
#include <stddef.h>
14+
#include <stdint.h>
15+
16+
#include "memfault/config.h"
17+
18+
// Keep this after config.h
19+
#include "memfault/core/task_watchdog.h"
20+
21+
#ifdef __cplusplus
22+
extern "C" {
23+
#endif
24+
25+
enum MemfaultTaskWatchdogChannelState {
26+
kMemfaultTaskWatchdogChannelState_Stopped = 0,
27+
kMemfaultTaskWatchdogChannelState_Started,
28+
kMemfaultTaskWatchdogChannelState_Expired,
29+
};
30+
struct MemfaultTaskWatchdogChannel {
31+
// Using a 32-bit value to track fed_time. This is enough for 49 days, which
32+
// should be much longer than any watchdog timeout.
33+
uint32_t fed_time_ms;
34+
enum MemfaultTaskWatchdogChannelState state;
35+
};
36+
typedef struct MemfaultTaskWatchdogInfo {
37+
struct MemfaultTaskWatchdogChannel channels[kMemfaultTaskWatchdogChannel_NumChannels];
38+
} sMemfaultTaskWatchdogInfo;
39+
40+
//! Bookkeeping for the task watchdog channels. If the structure needs to change
41+
//! in the future, rename it to keep analyzer compatibility (eg "_v2")
42+
extern sMemfaultTaskWatchdogInfo g_memfault_task_channel_info;
43+
44+
#ifdef __cplusplus
45+
}
46+
#endif

components/include/memfault/default_config.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ extern "C" {
177177
#define MEMFAULT_COREDUMP_COLLECT_LOG_REGIONS 0
178178
#endif
179179

180+
//
181+
// Heap Statistics Configuration
182+
//
183+
180184
//! When the FreeRTOS port is being used, controls whether or not heap
181185
//! allocation tracking is enabled.
182186
//! Note: When using this feature, MEMFAULT_COREDUMP_HEAP_STATS_LOCK_ENABLE 0
@@ -203,6 +207,33 @@ extern "C" {
203207
#define MEMFAULT_COREDUMP_HEAP_STATS_LOCK_ENABLE 1
204208
#endif
205209

210+
//
211+
// Task Watchdog Configuration
212+
//
213+
214+
//! Use this flag to enable the task watchdog component. See the header file at
215+
//! components/include/memfault/core/task_watchdog.h for usage details.
216+
#ifndef MEMFAULT_TASK_WATCHDOG_ENABLE
217+
#define MEMFAULT_TASK_WATCHDOG_ENABLE 0
218+
#endif
219+
220+
//! Configure the task watchdog timeout value in milliseconds.
221+
#ifndef MEMFAULT_TASK_WATCHDOG_TIMEOUT_INTERVAL_MS
222+
#define MEMFAULT_TASK_WATCHDOG_TIMEOUT_INTERVAL_MS 1000
223+
#endif
224+
225+
//! Enable this flag to collect the task watchdog information on coredump. Only
226+
//! needed if the entire memory contents are not already collected on coredump.
227+
#ifndef MEMFAULT_COREDUMP_COLLECT_TASK_WATCHDOG_REGION
228+
#define MEMFAULT_COREDUMP_COLLECT_TASK_WATCHDOG_REGION 0
229+
#endif
230+
231+
//
232+
// Trace Configuration
233+
//
234+
235+
//! Set the name for the user trace reason config file, which is where custom
236+
//! trace reasons can be defined
206237
#ifndef MEMFAULT_TRACE_REASON_USER_DEFS_FILE
207238
#define MEMFAULT_TRACE_REASON_USER_DEFS_FILE \
208239
"memfault_trace_reason_user_config.def"

components/include/memfault/panics/fault_handling.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ MEMFAULT_NORETURN
105105
#endif
106106
void memfault_fault_handling_assert_extra(void *pc, void *lr, sMemfaultAssertInfo *extra_info);
107107

108+
//! Handler called in all system-specific fault_handlers, to perform generic
109+
//! bookkeeping or other operations shared by all fault handlers.
110+
void memfault_fault_handling_common(void);
111+
108112
#ifdef __cplusplus
109113
}
110114
#endif

components/include/memfault/version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ typedef struct {
1919
uint8_t patch;
2020
} sMfltSdkVersion;
2121

22-
#define MEMFAULT_SDK_VERSION { .major = 0, .minor = 29, .patch = 1 }
22+
#define MEMFAULT_SDK_VERSION { .major = 0, .minor = 30, .patch = 0 }
2323

2424
#ifdef __cplusplus
2525
}

0 commit comments

Comments
 (0)