Skip to content

Commit d7ed96d

Browse files
author
Memfault Inc
committed
Memfault Firmware SDK 0.35.0 (Build 615)
1 parent b049df4 commit d7ed96d

28 files changed

+972
-51
lines changed

CHANGES.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,25 @@
1+
### Changes between Memfault SDK 0.35.0 and SDK 0.34.2 - Nov 22, 2022
2+
3+
#### :rocket: New Features
4+
5+
- **Experimental** Custom Data Recording API
6+
- Allows sending custom data collected over the course of a recording period
7+
8+
#### :chart_with_upwards_trend: Improvements
9+
10+
- Zephyr:
11+
- Modify heap stats to only collect info during allocations/deallocations from
12+
threads
13+
- ESP-IDF:
14+
- ESP32 reboot tracking into RTC noinit
15+
- nRF5 SDK:
16+
- NRF5 coredump regions -Wunused-macros, fixes warning for unused macros
17+
18+
#### :house: Internal
19+
20+
- Experiment: pytest as fw test frontend
21+
- README: Add additional details on port integration
22+
123
### Changes between Memfault SDK 0.34.2 and SDK 0.34.1 - Nov 8, 2022
224

325
#### :chart_with_upwards_trend: Improvements

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ The platform header files describe the interfaces which the component relies on
2828
that you must implement.
2929

3030
For some of the platform dependencies we have provided ports that can be linked
31-
into your system without modification. You can find them in the
32-
[`ports`](ports/) folder.
31+
into your system directly, or used as a template for further customization. You
32+
can find them in the [`ports`](ports/) folder.
3333

3434
For some of the popular MCUs & vendor SDKs, we have already provided a reference
3535
implementation for platform dependencies which can be found in the

VERSION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
BUILD ID: 412
2-
GIT COMMIT: ba639658d
1+
BUILD ID: 615
2+
GIT COMMIT: 465ee2834
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
//! @file
2+
//!
3+
//! Copyright (c) Memfault, Inc.
4+
//! See License.txt for details
5+
//!
6+
//! Implements sMemfaultDataSourceImpl API specified in data_packetizer_source.h to serialize a
7+
//! custom data recording such that it can be published to the Memfault cloud.
8+
9+
#include "memfault/core/custom_data_recording.h"
10+
#include "memfault_custom_data_recording_private.h"
11+
12+
#include <string.h>
13+
#include <stddef.h>
14+
#include <stdint.h>
15+
16+
#include "memfault/config.h"
17+
#include "memfault/core/data_packetizer_source.h"
18+
#include "memfault/core/debug_log.h"
19+
#include "memfault/core/math.h"
20+
#include "memfault/core/sdk_assert.h"
21+
#include "memfault/core/serializer_helper.h"
22+
#include "memfault/core/serializer_key_ids.h"
23+
#include "memfault/util/cbor.h"
24+
25+
#if MEMFAULT_CDR_ENABLE
26+
27+
// Holds CDR metadata -- we pre-serialize in prv_has_cdr to avoid an egregious amount of calls to
28+
// read out the metadata when a small chunk size is used by a platform
29+
typedef struct {
30+
size_t length;
31+
uint8_t data[MEMFAULT_CDR_MAX_ENCODED_METADATA_LEN];
32+
} sMemfaultCdrEncodedMetadata;
33+
34+
static const sMemfaultCdrSourceImpl *s_cdr_sources[MEMFAULT_CDR_MAX_DATA_SOURCES];
35+
36+
typedef struct {
37+
sMemfaultCborEncoder encoder;
38+
const sMemfaultCdrSourceImpl *active_source;
39+
size_t total_encode_len;
40+
sMemfaultCdrMetadata active_metadata;
41+
sMemfaultCdrEncodedMetadata encoded_metadata;
42+
} sMfltCdrSourceCtx;
43+
44+
static sMfltCdrSourceCtx s_memfault_cdr_source_ctx;
45+
46+
static bool prv_encode_cdr_metadata(sMemfaultCborEncoder *encoder, sMfltCdrSourceCtx *cdr_ctx) {
47+
const sMemfaultCdrMetadata *metadata = &cdr_ctx->active_metadata;
48+
49+
if (!memfault_serializer_helper_encode_metadata_with_time(
50+
encoder, kMemfaultEventType_Cdr, &metadata->start_time)) {
51+
return false;
52+
}
53+
if (!memfault_cbor_encode_unsigned_integer(encoder, kMemfaultEventKey_EventInfo)) {
54+
return false;
55+
}
56+
57+
const size_t cdr_num_pairs =
58+
1 /* mime types array */ +
59+
1 /* duration ms */ +
60+
1 /* collection reason */ +
61+
1 /* recording itself */;
62+
63+
memfault_cbor_encode_dictionary_begin(encoder, cdr_num_pairs);
64+
65+
if (!memfault_serializer_helper_encode_uint32_kv_pair(
66+
encoder, kMemfaultCdrInfoKey_DurationMs, metadata->duration_ms)) {
67+
return false;
68+
}
69+
70+
if (!memfault_cbor_encode_unsigned_integer(encoder, kMemfaultCdrInfoKey_Mimetypes) ||
71+
!memfault_cbor_encode_array_begin(encoder, metadata->num_mimetypes)) {
72+
return false;
73+
}
74+
75+
for (size_t i = 0; i < metadata->num_mimetypes; i++) {
76+
if (!memfault_cbor_encode_string(encoder, metadata->mimetypes[i])) {
77+
return false;
78+
}
79+
}
80+
81+
if (!memfault_cbor_encode_unsigned_integer(encoder, kMemfaultCdrInfoKey_Reason) ||
82+
!memfault_cbor_encode_string(encoder, metadata->collection_reason)) {
83+
return false;
84+
}
85+
86+
if (!memfault_cbor_encode_unsigned_integer(encoder, kMemfaultCdrInfoKey_Data)) {
87+
return false;
88+
}
89+
90+
if (!memfault_cbor_encode_byte_string_begin(encoder, metadata->data_size_bytes)) {
91+
return false;
92+
}
93+
94+
// Note: at this point all that's left to encode is the binary blob itself as a byte string
95+
return true;
96+
}
97+
98+
static void prv_try_get_cdr_source_with_data(sMfltCdrSourceCtx *ctx) {
99+
if (ctx->active_source != NULL) {
100+
// a source is already active
101+
return;
102+
}
103+
104+
for (size_t i = 0; i < MEMFAULT_ARRAY_SIZE(s_cdr_sources); i++) {
105+
const sMemfaultCdrSourceImpl *source = s_cdr_sources[i];
106+
if (source == NULL) {
107+
continue;
108+
}
109+
110+
if (source->has_cdr_cb(&ctx->active_metadata)) {
111+
ctx->active_source = source;
112+
return;
113+
}
114+
}
115+
}
116+
117+
static void prv_fill_header_cb(void *ctx, uint32_t offset, const void *buf, size_t buf_len) {
118+
uint8_t *header_buf = (uint8_t *)ctx;
119+
memcpy(&header_buf[offset], buf, buf_len);
120+
}
121+
122+
static bool prv_has_cdr(size_t *total_size) {
123+
sMfltCdrSourceCtx *cdr_ctx = &s_memfault_cdr_source_ctx;
124+
125+
prv_try_get_cdr_source_with_data(cdr_ctx);
126+
if (cdr_ctx->active_source == NULL) {
127+
return false;
128+
}
129+
130+
sMemfaultCborEncoder encoder;
131+
memfault_cbor_encoder_init(&encoder, prv_fill_header_cb, cdr_ctx->encoded_metadata.data,
132+
sizeof(cdr_ctx->encoded_metadata.data));
133+
134+
if (!prv_encode_cdr_metadata(&encoder, cdr_ctx)) {
135+
MEMFAULT_LOG_ERROR("Not enough storage to serialized CDR, increase MEMFAULT_CDR_MAX_ENCODED_METADATA_LEN");
136+
return false;
137+
}
138+
139+
cdr_ctx->encoded_metadata.length = memfault_cbor_encoder_deinit(&encoder);
140+
cdr_ctx->total_encode_len = cdr_ctx->encoded_metadata.length + cdr_ctx->active_metadata.data_size_bytes;
141+
*total_size = cdr_ctx->total_encode_len;
142+
return true;
143+
}
144+
145+
static bool prv_cdr_read(uint32_t offset, void *buf, size_t buf_len) {
146+
sMfltCdrSourceCtx *cdr_ctx = &s_memfault_cdr_source_ctx;
147+
if (cdr_ctx->active_source == NULL) {
148+
return false;
149+
}
150+
151+
if ((offset + buf_len) > cdr_ctx->total_encode_len) {
152+
return false;
153+
}
154+
155+
uint8_t *bufp = (uint8_t *)buf;
156+
if (offset < cdr_ctx->encoded_metadata.length) {
157+
const size_t metadata_bytes_to_copy = MEMFAULT_MIN(
158+
buf_len, cdr_ctx->encoded_metadata.length - offset);
159+
memcpy(bufp, &cdr_ctx->encoded_metadata.data[offset], metadata_bytes_to_copy);
160+
buf_len -= metadata_bytes_to_copy;
161+
162+
if (buf_len == 0) {
163+
return true;
164+
}
165+
166+
offset = 0;
167+
bufp += metadata_bytes_to_copy;
168+
} else {
169+
offset -= cdr_ctx->encoded_metadata.length;
170+
}
171+
172+
if (!cdr_ctx->active_source->read_data_cb(offset, bufp, buf_len)) {
173+
return false;
174+
}
175+
176+
return true;
177+
}
178+
179+
static void prv_cdr_mark_sent(void) {
180+
sMfltCdrSourceCtx *cdr_ctx = &s_memfault_cdr_source_ctx;
181+
if (cdr_ctx->active_source == NULL) {
182+
return;
183+
}
184+
185+
cdr_ctx->active_source->mark_cdr_read_cb();
186+
187+
*cdr_ctx = (sMfltCdrSourceCtx) { 0 };
188+
}
189+
190+
bool memfault_cdr_register_source(const sMemfaultCdrSourceImpl *impl) {
191+
// it is a configuration error if all the required dependencies are not implemented!
192+
MEMFAULT_SDK_ASSERT(
193+
(impl != NULL) &&
194+
(impl->has_cdr_cb != NULL) &&
195+
(impl->read_data_cb != NULL) &&
196+
(impl->mark_cdr_read_cb != NULL));
197+
198+
for (size_t i = 0; i < MEMFAULT_ARRAY_SIZE(s_cdr_sources); i++) {
199+
if (s_cdr_sources[i] == NULL) {
200+
s_cdr_sources[i] = impl;
201+
return true;
202+
}
203+
}
204+
205+
MEMFAULT_LOG_ERROR("Memfault Cdr Register is full, %d entries", (int)MEMFAULT_ARRAY_SIZE(s_cdr_sources));
206+
return false;
207+
}
208+
209+
void memfault_cdr_source_reset(void) {
210+
memset(s_cdr_sources, 0x0, sizeof(s_cdr_sources));
211+
s_memfault_cdr_source_ctx = (sMfltCdrSourceCtx) { 0x0 };
212+
}
213+
214+
//! Expose a data source for use by the Memfault Packetizer
215+
const sMemfaultDataSourceImpl g_memfault_cdr_source = {
216+
.has_more_msgs_cb = prv_has_cdr,
217+
.read_msg_cb = prv_cdr_read,
218+
.mark_msg_read_cb = prv_cdr_mark_sent,
219+
};
220+
221+
#endif /* MEMFAULT_CDR_ENABLE */
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#pragma once
2+
3+
//! @file
4+
//!
5+
//! Copyright (c) Memfault, Inc.
6+
//! See License.txt for details
7+
//!
8+
//! APIs intended for internal use _only_. And end user should never invoke these
9+
10+
#ifdef __cplusplus
11+
extern "C" {
12+
#endif
13+
14+
//! Resets Cdr for unit testing purposes.
15+
void memfault_cdr_source_reset(void);
16+
17+
#ifdef __cplusplus
18+
}
19+
#endif

components/core/src/memfault_data_packetizer.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ MEMFAULT_WEAK const sMemfaultDataSourceImpl g_memfault_log_data_source = {
6060
.mark_msg_read_cb = prv_data_source_mark_event_read_stub,
6161
};
6262

63+
MEMFAULT_WEAK const sMemfaultDataSourceImpl g_memfault_cdr_source = {
64+
.has_more_msgs_cb = prv_data_source_has_event_stub,
65+
.read_msg_cb = prv_data_source_read_stub,
66+
.mark_msg_read_cb = prv_data_source_mark_event_read_stub,
67+
};
68+
6369
MEMFAULT_WEAK
6470
bool memfault_data_source_rle_encoder_set_active(
6571
MEMFAULT_UNUSED const sMemfaultDataSourceImpl *active_source) {
@@ -72,6 +78,7 @@ typedef enum {
7278
kMfltMessageType_Coredump = 1,
7379
kMfltMessageType_Event = 2,
7480
kMfltMessageType_Log = 3,
81+
kMfltMessageType_Cdr = 4,
7582
kMfltMessageType_NumTypes
7683
} eMfltMessageType;
7784

@@ -82,7 +89,9 @@ MEMFAULT_STATIC_ASSERT((1 << kMfltMessageType_Event) == kMfltDataSourceMask_Even
8289
"kMfltDataSourceMask_Event, is incorrectly defined");
8390
MEMFAULT_STATIC_ASSERT((1 << kMfltMessageType_Log) == kMfltDataSourceMask_Log,
8491
"kMfltDataSourceMask_Log is incorrectly defined");
85-
MEMFAULT_STATIC_ASSERT(kMfltMessageType_NumTypes == 4, "eMfltDataSourceMask needs to be updated");
92+
MEMFAULT_STATIC_ASSERT((1 << kMfltMessageType_Cdr) == kMfltDataSourceMask_Cdr,
93+
"kMfltDataSourceMask_Cdr is incorrectly defined");
94+
MEMFAULT_STATIC_ASSERT(kMfltMessageType_NumTypes == 5, "eMfltMessageType needs to be updated");
8695

8796

8897
typedef struct MemfaultDataSource {
@@ -106,6 +115,14 @@ static const sMemfaultDataSource s_memfault_data_source[] = {
106115
.type = kMfltMessageType_Log,
107116
.use_rle = false,
108117
.impl = &g_memfault_log_data_source,
118+
},
119+
// NB: We may want to enable RLE in the future here (probably a lot of repeat patterns). The one
120+
// thing to keep in mind is that when the encoder is enabled, it requires a lot more short reads
121+
// to take place on the data source which can be a slow operation for flash based filesystems.
122+
{
123+
.type = kMfltMessageType_Cdr,
124+
.use_rle = false,
125+
.impl = &g_memfault_cdr_source,
109126
}
110127
};
111128

components/include/memfault/components.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ extern "C" {
2121
#include "memfault/core/arch.h"
2222
#include "memfault/core/batched_events.h"
2323
#include "memfault/core/build_info.h"
24-
#include "memfault/core/device_info.h"
2524
#include "memfault/core/compiler.h"
25+
#include "memfault/core/custom_data_recording.h"
2626
#include "memfault/core/data_export.h"
27+
#include "memfault/core/data_packetizer.h"
2728
#include "memfault/core/debug_log.h"
29+
#include "memfault/core/device_info.h"
2830
#include "memfault/core/errors.h"
2931
#include "memfault/core/event_storage.h"
3032
#include "memfault/core/heap_stats.h"
@@ -40,10 +42,9 @@ extern "C" {
4042
#include "memfault/core/platform/system_time.h"
4143
#include "memfault/core/reboot_reason_types.h"
4244
#include "memfault/core/reboot_tracking.h"
43-
#include "memfault/core/task_watchdog.h"
4445
#include "memfault/core/sdk_assert.h"
46+
#include "memfault/core/task_watchdog.h"
4547
#include "memfault/core/trace_event.h"
46-
#include "memfault/core/data_packetizer.h"
4748
#include "memfault/demo/cli.h"
4849
#include "memfault/demo/shell.h"
4950
#include "memfault/demo/shell_commands.h"

0 commit comments

Comments
 (0)