Skip to content

Commit 5d57753

Browse files
author
Memfault Inc
committed
Memfault Firmware SDK 1.1.2 (Build 2861)
1 parent 73ec7b7 commit 5d57753

File tree

19 files changed

+159
-91
lines changed

19 files changed

+159
-91
lines changed

CHANGES.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
### Changes between Memfault SDK 1.1.1 and 1.1.2 - July 11, 2023
2+
3+
#### :chart_with_upwards_trend: Improvements
4+
5+
- Improve compatibility in
6+
[reboot reason tracking](ports/emlib/rmu_reboot_tracking.c) and
7+
[watchdog implementation](ports/emlib/wdog_software_watchdog.c) on Silicon
8+
Labs Series 2 MCUs
9+
10+
- Zephyr:
11+
- Fix a build error when `CONFIG_MEMFAULT_LOGGING=n`, see
12+
[#56](https://github.com/memfault/memfault-firmware-sdk/issues/56). Thanks
13+
to @JordanYates for reporting this issue!
14+
- Fix a potential bug in the Memfault Log Backend when
15+
`CONFIG_LOG_MODE_IMMEDIATE=y` when flushing of fault logs during a crash
16+
117
### Changes between Memfault SDK 1.1.0 and 1.1.1 - June 30, 2023
218

319
#### :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: 2709
2-
GIT COMMIT: c403952a4
1+
BUILD ID: 2861
2+
GIT COMMIT: 3a1297110

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 = 1, .minor = 1, .patch = 1 }
22+
#define MEMFAULT_SDK_VERSION { .major = 1, .minor = 1, .patch = 2 }
2323

2424
#ifdef __cplusplus
2525
}

ports/emlib/README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Silicon Labs emlib Port
2+
3+
This port adds implementations for coredump storage, reboot reasons, and
4+
watchdog features using the Gecko SDK/emblib.
5+
6+
## Compatibility
7+
8+
The port has been built against v3.0 of the Gecko SDK. The port has been built
9+
and tested against v4.3.0 using SimplicityStudio.
10+
11+
## Features
12+
13+
The port provides the following features:
14+
15+
- Coredump storage using a linker-defined region in internal Flash
16+
- Reboot reason implementation for collecting reboot events
17+
- An integration with the Watchdog peripheral to capture watchdog-triggered
18+
traces
19+
20+
## Adding To Your Project
21+
22+
The simplest way to add this to your project is to do the following:
23+
24+
1. Add the source files in `ports/emblib` to your build system
25+
2. Add the include directory at `ports/include`

ports/emlib/rmu_reboot_tracking.c

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,19 @@
1212

1313
#include "memfault/ports/reboot_reason.h"
1414

15-
#include "em_rmu.h"
15+
// non-module headers below
16+
#include "em_device.h"
1617
#include "em_emu.h"
17-
18+
#include "em_rmu.h"
1819
#include "memfault/config.h"
1920
#include "memfault/core/debug_log.h"
2021
#include "memfault/core/reboot_reason_types.h"
2122
#include "memfault/core/sdk_assert.h"
2223

2324
#if MEMFAULT_ENABLE_REBOOT_DIAG_DUMP
24-
#define MEMFAULT_PRINT_RESET_INFO(...) MEMFAULT_LOG_INFO(__VA_ARGS__)
25+
#define MEMFAULT_PRINT_RESET_INFO(...) MEMFAULT_LOG_INFO(__VA_ARGS__)
2526
#else
26-
#define MEMFAULT_PRINT_RESET_INFO(...)
27+
#define MEMFAULT_PRINT_RESET_INFO(...)
2728
#endif
2829

2930
#if defined(_RMU_RSTCAUSE_MASK)
@@ -36,21 +37,21 @@ static eMemfaultRebootReason prv_get_and_print_reason(uint32_t reset_cause) {
3637
if (reset_cause & RMU_RSTCAUSE_PORST) {
3738
MEMFAULT_PRINT_RESET_INFO(" Power on Reset");
3839
return kMfltRebootReason_PowerOnReset;
39-
#if defined(RMU_RSTCAUSE_AVDDBOD)
40+
#if defined(RMU_RSTCAUSE_AVDDBOD)
4041
} else if (reset_cause & RMU_RSTCAUSE_AVDDBOD) {
4142
MEMFAULT_PRINT_RESET_INFO(" AVDD Brown Out");
4243
return kMfltRebootReason_BrownOutReset;
43-
#endif
44-
#if defined(RMU_RSTCAUSE_DVDDBOD)
44+
#endif
45+
#if defined(RMU_RSTCAUSE_DVDDBOD)
4546
} else if (reset_cause & RMU_RSTCAUSE_DVDDBOD) {
4647
MEMFAULT_PRINT_RESET_INFO(" DVDD Brown Out");
4748
return kMfltRebootReason_BrownOutReset;
48-
#endif
49-
#if defined(RMU_RSTCAUSE_DECBOD)
49+
#endif
50+
#if defined(RMU_RSTCAUSE_DECBOD)
5051
} else if (reset_cause & RMU_RSTCAUSE_DECBOD) {
5152
MEMFAULT_PRINT_RESET_INFO(" DEC Brown Out");
5253
return kMfltRebootReason_BrownOutReset;
53-
#endif
54+
#endif
5455
} else if (reset_cause & RMU_RSTCAUSE_LOCKUPRST) {
5556
MEMFAULT_PRINT_RESET_INFO(" Lockup");
5657
return kMfltRebootReason_Lockup;
@@ -60,11 +61,11 @@ static eMemfaultRebootReason prv_get_and_print_reason(uint32_t reset_cause) {
6061
} else if (reset_cause & RMU_RSTCAUSE_WDOGRST) {
6162
MEMFAULT_PRINT_RESET_INFO(" Watchdog");
6263
return kMfltRebootReason_HardwareWatchdog;
63-
#if defined(RMU_RSTCAUSE_EM4WURST)
64+
#if defined(RMU_RSTCAUSE_EM4WURST)
6465
} else if (reset_cause & RMU_RSTCAUSE_EM4RST) {
6566
MEMFAULT_PRINT_RESET_INFO(" EM4 Wakeup");
6667
return kMfltRebootReason_DeepSleep;
67-
#endif
68+
#endif
6869
} else if (reset_cause & RMU_RSTCAUSE_EXTRST) {
6970
MEMFAULT_PRINT_RESET_INFO(" Pin Reset");
7071
return kMfltRebootReason_ButtonReset;
@@ -94,7 +95,7 @@ static eMemfaultRebootReason prv_get_and_print_reason(uint32_t reset_cause) {
9495
} else if (reset_cause & EMU_RSTCAUSE_DVDDBOD) {
9596
MEMFAULT_PRINT_RESET_INFO(" DVDD Brown Out");
9697
return kMfltRebootReason_BrownOutReset;
97-
} else if (reset_cause & EMU_RSTCAUSE_DVDDLEBOD) {
98+
} else if (reset_cause & EMU_RSTCAUSE_DVDDLEBOD) {
9899
MEMFAULT_PRINT_RESET_INFO(" DVDDLE Brown Out");
99100
return kMfltRebootReason_BrownOutReset;
100101
} else if (reset_cause & EMU_RSTCAUSE_DECBOD) {
@@ -118,12 +119,26 @@ static eMemfaultRebootReason prv_get_and_print_reason(uint32_t reset_cause) {
118119
} else if (reset_cause & EMU_RSTCAUSE_SETAMPER) {
119120
MEMFAULT_PRINT_RESET_INFO(" SE Tamper");
120121
return kMfltRebootReason_UnknownError;
122+
#if defined(EMU_RSTCAUSE_SESYSREQ)
121123
} else if (reset_cause & EMU_RSTCAUSE_SESYSREQ) {
122-
MEMFAULT_PRINT_RESET_INFO(" SE Software Reset");
124+
MEMFAULT_PRINT_RESET_INFO(" SE System Reset");
125+
return kMfltRebootReason_SoftwareReset;
126+
#endif
127+
#if defined(EMU_RSTCAUSE_SYSREQ)
128+
} else if (reset_cause & EMU_RSTCAUSE_SYSREQ) {
129+
MEMFAULT_PRINT_RESET_INFO("Software Reset");
123130
return kMfltRebootReason_SoftwareReset;
131+
#endif
132+
#if defined(EMU_RSTCAUSE_SELOCKUP)
124133
} else if (reset_cause & EMU_RSTCAUSE_SELOCKUP) {
125-
MEMFAULT_PRINT_RESET_INFO(" SE Lockup");
134+
MEMFAULT_PRINT_RESET_INFO("SE Lockup");
135+
return kMfltRebootReason_Lockup;
136+
#endif
137+
#if defined(EMU_RSTCAUSE_LOCKUP)
138+
} else if (reset_cause & EMU_RSTCAUSE_LOCKUP) {
139+
MEMFAULT_PRINT_RESET_INFO("Lockup");
126140
return kMfltRebootReason_Lockup;
141+
#endif
127142
} else if (reset_cause & EMU_RSTCAUSE_PIN) {
128143
MEMFAULT_PRINT_RESET_INFO(" SE Pin Reset");
129144
return kMfltRebootReason_PinReset;
@@ -133,7 +148,7 @@ static eMemfaultRebootReason prv_get_and_print_reason(uint32_t reset_cause) {
133148
return kMfltRebootReason_Unknown;
134149
}
135150
#else
136-
#error "Unexpected RSTCTRL configuration"
151+
#error "Unexpected RSTCTRL configuration"
137152
#endif
138153

139154
void memfault_reboot_reason_get(sResetBootupInfo *info) {
@@ -154,7 +169,7 @@ void memfault_reboot_reason_get(sResetBootupInfo *info) {
154169
RMU_ResetCauseClear();
155170
#endif
156171

157-
*info = (sResetBootupInfo) {
172+
*info = (sResetBootupInfo){
158173
.reset_reason_reg = reset_cause,
159174
.reset_reason = reset_reason,
160175
};

ports/emlib/wdog_software_watchdog.c

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,34 @@
1717
//! - The WDOG peripheral supports discrete timeouts. This port chooses the closest period
1818
//! that is less than or equal to the requested value. Valid selections for
1919
//! MEMFAULT_WATCHDOG_SW_TIMEOUT_SECS range from 1s - 128s.
20-
2120
#include "memfault/ports/watchdog.h"
2221

22+
// non-module includes below
23+
#include "em_cmu.h"
24+
#include "em_wdog.h"
2325
#include "memfault/config.h"
2426
#include "memfault/core/debug_log.h"
2527

26-
#include "em_wdog.h"
27-
#include "em_cmu.h"
28-
2928
#if defined(WDOG0)
30-
#define MEMFAULT_WDOG WDOG0
31-
#define MEMFAULT_WDOG_IRQn WDOG0_IRQn
29+
#define MEMFAULT_WDOG WDOG0
30+
#define MEMFAULT_WDOG_IRQn WDOG0_IRQn
3231

33-
#ifndef MEMFAULT_EXC_HANDLER_WATCHDOG
34-
# error "Port expects following define to be set: -DMEMFAULT_EXC_HANDLER_WATCHDOG=WDOG0_IRQHandler"
35-
#endif
32+
#ifndef MEMFAULT_EXC_HANDLER_WATCHDOG
33+
#error \
34+
"Port expects following define to be set: -DMEMFAULT_EXC_HANDLER_WATCHDOG=WDOG0_IRQHandler"
35+
#endif
3636

3737
#elif defined(WDOG)
38-
#define MEMFAULT_WDOG WDOG
39-
#define MEMFAULT_WDOG_IRQn WDOG_IRQn
38+
#define MEMFAULT_WDOG WDOG
39+
#define MEMFAULT_WDOG_IRQn WDOG_IRQn
4040

41-
#ifndef MEMFAULT_EXC_HANDLER_WATCHDOG
42-
# error "Port expects following define to be set: -DMEMFAULT_EXC_HANDLER_WATCHDOG=WDOG_IRQHandler"
43-
#endif
41+
#ifndef MEMFAULT_EXC_HANDLER_WATCHDOG
42+
#error \
43+
"Port expects following define to be set: -DMEMFAULT_EXC_HANDLER_WATCHDOG=WDOG_IRQHandler"
44+
#endif
4445

4546
#else
46-
# error "Could not find an available WDOG to use"
47+
#error "Could not find an available WDOG to use"
4748
#endif
4849

4950
#define MEMFAULT_EM_WDOG_FREQ_HZ 1000
@@ -55,6 +56,7 @@
5556

5657
#define MEMFAULT_EM_WDOG_MAX_TIMEOUT_MS (MEMFAULT_EM_WDOG_PERSEL_TO_TIMEOUT_MS(wdogPeriod_256k))
5758

59+
// clang-format off
5860
static void prv_build_configuration(WDOG_Init_TypeDef *cfg, uint32_t persel) {
5961
*cfg = (WDOG_Init_TypeDef) {
6062
.enable = true,
@@ -70,8 +72,6 @@ static void prv_build_configuration(WDOG_Init_TypeDef *cfg, uint32_t persel) {
7072
#if defined(_WDOG_CTRL_CLKSEL_MASK)
7173
// use internal 1kHz clock for largest range
7274
.clkSel = wdogClkSelULFRCO,
73-
#else
74-
#error "Port doesn't support WDOG Variant - cannot configure clock"
7575
#endif
7676
.perSel = persel,
7777

@@ -91,41 +91,44 @@ static void prv_build_configuration(WDOG_Init_TypeDef *cfg, uint32_t persel) {
9191
#endif
9292
};
9393
}
94+
// clang-format on
9495

9596
static int prv_configure_watchdog_with_timeout(uint32_t timeout_ms) {
96-
9797
// NB: An interrupt can be configured to fire at 25%, 50%, or 75% of the watchdog cycle
9898
// configured. We'll use this interrupt as our "software watchdog" and configure it to be at
9999
// the 50% interval
100-
const size_t sw_wdog_max_ms = MEMFAULT_EM_WDOG_WARNING_TIMEOUT_MS(MEMFAULT_EM_WDOG_MAX_TIMEOUT_MS);
100+
const size_t sw_wdog_max_ms =
101+
MEMFAULT_EM_WDOG_WARNING_TIMEOUT_MS(MEMFAULT_EM_WDOG_MAX_TIMEOUT_MS);
101102
if (timeout_ms > sw_wdog_max_ms) {
102-
MEMFAULT_LOG_ERROR("Requested wdog timeout (%d) exceeds max supported (%d)",
103-
(int)timeout_ms, (int)sw_wdog_max_ms);
103+
MEMFAULT_LOG_ERROR("Requested wdog timeout (%d) exceeds max supported (%d)", (int)timeout_ms,
104+
(int)sw_wdog_max_ms);
104105
return -1;
105106
}
106107

107108
uint32_t persel = wdogPeriod_9;
108109
while (persel <= wdogPeriod_256k) {
109110
const uint32_t warning_timeout_ms =
110-
MEMFAULT_EM_WDOG_WARNING_TIMEOUT_MS(MEMFAULT_EM_WDOG_PERSEL_TO_TIMEOUT_MS(persel));
111+
MEMFAULT_EM_WDOG_WARNING_TIMEOUT_MS(MEMFAULT_EM_WDOG_PERSEL_TO_TIMEOUT_MS(persel));
111112
if (warning_timeout_ms > timeout_ms) {
112113
break;
113114
}
114115
persel++;
115116
}
116117

117118
// choose the closest timeout without going over the desired max
118-
persel = (persel == 0) ? 0 : persel - 1;
119+
persel = (persel == 0) ? 0 : persel - 1;
119120

120121
const size_t actual_timeout_ms = MEMFAULT_EM_WDOG_PERSEL_TO_TIMEOUT_MS(persel);
121122
MEMFAULT_LOG_DEBUG("Configuring SW Watchdog. SW Timeout=%dms HW Timeout=%dms",
122123
(int)MEMFAULT_EM_WDOG_WARNING_TIMEOUT_MS(actual_timeout_ms),
123124
actual_timeout_ms);
124125

125126
// Low energy clock must be on to use the watchdog
126-
if ((CMU->HFBUSCLKEN0 & CMU_HFBUSCLKEN0_LE) == 0) {
127-
CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_LE;
128-
}
127+
#if defined(_SILICON_LABS_32B_SERIES_2)
128+
CMU_ClockEnable(cmuClock_WDOG0, true);
129+
#else // !defined(_SILICON_LABS_32B_SERIES_2)
130+
CMU_ClockEnable(cmuClock_HFLE, true);
131+
#endif // defined(_SILICON_LABS_32B_SERIES_2)
129132

130133
if (WDOGn_IsLocked(MEMFAULT_WDOG)) {
131134
MEMFAULT_LOG_ERROR("Watchdog is locked and cannot be reconfigured");
@@ -137,13 +140,18 @@ static int prv_configure_watchdog_with_timeout(uint32_t timeout_ms) {
137140
NVIC_DisableIRQ(MEMFAULT_WDOG_IRQn);
138141
NVIC_ClearPendingIRQ(MEMFAULT_WDOG_IRQn);
139142

143+
// Series 2 chips select the watchdog source via the CMU
144+
#if defined(_SILICON_LABS_32B_SERIES_2)
145+
CMU_ClockSelectSet(cmuClock_WDOG0, cmuSelect_ULFRCO);
146+
#endif // defined(_SILICON_LABS_32B_SERIES_2)
147+
140148
WDOG_Init_TypeDef cfg;
141149
prv_build_configuration(&cfg, persel);
142150
WDOGn_Init(MEMFAULT_WDOG, &cfg);
143151

144152
// enable the warning interrupt. This will be used to capture a coredump rather than just letting
145153
// the hardware watchdog immediately reboot the system
146-
const uint32_t warn_int_mask = 0x2; // "WARN Interrupt Enable"
154+
const uint32_t warn_int_mask = 0x2; // "WARN Interrupt Enable"
147155
WDOGn_IntClear(MEMFAULT_WDOG, warn_int_mask);
148156
WDOGn_IntEnable(MEMFAULT_WDOG, warn_int_mask);
149157

@@ -154,7 +162,6 @@ static int prv_configure_watchdog_with_timeout(uint32_t timeout_ms) {
154162

155163
// finally, with everything setup, start the watchdog!
156164
WDOGn_Enable(MEMFAULT_WDOG, true);
157-
WDOGn_SyncWait(MEMFAULT_WDOG);
158165
return 0;
159166
}
160167

@@ -182,6 +189,6 @@ int memfault_software_watchdog_feed(void) {
182189
// Enteriung EM2 or EM3 power states while this is in progress will
183190
// cause the operation to be aborted. WDOGn_SyncWait() can be used to
184191
// block until the operation is complete!
185-
WDOG_Feed();
192+
WDOGn_Feed(MEMFAULT_WDOG);
186193
return 0;
187194
}

ports/zephyr/common/memfault_logging.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,23 @@ LOG_BACKEND_DEFINE(log_backend_mflt, log_backend_mflt_api, true);
152152

153153
// Tie Memfault's log function to the Zephyr buffer sender. This is *the* connection to Memfault.
154154
static int prv_log_out(uint8_t *data, size_t length, void *ctx) {
155-
sMfltLogProcessCtx *mflt_ctx = (sMfltLogProcessCtx*)ctx;
156-
size_t save_length = length;
155+
// In synchronous mode, logging can occur from ISRs. The zephyr fault handlers are chatty so
156+
// don't save info while in an ISR to avoid wrapping over the info we are collecting.
157+
// This function may also be run from LOG_PANIC. We also want to skip saving data in this case
158+
// because the context object uses local stack memory which may not be valid when run from
159+
// LOG_PANIC
160+
if (memfault_arch_is_inside_isr()) {
161+
return (int)length;
162+
}
157163

164+
// Ensure we have control over logging context, drop data if we cannot obtain control
158165
if (prv_sem_take() != 0) {
159166
return (int)length;
160167
}
161168

169+
sMfltLogProcessCtx *mflt_ctx = (sMfltLogProcessCtx *)ctx;
170+
size_t save_length = length;
171+
162172
#if CONFIG_LOG_MODE_IMMEDIATE
163173
// A check to help us catch if behavior changes in a future release of Zephyr
164174
MEMFAULT_SDK_ASSERT(length <= 1);

ports/zephyr/common/memfault_platform_core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
// so we can preserve the pristine fault register values.
4040
void __wrap_z_arm_fault(uint32_t msp, uint32_t psp, uint32_t exc_return,
4141
_callee_saved_t *callee_regs) {
42-
#if MEMFAULT_ZEPHYR_VERSION_GT(3, 1) || defined(CONFIG_LOG2)
42+
#if CONFIG_MEMFAULT_LOGGING && (MEMFAULT_ZEPHYR_VERSION_GT(3, 1) || defined(CONFIG_LOG2))
4343
// Trigger a LOG_PANIC() early to flush any buffered logs, then disable the
4444
// Memfault log backend to prevent any further logs from being captured
4545
// (primarily the Zephyr fault logs, which can fill up the Memfault log

scripts/cmsis_pack_bundle.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ def build_cmsis_pack(
126126
if not os.path.isdir(memfault_sdk_dir) or not os.path.isfile(
127127
"{}/VERSION".format(memfault_sdk_dir)
128128
):
129-
raise Exception(
129+
raise ValueError(
130130
"Invalid path to memfault-firmware-sdk (missing VERSION file) at {}".format(
131131
memfault_sdk_dir
132132
)
@@ -141,7 +141,8 @@ def build_cmsis_pack(
141141
tree = ET.ElementTree(
142142
ET.fromstring( # noqa: S314
143143
PDSC_TEMPLATE.format(
144-
SDK_VERSION=sdk_version, SDK_DATE=datetime.date.today().strftime("%Y-%m-%d")
144+
SDK_VERSION=sdk_version,
145+
SDK_DATE=datetime.datetime.now(tz=datetime.timezone.utc).strftime("%Y-%m-%d"),
145146
)
146147
)
147148
)

0 commit comments

Comments
 (0)