Skip to content

Commit 907c880

Browse files
author
Memfault Inc
committed
Memfault Firmware SDK 0.23.0 (Build 268452)
1 parent 2e15f95 commit 907c880

File tree

59 files changed

+2791
-206
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+2791
-206
lines changed

CHANGES.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,36 @@
1+
### Changes between Memfault SDK 0.23.0 and SDK 0.22.0 - July 8, 2021
2+
3+
#### :chart_with_upwards_trend: Improvements
4+
5+
- Support for Dialog DA1469x chip family (Huge thanks to @iandmorris for the
6+
help here!)
7+
- Example eclipse project and more details about how to add the port to any
8+
DA1469x based project [can be found here](examples/dialog/da1469x).
9+
- Added a simple utility to track heap allocations. This can be used to more
10+
easily debug what allocations led to out of memory situations with the
11+
addition of only several hundred bytes to a coredump capture. For more
12+
details, see
13+
[`memfault/core/heap_stats.h`](components/include/memfault/core/heap_stats.h)
14+
- For FreeRTOS users, automatic tracking of heap allocations can be enabled
15+
with the Memfault port. To enable, see the "Heap Tracking" section in the
16+
README at [ports/freertos/](ports/freertos).
17+
- Added new convenience utilities for asserting when a watchdog event is
18+
detected,
19+
[`MEMFAULT_SOFTWARE_WATCHDOG`](components/include/memfault/panics/assert.h#L65).
20+
This will result in the issue in the Memfault UI being classified for as a
21+
"Software Watchdog" instead of an "Assert" for easier classification.
22+
- Fixed a :bug: in
23+
[Zephyr port](ports/zephyr/common/memfault_platform_metrics.c) where cpu
24+
runtime metrics were never getting reset after a heartbeat was collected
25+
leading to always increasing runtime values getting reported.
26+
27+
#### :house: Internal
28+
29+
- Improved support for running [tests](tests/) against different versions of
30+
clang and gcc and enabled more address sanitizers such as
31+
[`-fsanitize=undefined`](https://interrupt.memfault.com/blog/ubsan-trap)
32+
- Misc documentation edits
33+
134
### Changes between Memfault SDK 0.22.0 and SDK 0.21.1 - June 17, 2021
235

336
#### :chart_with_upwards_trend: Improvements

README.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ integration guides
1111

1212
# Getting Started
1313

14-
To see a demo of the type of data which can be collected before writing _any_
15-
code, check out https://try.memfault.com.
16-
1714
To start integrating in your platform today,
1815
[create a Memfault cloud account](https://mflt.io/signup).
1916

VERSION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
BUILD ID: 252339
2-
GIT COMMIT: 6ab191b62
1+
BUILD ID: 268452
2+
GIT COMMIT: 9d1b0d8da
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//! @file
2+
//!
3+
//! Copyright (c) Memfault, Inc.
4+
//! See License.txt for details
5+
//!
6+
//! Simple heap allocation tracking utility. Intended to shim into a system's
7+
//! malloc/free implementation to track last allocations with callsite
8+
//! information.
9+
10+
#include "memfault/core/heap_stats.h"
11+
#include "memfault/core/heap_stats_impl.h"
12+
13+
#include <stdbool.h>
14+
#include <stddef.h>
15+
#include <stdint.h>
16+
#include <string.h>
17+
18+
#include "memfault/config.h"
19+
#include "memfault/core/compiler.h"
20+
#include "memfault/core/debug_log.h"
21+
#include "memfault/core/math.h"
22+
#include "memfault/core/platform/debug_log.h"
23+
#include "memfault/core/platform/overrides.h"
24+
25+
#define MEMFAULT_HEAP_STATS_VERSION 1
26+
27+
sMfltHeapStats g_memfault_heap_stats = {
28+
.version = MEMFAULT_HEAP_STATS_VERSION,
29+
};
30+
sMfltHeapStatEntry g_memfault_heap_stats_pool[MEMFAULT_HEAP_STATS_MAX_COUNT];
31+
32+
static void prv_heap_stats_lock(void) {
33+
#if MEMFAULT_COREDUMP_HEAP_STATS_LOCK_ENABLE
34+
memfault_lock();
35+
#endif
36+
}
37+
38+
static void prv_heap_stats_unlock(void) {
39+
#if MEMFAULT_COREDUMP_HEAP_STATS_LOCK_ENABLE
40+
memfault_unlock();
41+
#endif
42+
}
43+
44+
void memfault_heap_stats_reset(void) {
45+
prv_heap_stats_lock();
46+
g_memfault_heap_stats = (sMfltHeapStats){0};
47+
memset(g_memfault_heap_stats_pool, 0, sizeof(g_memfault_heap_stats_pool));
48+
prv_heap_stats_unlock();
49+
}
50+
51+
bool memfault_heap_stats_empty(void) {
52+
// if the first entry has a zero size, we know there was no entry ever
53+
// populated
54+
return g_memfault_heap_stats_pool[0].info.size == 0;
55+
}
56+
57+
//! Return the next slot to write
58+
static sMfltHeapStatEntry *prv_get_next_entry(void) {
59+
sMfltHeapStatEntry *slot =
60+
&g_memfault_heap_stats_pool[g_memfault_heap_stats.stats_pool_head];
61+
g_memfault_heap_stats.stats_pool_head = (g_memfault_heap_stats.stats_pool_head + 1) %
62+
MEMFAULT_ARRAY_SIZE(g_memfault_heap_stats_pool);
63+
return slot;
64+
}
65+
66+
void memfault_heap_stats_malloc(const void *lr, const void *ptr, size_t size) {
67+
prv_heap_stats_lock();
68+
69+
if (ptr) {
70+
g_memfault_heap_stats.in_use_block_count++;
71+
if (g_memfault_heap_stats.in_use_block_count > g_memfault_heap_stats.max_in_use_block_count) {
72+
g_memfault_heap_stats.max_in_use_block_count = g_memfault_heap_stats.in_use_block_count;
73+
}
74+
sMfltHeapStatEntry *slot = prv_get_next_entry();
75+
*slot = (sMfltHeapStatEntry){
76+
.lr = lr,
77+
.ptr = ptr,
78+
.info =
79+
{
80+
.size = size & (~(1u << 31)),
81+
.in_use = 1u,
82+
},
83+
};
84+
}
85+
86+
prv_heap_stats_unlock();
87+
}
88+
89+
void memfault_heap_stats_free(const void *ptr) {
90+
prv_heap_stats_lock();
91+
if (ptr) {
92+
g_memfault_heap_stats.in_use_block_count--;
93+
94+
// if the pointer exists in the tracked stats, mark it as freed
95+
for (size_t i = 0; i < MEMFAULT_ARRAY_SIZE(g_memfault_heap_stats_pool); i++) {
96+
if (g_memfault_heap_stats_pool[i].ptr == ptr) {
97+
g_memfault_heap_stats_pool[i].info.in_use = 0;
98+
break;
99+
}
100+
}
101+
}
102+
prv_heap_stats_unlock();
103+
}

components/demo/src/panics/memfault_demo_panics.c

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,32 @@ int memfault_demo_cli_cmd_crash(int argc, char *argv[]) {
6161
crash_type = atoi(argv[1]);
6262
}
6363

64-
if (crash_type == 0) {
65-
MEMFAULT_ASSERT(0);
66-
} else if (crash_type == 1) {
67-
g_bad_func_call();
68-
} else if (crash_type == 2) {
69-
uint64_t *buf = g_memfault_unaligned_buffer;
70-
*buf = 0xbadcafe0000;
71-
} else if (crash_type == 3) {
72-
do_some_work5(argv);
73-
} else {
74-
// this should only ever be reached if crash_type is invalid
75-
MEMFAULT_LOG_ERROR("Usage: \"crash\" or \"crash <n>\" where n is 0..3");
76-
return -1;
64+
switch (crash_type) {
65+
case 0:
66+
MEMFAULT_ASSERT(0);
67+
break;
68+
69+
case 1:
70+
g_bad_func_call();
71+
break;
72+
73+
case 2: {
74+
uint64_t *buf = g_memfault_unaligned_buffer;
75+
*buf = 0xbadcafe0000;
76+
} break;
77+
78+
case 3:
79+
do_some_work5(argv);
80+
break;
81+
82+
case 4:
83+
MEMFAULT_SOFTWARE_WATCHDOG(0);
84+
break;
85+
86+
default:
87+
// this should only ever be reached if crash_type is invalid
88+
MEMFAULT_LOG_ERROR("Usage: \"crash\" or \"crash <n>\" where n is 0..4");
89+
return -1;
7790
}
7891

7992
// Should be unreachable. If we get here, trigger an assert and record the crash_type which

components/include/memfault/components.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ extern "C" {
2727
#include "memfault/core/debug_log.h"
2828
#include "memfault/core/errors.h"
2929
#include "memfault/core/event_storage.h"
30+
#include "memfault/core/heap_stats.h"
3031
#include "memfault/core/log.h"
3132
#include "memfault/core/math.h"
3233
#include "memfault/core/platform/core.h"
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#pragma once
2+
3+
//! @file
4+
//!
5+
//! Copyright (c) Memfault, Inc.
6+
//! See License.txt for details
7+
//!
8+
//! @brief
9+
//!
10+
//! A minimal set of functions to track statistics on heap allocations.
11+
//!
12+
//! @note To integrate with your system heap, add the intrumentation functions
13+
//! to your platforms malloc + free implementations.
14+
//!
15+
//! For example, when using malloc & free from a library with GCC or Clang, you can use the
16+
//! compiler flag `-Wl,--wrap=malloc,--wrap=free` to shim around the library malloc- in that case,
17+
//! these functions should be added to your platform port:
18+
//!
19+
//! #include memfault/components.h
20+
//!
21+
//! extern void *__real_malloc(size_t size);
22+
//! extern void __real_free(void *ptr);
23+
//!
24+
//! void *__wrap_malloc(size_t size) {
25+
//! void *ptr = __real_malloc(size);
26+
//! MEMFAULT_HEAP_STATS_MALLOC(ptr, size);
27+
//! return ptr;
28+
//! }
29+
//!
30+
//! void __wrap_free(void *ptr) {
31+
//! MEMFAULT_HEAP_STATS_FREE(ptr);
32+
//! __real_free(ptr);
33+
//! }
34+
//!
35+
//! @note By default, the thread-safety of the module depends on memfault_lock/unlock() API.
36+
//! If calls to the malloc/free stats functions can be made from multiple tasks,
37+
//! these APIs must be implemented. Locks are held while updating the internal
38+
//! stats tracking data structures, which is quick and has a bounded worst-case
39+
//! runtime.
40+
//! @note If the functions you are calling MEMFAULT_HEAP_STATS_MALLOC/FREE from
41+
//! already use a lock of their own, the use of memfault_lock/unlock can be disabled from
42+
//! memfault_platform_config.h:
43+
//!
44+
//! #define MEMFAULT_COREDUMP_HEAP_STATS_LOCK_ENABLE 0
45+
46+
47+
#include <stdbool.h>
48+
#include <stddef.h>
49+
#include <stdint.h>
50+
51+
#include "memfault/core/compiler.h"
52+
53+
#ifdef __cplusplus
54+
extern "C" {
55+
#endif
56+
57+
//! Record a single malloc. Called from within malloc handler (eg __wrap_malloc).
58+
//!
59+
//! @note This function usually should not be called directly, but instead via the macro
60+
//! MEMFAULT_HEAP_STATS_MALLOC, which will retrieve the LR for the frame where malloc was called.
61+
//!
62+
//! @param lr Link register from the malloc function frame, stored for minimal context around this
63+
//! @param ptr The pointer returned by the malloc call (can be NULL)
64+
//! @param size The size value passed to the malloc call
65+
//! allocation
66+
void memfault_heap_stats_malloc(const void *lr, const void *ptr, size_t size);
67+
68+
#define MEMFAULT_HEAP_STATS_MALLOC(ptr_, size_) \
69+
do { \
70+
void *lr_; \
71+
MEMFAULT_GET_LR(lr_); \
72+
memfault_heap_stats_malloc(lr_, ptr_, size_); \
73+
} while (0)
74+
75+
//! Record a single free. Called from within free handler (eg __wraps_free).
76+
//!
77+
//! @note A macro MEMFAULT_HEAP_STATS_FREE is provided for visual symmetry with
78+
//! MEMFAULT_HEAP_STATS_MALLOC
79+
//!
80+
//! @param ptr The pointer being passed to free (can be NULL)
81+
void memfault_heap_stats_free(const void *ptr);
82+
83+
#define MEMFAULT_HEAP_STATS_FREE(ptr_) memfault_heap_stats_free(ptr_)
84+
85+
#ifdef __cplusplus
86+
}
87+
#endif
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#pragma once
2+
3+
//! @file
4+
//!
5+
//! Copyright (c) Memfault, Inc.
6+
//! See License.txt for details
7+
//!
8+
//! @brief
9+
//!
10+
//! Heap tracking 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+
#ifdef __cplusplus
19+
extern "C" {
20+
#endif
21+
22+
//! Number of regions used by heap stats
23+
#define MEMFAULT_HEAP_STATS_NUM_RAM_REGIONS 2
24+
25+
26+
//! The heap stats data structure, which is exported when capturing a core.
27+
typedef struct MfltHeapStatEntry {
28+
// LR at time of allocation
29+
const void *lr;
30+
31+
// The pointer returned by the actual allocation function
32+
const void *ptr;
33+
34+
// Size of this allocation. 0 means the entry is invalid and should be ignored
35+
struct {
36+
// 31 bits to represent the size passed to malloc
37+
uint32_t size : 31;
38+
// 1 bit indicating whether this entry is still in use or has been freed
39+
uint32_t in_use : 1;
40+
} info;
41+
} sMfltHeapStatEntry;
42+
43+
44+
typedef struct MfltHeapStats {
45+
uint8_t version;
46+
47+
// Number of blocks currently allocated and not freed
48+
uint32_t in_use_block_count;
49+
50+
// Track the max value of 'in_use_block_count'
51+
uint32_t max_in_use_block_count;
52+
53+
// Allocation entry list pointer
54+
size_t stats_pool_head;
55+
} sMfltHeapStats;
56+
57+
extern sMfltHeapStats g_memfault_heap_stats;
58+
extern sMfltHeapStatEntry g_memfault_heap_stats_pool[MEMFAULT_HEAP_STATS_MAX_COUNT];
59+
60+
//! Reset the tracked stats.
61+
void memfault_heap_stats_reset(void);
62+
63+
//! Check if no heap stats have been collected
64+
bool memfault_heap_stats_empty(void);
65+
66+
#ifdef __cplusplus
67+
}
68+
#endif

components/include/memfault/default_config.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,32 @@ extern "C" {
161161
#define MEMFAULT_COREDUMP_COLLECT_LOG_REGIONS 0
162162
#endif
163163

164+
//! When the FreeRTOS port is being used, controls whether or not heap
165+
//! allocation tracking is enabled.
166+
//! Note: When using this feature, MEMFAULT_COREDUMP_HEAP_STATS_LOCK_ENABLE 0
167+
//! is also required
168+
#ifndef MEMFAULT_FREERTOS_PORT_HEAP_STATS_ENABLE
169+
#define MEMFAULT_FREERTOS_PORT_HEAP_STATS_ENABLE 0
170+
#endif
171+
172+
//! Enable this flag to collect the heap stats information on coredump
173+
#ifndef MEMFAULT_COREDUMP_COLLECT_HEAP_STATS
174+
#define MEMFAULT_COREDUMP_COLLECT_HEAP_STATS 0
175+
#endif
176+
177+
//! Max number of recent outstanding heap allocations to track.
178+
//! oldest tracked allocations are expired (by allocation order)
179+
#ifndef MEMFAULT_HEAP_STATS_MAX_COUNT
180+
#define MEMFAULT_HEAP_STATS_MAX_COUNT 32
181+
#endif
182+
183+
//! Controls whether or not memfault_lock() will be used in the heap stats module. If the
184+
//! allocation implementation in use already enables locks of it's own (i.e FreeRTOS heap_*.c
185+
//! implementations), the recommendation is to disable memfault locking
186+
#ifndef MEMFAULT_COREDUMP_HEAP_STATS_LOCK_ENABLE
187+
#define MEMFAULT_COREDUMP_HEAP_STATS_LOCK_ENABLE 1
188+
#endif
189+
164190
#ifndef MEMFAULT_TRACE_REASON_USER_DEFS_FILE
165191
#define MEMFAULT_TRACE_REASON_USER_DEFS_FILE \
166192
"memfault_trace_reason_user_config.def"

0 commit comments

Comments
 (0)