Skip to content

Commit

Permalink
Memfault Firmware SDK 1.10.1 (Build 9081)
Browse files Browse the repository at this point in the history
  • Loading branch information
Memfault Inc committed Jul 24, 2024
1 parent a4711bc commit 0901fbb
Show file tree
Hide file tree
Showing 20 changed files with 294 additions and 215 deletions.
193 changes: 111 additions & 82 deletions CHANGELOG.md

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# Memfault Firmware SDK

[![CircleCI](https://circleci.com/gh/memfault/memfault-firmware-sdk.svg?style=svg)](https://circleci.com/gh/memfault/memfault-firmware-sdk)
[![Coverage](https://img.shields.io/codecov/c/gh/memfault/memfault-firmware-sdk/master)](https://codecov.io/gh/memfault/memfault-firmware-sdk/)

# Memfault Firmware SDK

Ship Firmware with Confidence.

More details about the Memfault platform itself, how it works, and step-by-step
integration guides
[can be found here](https://mflt.io/embedded-getting-started).

# Getting Started
## Getting Started

To start integrating in your platform today,
[create a Memfault cloud account](https://mflt.io/signup).

# Components
## Components

The SDK is designed as a collection of components, so you can include only what
is needed for your project. The SDK has been designed to have minimal impact on
Expand Down Expand Up @@ -53,14 +53,14 @@ Please refer to the `README.md` in each of these for more details.
Memfault service from devices.
- `util` – various utilities.

# Integrating the Memfault SDK
## Integrating the Memfault SDK

## Add Memfault SDK to Your Repository

The Memfault SDK can be added directly into your repository. The structure
typically looks like:

```
```bash
<YOUR_PROJECT>
├── third_party/memfault
│ ├── memfault-firmware-sdk (submodule)
Expand All @@ -79,8 +79,8 @@ typically looks like:
If you are using `git`, the Memfault SDK is typically added to a project as a
submodule:

```
$ git submodule add https://github.com/memfault/memfault-firmware-sdk.git $YOUR_PROJECT/third_party/memfault/memfault-firmware-sdk
```bash
git submodule add https://github.com/memfault/memfault-firmware-sdk.git $YOUR_PROJECT/third_party/memfault/memfault-firmware-sdk
```

This makes it easy to track the history of the Memfault SDK. You should not need
Expand Down Expand Up @@ -147,7 +147,7 @@ out
The unit tests are run by CircleCI upon every commit to this repo. See badges at
the top for build & test coverage status of the `master` branch.
# FAQ
## FAQ
- Why does a coredump not show up under "Issues" after uploading it?
Expand All @@ -163,7 +163,7 @@ the top for build & test coverage status of the `master` branch.
- Don't hesitate to contact us for help! You can reach us through
<https://mflt.io/contact-support>.
# License
## License
Unless specifically indicated otherwise in a file, all memfault-firmware-sdk
files are all licensed under the [Memfault License](/License.txt). (A few files
Expand Down
6 changes: 3 additions & 3 deletions VERSION
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
BUILD ID: 8899
GIT COMMIT: 7e534eec9c
VERSION: 1.10.0
BUILD ID: 9081
GIT COMMIT: 5183b73f74
VERSION: 1.10.1
24 changes: 16 additions & 8 deletions components/core/src/memfault_self_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,9 +336,9 @@ MEMFAULT_NO_OPT static uint32_t prv_get_time_since_boot_test(void) {

uint64_t end_time_ms = memfault_platform_get_time_since_boot_ms();
if ((end_time_ms <= start_time_ms)) {
MEMFAULT_LOG_ERROR("Time since boot not monotonically increasing: start[%" PRIu64
"] vs end[%" PRIu64 "]",
start_time_ms, end_time_ms);
MEMFAULT_LOG_ERROR("Time since boot not monotonically increasing: start[%" PRIu32
"] vs end[%" PRIu32 "]",
(uint32_t)start_time_ms, (uint32_t)end_time_ms);
return (1 << 1);
}

Expand Down Expand Up @@ -369,12 +369,13 @@ static uint32_t prv_platform_time_get_current_test(void) {
}

if (time.info.unix_timestamp_secs < MEMFAULT_SELF_TEST_TIMESTAMP_ANCHOR) {
MEMFAULT_LOG_ERROR("Timestamp too far in the past: %" PRIu64, time.info.unix_timestamp_secs);
MEMFAULT_LOG_ERROR("Timestamp too far in the past: %" PRIu32,
(uint32_t)time.info.unix_timestamp_secs);
return (1 << 4);
}

MEMFAULT_LOG_INFO("Verify received timestamp for accuracy. Timestamp received %" PRIu64,
time.info.unix_timestamp_secs);
MEMFAULT_LOG_INFO("Verify received timestamp for accuracy. Timestamp received %" PRIu32,
(uint32_t)time.info.unix_timestamp_secs);
return 0;
}

Expand All @@ -390,9 +391,16 @@ uint32_t memfault_self_test_time_test(void) {

uint32_t memfault_self_test_coredump_storage_capacity_test(void) {
MEMFAULT_SELF_TEST_PRINT_HEADER("Coredump Storage Capacity Test");
bool result = memfault_coredump_storage_check_size();
bool capacity_ok = memfault_coredump_storage_check_size();
if (capacity_ok) {
size_t total_size = 0;
size_t capacity = 0;
memfault_coredump_size_and_storage_capacity(&total_size, &capacity);
MEMFAULT_LOG_INFO("Total size required: %u bytes", (unsigned)total_size);
MEMFAULT_LOG_INFO("Storage capacity: %u bytes", (unsigned)capacity);
}
MEMFAULT_LOG_INFO(MEMFAULT_SELF_TEST_END_OUTPUT);
return result ? 0 : 1;
return capacity_ok ? 0 : 1;
}

uint32_t memfault_self_test_coredump_storage_test(void) {
Expand Down
2 changes: 1 addition & 1 deletion components/include/memfault/panics/arch/arm/v7_a_r.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
extern "C" {
#endif

//! Register State collected for ARMv7-R when a fault occurs. Non-arch-specific
//! Register State collected for ARMv7-A/R when a fault occurs. Non-arch-specific
//! name for the struct type- this type is used when defining the coredump
//! header layout.
MEMFAULT_PACKED_STRUCT MfltRegState {
Expand Down
4 changes: 2 additions & 2 deletions components/include/memfault/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ typedef struct {
uint8_t patch;
} sMfltSdkVersion;

#define MEMFAULT_SDK_VERSION { .major = 1, .minor = 10, .patch = 0 }
#define MEMFAULT_SDK_VERSION_STR "1.10.0"
#define MEMFAULT_SDK_VERSION { .major = 1, .minor = 10, .patch = 1 }
#define MEMFAULT_SDK_VERSION_STR "1.10.1"

#ifdef __cplusplus
}
Expand Down
120 changes: 46 additions & 74 deletions components/panics/src/memfault_fault_handling_armv7_a_r.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@
#include "memfault/core/compiler.h"

#if MEMFAULT_COMPILER_ARM_V7_A_R

//! Only ARMv7-R is officially supported, notify the user if compiling for
//! ARMv7-A
#if defined(__ARM_ARCH_7A__)
#pragma message \
"ARMv7-A is not officially supported yet by Memfault. Please contact [email protected] with questions!"
#endif

#include "memfault/components.h"
#include "memfault/panics/arch/arm/v7_a_r.h"
#include "memfault/panics/coredump_impl.h"
Expand All @@ -43,27 +35,6 @@ extern void MEMFAULT_EXC_HANDLER_PREFETCH_ABORT(void);

static eMemfaultRebootReason s_crash_reason = kMfltRebootReason_Unknown;

//! These are the regs pushed by the exception wrapper, which are transcribed
//! into 'struct MfltRegState' for the coredump.
MEMFAULT_PACKED_STRUCT ExceptionPushedRegs {
uint32_t r0;
uint32_t r1;
uint32_t r2;
uint32_t r3;
uint32_t r4;
uint32_t r5;
uint32_t r6;
uint32_t r7;
uint32_t r8;
uint32_t r9;
uint32_t r10;
uint32_t r11;
uint32_t r12;
uint32_t sp; // R13
uint32_t lr; // R14
uint32_t cpsr;
};

const sMfltCoredumpRegion *memfault_coredump_get_arch_regions(size_t *num_regions) {
*num_regions = 0;
return NULL;
Expand Down Expand Up @@ -247,6 +218,17 @@ MEMFAULT_USED void memfault_fault_handler(const sMfltRegState *regs, eMemfaultRe
// We push callee r0-r12, lr, pc, and cpsr onto the stack, then pass the stack
// pointer to the C memfault_fault_handler.
//
// Note that r0-r7 are shared across all execution modes, and r8-r12 are
// shared in all modes except for FIQ.
//
// We need to ensure that we enter SYS MODE rather than USER MODE, so we
// perform a check and mask if the fault occurred in USER mode.
//
// In order to preserve the layout of `MfltRegState` and ensure that we don't
// clobber any registers, pushing to the stack to the stack is done out of
// order, moving the stack pointer around manually to ensure ordering is
// consistent.
//
// Here's a worked example of the position the registers are saved on the stack:
//
// sp = 128 <- starting example stack pointer value
Expand All @@ -256,16 +238,10 @@ MEMFAULT_USED void memfault_fault_handler(const sMfltRegState *regs, eMemfaultRe
// cpsr @ 124
// pc @ 120
//
// // Now push user mode r8-r12, sp, lr, by first switching to user mode
// lr @ 116
// sp @ 112
// r12 @ 108
// r11 @ 104
// r10 @ 100
// r9 @ 96
// r8 @ 92
// // Now, create a hole for the user mode registers.
// sp -> 92
//
// // Now switch back to exception mode, save r0-r7 to the stack
// // Now push r0-r7 to the stack
// r7 @ 88
// r6 @ 84
// r5 @ 80
Expand All @@ -274,43 +250,39 @@ MEMFAULT_USED void memfault_fault_handler(const sMfltRegState *regs, eMemfaultRe
// r2 @ 68
// r1 @ 64
// r0 @ 60 <- this is the struct address we pass to memfault_fault_handler

//
// // Now enter user mode, with r2 address @ 120 (the hole we made earlier)
// // Now push user mode r8-r12, sp, lr, using r2 as the stack pointer
// lr @ 116
// sp @ 112
// r12 @ 108
// r11 @ 104
// r10 @ 100
// r9 @ 96
// r8 @ 92
//
// // Now switch back to exception mode, set up args in r0 & r1, and call the
// // fault handler.
#define MEMFAULT_FAULT_HANDLING_ASM(_mode_string, _reason) \
__asm volatile( /* assemble in ARM mode so we can copy sp with a stm instruction */ \
".arm \n" /* save callee pc (exception handler adjusted lr) + spsr (callee \
cpsr) of the current mode */ \
"srsdb sp!, #" _mode_string \
" \n" /* push user mode regs at point of fault, including sp + lr */ \
"mov r8, r1 \n" \
"mov r1, sp \n" /* Save SPSR and mask mode bits */ \
"mrs r9, spsr \n" \
"and r9, #0x1f \n" /* Check each applicable mode and set current mode on a \
match */ \
"cmp r9, #" CPU_MODE_IRQ_STR " \n" \
"bne fiq_mode_%= \n" \
"cps #" CPU_MODE_IRQ_STR " \n" \
"b store_regs_%= \n" \
"fiq_mode_%=: \n" \
"cmp r9, #" CPU_MODE_FIQ_STR " \n" \
"bne supervisor_mode_%= \n" \
"cps #" CPU_MODE_FIQ_STR " \n" \
"b store_regs_%= \n" \
"supervisor_mode_%=: \n" \
"cmp r9, #" CPU_MODE_SUPERVISOR_STR " \n" \
"bne system_mode_%= \n" \
"cps #" CPU_MODE_SUPERVISOR_STR " \n" \
"b store_regs_%= \n" /* Fall back to system mode if no match */ \
"system_mode_%=: \n" \
"cps #" CPU_MODE_SYSTEM_STR " \n" \
"store_regs_%=: \n" \
"stmfd r1!, {r8-r12, sp, lr} \n" \
"cps #" _mode_string " \n" /* save active registers in exception frame */ \
"mov sp, r1 \n" \
"mov r1, r8 \n" \
"stmfd sp!, {r0-r7} \n" /* load the pushed frame and reason into r0+r1 for \
the handler args */ \
"mov r0, sp \n" \
"ldr r1, =%c0 \n" \
__asm volatile(".arm \n" /* assemble in ARM mode so we can copy sp with a stm instruction */ \
\
"srsdb sp!, #" _mode_string " \n" /* Push PC + CPSR of previous mode */ \
"sub sp, sp, #28 \n" /* Want r0-r7 after r8 - r14, make space */ \
"stmfd sp!, {r0-r7} \n" /* Push r0-r7, shared amongst all modes */ \
"add r2, sp, #60 \n" /* r2 for previous mode to push r8-r14 */ \
\
"mrs r3, cpsr \n" /* r3: CPSR to return to exception mode */ \
"mrs r4, spsr \n" /* Get the previous mode CPSR */ \
"tst r4, #0xf \n" /* Set Z Flag if in USR mode */ \
"orreq r4, r4, #0xf \n" /* r4: Previous mode changed to SYS if was USR */ \
\
"msr CPSR_c, r4 \n" /* Enter the previous mode */ \
"stmfd r2!, {r8-r12, sp, lr} \n" /* Push all banked registers */ \
\
"msr CPSR_cxsf, r3 \n" /* Back to our exception mode */ \
\
"mov r0, sp \n" /* arg0 = sp */ \
"ldr r1, =%c0 \n" /* arg1 = reason */ \
"b memfault_fault_handler \n" \
: \
: "i"((uint16_t)_reason))
Expand Down
28 changes: 27 additions & 1 deletion examples/freertos/src/memfault/memfault_platform_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
//! See License.txt for details

#include <stdio.h>
#include <time.h>

#include "memfault/components.h"
#include "memfault/ports/freertos.h"
#include "memfault/ports/reboot_reason.h"

// Buffer used to store formatted string for output
#define MEMFAULT_DEBUG_LOG_BUFFER_SIZE_BYTES (MEMFAULT_DATA_EXPORT_BASE64_CHUNK_MAX_LEN)

Expand Down Expand Up @@ -74,6 +74,32 @@ void memfault_platform_log_raw(const char *fmt, ...) {
va_end(args);
}

bool memfault_platform_time_get_current(sMemfaultCurrentTime *time_output) {
// Get time from time.h

// Debug: print time fields
time_t time_now = time(NULL);

struct tm *tm_time = gmtime(&time_now);
MEMFAULT_LOG_DEBUG("Time: %u-%u-%u %u:%u:%u", tm_time->tm_year + 1900, tm_time->tm_mon + 1,
tm_time->tm_mday, tm_time->tm_hour, tm_time->tm_min, tm_time->tm_sec);

// If pre-2023, something is wrong
if ((tm_time->tm_year < 123) || (tm_time->tm_year > 200)) {
MEMFAULT_LOG_WARN("Time doesn't make sense: year %u", tm_time->tm_year + 1900);
return false;
}

// load the timestamp and return true for a valid timestamp
*time_output = (sMemfaultCurrentTime){
.type = kMemfaultCurrentTimeType_UnixEpochTimeSec,
.info = {
.unix_timestamp_secs = (uint64_t)time_now,
},
};
return true;
}

void memfault_platform_reboot_tracking_boot(void) {
sResetBootupInfo reset_info = { 0 };
memfault_reboot_reason_get(&reset_info);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,4 @@ CONFIG_HEAP_MEM_POOL_SIZE=1024
# Currently not supported on older Zephyr, so explicitly disable until this
# sample is updated
CONFIG_MEMFAULT_METRICS_CPU_TEMP=n
CONFIG_MEMFAULT_DTS_IN_ELF=n
Loading

0 comments on commit 0901fbb

Please sign in to comment.