Skip to content

Commit b7eea3b

Browse files
author
Memfault Inc
committed
Memfault Firmware SDK 0.29.1 (Build 412506)
1 parent 0c0f78a commit b7eea3b

File tree

14 files changed

+232
-746
lines changed

14 files changed

+232
-746
lines changed

CHANGES.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
### Changes between Memfault SDK 0.29.1 and SDK 0.29.0 - Mar 16, 2022
2+
3+
#### :house: Internal
4+
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
8+
[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
10+
11+
#### :boom: Breaking Changes
12+
13+
- If your project is based on Zephyr < 2.6, you now need to explicitly set
14+
`CONFIG_OPENOCD_SUPPORT=y` in your `prj.conf`
15+
116
### Changes between Memfault SDK 0.29.0 and SDK 0.28.2 - Feb 28, 2022
217

318
#### :rocket: New Features

VERSION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
BUILD ID: 400378
2-
GIT COMMIT: b015b1226
1+
BUILD ID: 412506
2+
GIT COMMIT: f81a4f865

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

2424
#ifdef __cplusplus
2525
}

ports/dialog/da1469x/memfault_diagnostic_service.c

Lines changed: 88 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -75,18 +75,32 @@ MEMFAULT_STATIC_ASSERT(configTIMER_TASK_STACK_DEPTH >= 256,
7575
#define MDS_DYNAMIC_ACCESS_CONTROL 0
7676
#endif
7777

78-
#define MDS_VERSION 0x01
78+
//! Payload returned via a read to "MDS Supported Features Characteristic"
79+
const static uint8_t s_mds_supported_features[] = {
80+
// no feature additions since the first spin of the profile
81+
0x0
82+
};
7983

80-
#define MDS_MAJOR_VERSION 0x01
81-
#define MDS_MINOR_VERSION 0x00
82-
#define MDS_PATCH_VERSION 0x00
84+
//! Valid SNs used when sending data are 0-31
85+
#define MDS_TOTAL_SEQ_NUMBERS 32
86+
87+
typedef enum {
88+
kMdsDataExportMode_StreamingDisabled = 0x00,
89+
kMdsDataExportMode_FullStreamingEnabled = 0x01,
90+
} eMdsDataExportMode;
8391

84-
const static uint8_t s_mds_version[] = { MDS_VERSION, MDS_MINOR_VERSION, MDS_PATCH_VERSION};
92+
93+
typedef MEMFAULT_PACKED_STRUCT {
94+
// bits 5-7: rsvd for future use
95+
// bits 0-4: sequence number
96+
uint8_t hdr;
97+
uint8_t chunk[];
98+
} sMdsDataExportPayload;
8599

86100
typedef struct {
87101
ble_service_t svc;
88102

89-
uint16_t version_h;
103+
uint16_t supported_features_h;
90104
uint16_t data_uri_h;
91105
uint16_t auth_h;
92106
uint16_t device_id_h;
@@ -100,13 +114,13 @@ typedef struct {
100114
// second request will be ignored.
101115
struct {
102116
bool active;
117+
eMdsDataExportMode mode;
118+
uint8_t seq_num; // current sequence number to use
103119
uint16_t conn_idx;
104120
} subscriber;
105121

106-
struct {
107-
void *buf;
108-
size_t buf_len;
109-
} chunk;
122+
sMdsDataExportPayload *payload;
123+
size_t chunk_len;
110124

111125
TimerHandle_t timer;
112126
} md_service_t;
@@ -115,6 +129,7 @@ typedef enum {
115129
kMdsAppError_InvalidLength = ATT_ERROR_APPLICATION_ERROR,
116130
kMdsAppError_ClientAlreadySubscribed,
117131
kMdsAppError_InsufficientLength,
132+
kMdsAppError_ClientNotSubscribed,
118133
} eMdsAppError;
119134

120135
static md_service_t *s_mds;
@@ -135,6 +150,8 @@ static void prv_handle_disconnected_evt(ble_service_t *svc,
135150
if (mds->subscriber.active && (mds->subscriber.conn_idx == evt->conn_idx)) {
136151
mds->subscriber.active = false;
137152
mds->subscriber.conn_idx = 0;
153+
mds->subscriber.seq_num = 0;
154+
mds->subscriber.mode = kMdsDataExportMode_StreamingDisabled;
138155
}
139156

140157
xTimerStop(mds->timer, 0);
@@ -147,29 +164,37 @@ static void prv_try_notify(md_service_t *mds, uint16_t conn_idx) {
147164
return;
148165
}
149166

167+
if (mds->subscriber.mode == kMdsDataExportMode_StreamingDisabled) {
168+
// client has subscribed but not yet enabled data export
169+
return;
170+
}
171+
150172
uint16_t mtu_size = 0;
151173
ble_error_t rv = ble_gattc_get_mtu(conn_idx, &mtu_size);
152174
if (rv != BLE_STATUS_OK) {
153175
return;
154176
}
155177

156-
if ((mds->chunk.buf == NULL) && memfault_packetizer_data_available()) {
157-
mds->chunk.buf = OS_MALLOC(mtu_size - MDS_ATT_HEADER_OVERHEAD);
158-
if (mds->chunk.buf != NULL) {
159-
mds->chunk.buf_len = mtu_size - MDS_ATT_HEADER_OVERHEAD;
160-
memfault_packetizer_get_chunk(mds->chunk.buf, &mds->chunk.buf_len);
178+
if ((mds->payload == NULL) && memfault_packetizer_data_available()) {
179+
mds->payload = OS_MALLOC(mtu_size - MDS_ATT_HEADER_OVERHEAD);
180+
if (mds->payload != NULL) {
181+
mds->payload->hdr = mds->subscriber.seq_num & 0x1f;
182+
mds->chunk_len = mtu_size - MDS_ATT_HEADER_OVERHEAD - sizeof(*mds->payload);
183+
memfault_packetizer_get_chunk(&mds->payload->chunk[0], &mds->chunk_len);
161184
}
162185
}
163186

164-
if (mds->chunk.buf_len != 0) {
187+
if (mds->chunk_len != 0) {
188+
165189
rv = ble_gatts_send_event(conn_idx, mds->chunk_val_h, GATT_EVENT_NOTIFICATION,
166-
mds->chunk.buf_len, mds->chunk.buf);
190+
mds->chunk_len + sizeof(*mds->payload), mds->payload);
167191
if (rv == BLE_STATUS_OK) {
192+
mds->subscriber.seq_num = (mds->subscriber.seq_num + 1) % MDS_TOTAL_SEQ_NUMBERS;
168193
// Note: No need to schedule a retry since we will pump more data when the sent callback is
169194
// invoked for the current notification
170-
OS_FREE(mds->chunk.buf);
171-
mds->chunk.buf = NULL;
172-
mds->chunk.buf_len = 0;
195+
OS_FREE(mds->payload);
196+
mds->payload = NULL;
197+
mds->chunk_len = 0;
173198
return;
174199
}
175200
}
@@ -216,9 +241,9 @@ static void prv_handle_read_req(ble_service_t *svc,
216241
char uri[MDS_MAX_DATA_URI_LENGTH];
217242
struct MemfaultDeviceInfo info;
218243

219-
if (evt->handle == mds->version_h) {
220-
value = &s_mds_version;
221-
length = sizeof(s_mds_version);
244+
if (evt->handle == mds->supported_features_h) {
245+
value = &s_mds_supported_features;
246+
length = sizeof(s_mds_supported_features);
222247
} else if (evt->handle == mds->data_uri_h) {
223248
memfault_platform_get_device_info(&info);
224249
strncpy(uri, MDS_URI_BASE, sizeof(uri) - 1);
@@ -282,7 +307,7 @@ static att_error_t prv_handle_cccd_write(md_service_t *mds, uint16_t conn_idx,
282307
const bool subscribe_for_notifs = ((cccd & GATT_CCC_NOTIFICATIONS) != 0);
283308
if (!mds->subscriber.active) {
284309
// NB: we expect caller to subscribe for notifications each time they connect
285-
// so don't persist the state across disconnects _and_ we only allow one
310+
// so don't persist the mode across disconnects _and_ we only allow one
286311
// active subscription at a time.
287312
mds->subscriber.active = subscribe_for_notifs;
288313
mds->subscriber.conn_idx = conn_idx;
@@ -298,6 +323,37 @@ static att_error_t prv_handle_cccd_write(md_service_t *mds, uint16_t conn_idx,
298323
return ATT_ERROR_OK;
299324
}
300325

326+
static att_error_t prv_handle_data_export_write(md_service_t *mds, uint16_t conn_idx,
327+
uint16_t offset, uint16_t length,
328+
const uint8_t *value) {
329+
if (offset != 0) {
330+
return ATT_ERROR_ATTRIBUTE_NOT_LONG;
331+
}
332+
333+
if (length != sizeof(uint8_t)) {
334+
return kMdsAppError_InvalidLength;
335+
}
336+
337+
if ((!mds->subscriber.active) || (mds->subscriber.conn_idx != conn_idx)) {
338+
return kMdsAppError_ClientNotSubscribed;
339+
}
340+
341+
const eMdsDataExportMode cmd = (eMdsDataExportMode)get_u8(value);
342+
343+
switch (cmd) {
344+
case kMdsDataExportMode_StreamingDisabled:
345+
case kMdsDataExportMode_FullStreamingEnabled:
346+
break;
347+
default:
348+
return ATT_ERROR_REQUEST_NOT_SUPPORTED;
349+
}
350+
351+
mds->subscriber.mode = cmd;
352+
prv_try_notify(mds, conn_idx);
353+
354+
return ATT_ERROR_OK;
355+
}
356+
301357
static void prv_handle_write_req(ble_service_t *svc,
302358
const ble_evt_gatts_write_req_t *evt) {
303359
if (!mds_access_enabled(evt->conn_idx)) {
@@ -312,22 +368,18 @@ static void prv_handle_write_req(ble_service_t *svc,
312368
if (evt->handle == mds->chunk_cccd_h) {
313369
status = prv_handle_cccd_write(mds, evt->conn_idx, evt->offset, evt->length,
314370
evt->value);
315-
if (status == ATT_ERROR_OK) {
316-
// Empirically, sending a notification immediately will wind up getting flushed
317-
// before the response for the CCCD write so we defer starting to send chunk
318-
// notifications so they do not arrive out of order
319-
xTimerChangePeriod(mds->timer, 10, 0);
320-
xTimerStart(mds->timer, 0);
321-
}
371+
} else if (evt->handle == mds->chunk_val_h) {
372+
status = prv_handle_data_export_write(mds, evt->conn_idx, evt->offset, evt->length,
373+
evt->value);
322374
}
323375

324376
ble_gatts_write_cfm(evt->conn_idx, evt->handle, status);
325377
}
326378

327379
static void prv_cleanup_service(ble_service_t *svc) {
328380
md_service_t *mds = (md_service_t *)svc;
329-
if (mds->chunk.buf != NULL) {
330-
OS_FREE(mds->chunk.buf);
381+
if (mds->payload != NULL) {
382+
OS_FREE(mds->payload);
331383
}
332384
if (mds->timer != NULL) {
333385
xTimerDelete(mds->timer, portMAX_DELAY);
@@ -365,7 +417,7 @@ void *mds_boot(void) {
365417

366418
ble_uuid_from_string("54220001-f6a5-4007-a371-722f4ebd8436", &uuid);
367419
ble_gatts_add_characteristic(&uuid, GATT_PROP_READ, ATT_PERM_RW, sizeof(uint8_t),
368-
GATTS_FLAG_CHAR_READ_REQ, NULL, &mds->version_h);
420+
GATTS_FLAG_CHAR_READ_REQ, NULL, &mds->supported_features_h);
369421

370422
ble_uuid_from_string("54220002-f6a5-4007-a371-722f4ebd8436", &uuid);
371423
ble_gatts_add_characteristic(&uuid, GATT_PROP_READ, ATT_PERM_RW, sizeof(uint8_t),
@@ -380,13 +432,13 @@ void *mds_boot(void) {
380432
GATTS_FLAG_CHAR_READ_REQ, NULL, &mds->auth_h);
381433

382434
ble_uuid_from_string("54220005-f6a5-4007-a371-722f4ebd8436", &uuid);
383-
ble_gatts_add_characteristic(&uuid, GATT_PROP_NOTIFY, ATT_PERM_RW, sizeof(uint8_t),
435+
ble_gatts_add_characteristic(&uuid, GATT_PROP_NOTIFY | GATT_PROP_WRITE, ATT_PERM_RW, sizeof(uint8_t),
384436
GATTS_FLAG_CHAR_READ_REQ, NULL, &mds->chunk_val_h);
385437

386438
ble_uuid_create16(UUID_GATT_CLIENT_CHAR_CONFIGURATION, &uuid);
387439
ble_gatts_add_descriptor(&uuid, ATT_PERM_RW, 2, 0, &mds->chunk_cccd_h);
388440

389-
ble_gatts_register_service(&mds->svc.start_h, &mds->version_h, &mds->device_id_h,
441+
ble_gatts_register_service(&mds->svc.start_h, &mds->supported_features_h, &mds->device_id_h,
390442
&mds->data_uri_h, &mds->auth_h, &mds->chunk_val_h,
391443
&mds->chunk_cccd_h, 0);
392444

ports/include/memfault/ports/ble/mds.h

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
//!
1414
//! Memfault Diagnostic Service: (UUID 54220000-f6a5-4007-a371-722f4ebd8436)
1515
//!
16-
//! MDS Version Characteristic: (UUID 54220001-f6a5-4007-a371-722f4ebd8436)
17-
//! read - (length: 3 bytes) returns the version of this profile where there is 1 byte for Major,
18-
//! Minor, & Patch Version
19-
//! Version 1.0.0 = Initial gatt service definition and prototype implementation
16+
//! MDS Supported Features Characteristic: (UUID 54220001-f6a5-4007-a371-722f4ebd8436)
17+
//! read - (length: variable*)
18+
//! Octet 0:
19+
//! bit 0-7: rsvd for future use
20+
//! ...
2021
//!
2122
//! MDS Device Identifier Characteristic: (UUID 54220002-f6a5-4007-a371-722f4ebd8436)
2223
//! read - (length: variable*) returns the device identifier populated in the
@@ -30,11 +31,26 @@
3031
//! "Memfault-Project-Key:YOUR_PROJECT_KEY"
3132
//!
3233
//! MDS Data Export Characteristic: (UUID 54220005-f6a5-4007-a371-722f4ebd8436)
33-
//! notify
34-
//! When subscribed to, streams any collected SDK data to listener as opaque packets.
35-
//! Packets will be sized to fit within negotiated MTU. Listener is responsible
36-
//! for forwarding chunks to the URI specified in the Data URI Characteristic using
37-
//! the authorization scheme specified in the Authorization Characteristic.
34+
//! notify - must be subscribed to in order for any collected SDK data to be streamed
35+
//! write - (length: 1 byte) controls data export operation mode
36+
//! 0x00 - Streaming Disabled
37+
//! 0x01 - Streaming of any collected SDK data enabled
38+
//! Other: reserved for future use
39+
//!
40+
//! When subscribed to and when streaming mode has been enabled via a GATT Write with response,
41+
//! packets will be sized to fit within negotiated MTU.
42+
//! The format of a packet streamed is as follows:
43+
//! byte 0:
44+
//! bits 0-4: Sequence Number A sequentially increasing counter that can be used to detect
45+
//! errors in the BLE stack. SN is reset to 0 anytime a disconnect takes place.
46+
//! Errors client can check for:
47+
//! - Packets are getting repeated when Last Sequence Number == Current Sequence Number
48+
//! - Packets are getting dropped when abs(Last Sequence Number - Current Sequence Number) != 1
49+
//! bit 5-7: Reserved for future use
50+
//!
51+
//! byte 1-N: opaque payload listener is responsible for forwarding to the URI specified in the Data URI
52+
//! Characteristic using the authorization scheme specified in the Authorization Characteristic.
53+
//!
3854
//! Client Characteristic Configuration Descriptor: (UUID 00002902-0000-1000-8000-00805f9b34fb)
3955
//!
4056
//! * If length exceeds negotiated MTU size, it is assumed that client has implemented support for
@@ -51,8 +67,8 @@
5167
//!
5268
//! Note 3: This GATT service is currently under development and subject to updates and
5369
//! enhancements in the future with no current guarantees for backward compatibility. Client
54-
//! implementations should read the MDS Version Characteristic and only attempt to use the service
55-
//! as it is currently defined if the Major Version == 1.
70+
//! implementations should read the MDS Supported Features Characteristic and only attempt to use
71+
//! the service as it is currently defined if the value is 0x00.
5672

5773
#ifdef __cplusplus
5874
extern "C" {

ports/particle/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@ The library is compatible with all versions of
1010
[Device OS](https://github.com/particle-iot/device-os) greater than or equal to
1111
Device OS 3.0
1212

13-
:exclamation: Note: The
13+
:exclamation: Note: Use the
1414
[particle-firmware-library](https://github.com/memfault/particle-firmware-library)
15-
to include this in your project. This repository is updated as part of the
16-
release process for the
15+
repository to add memfault support to an application. This repository is updated
16+
as part of the release process for the
1717
[memfault-firmware-sdk](https://github.com/memfault/memfault-firmware-sdk).
1818

1919
## Welcome to your library!
2020

2121
To get started, add the library to your particle application:
2222

2323
```bash
24-
$ git clone https://github.com/memfault/particle-firmware-library lib/memfault
24+
$ git submodule add https://github.com/memfault/particle-firmware-library lib/memfault
2525
```
2626

2727
## Integration Steps

ports/zephyr/Kconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ config MEMFAULT
55
select RUNTIME_NMI
66
select EXTRA_EXCEPTION_INFO
77
select DEBUG_THREAD_INFO
8-
select OPENOCD_SUPPORT
98
help
109
Enable Zephyr Integration with the Memfault SDK
1110
At the moment a port is only provided for Cortex-M based targets

ports/zephyr/common/memfault_platform_core.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,31 @@
55

66
#include "memfault/core/platform/core.h"
77

8-
#include <soc.h>
98
#include <init.h>
9+
#include <soc.h>
1010

1111
#include "memfault/core/build_info.h"
1212
#include "memfault/core/compiler.h"
1313
#include "memfault/core/event_storage.h"
14-
#include "memfault/core/platform/core.h"
1514
#include "memfault/core/reboot_tracking.h"
1615
#include "memfault/core/trace_event.h"
1716
#include "memfault/panics/coredump.h"
1817
#include "memfault/ports/reboot_reason.h"
18+
#include "memfault/ports/zephyr/version.h"
19+
20+
#if !MEMFAULT_ZEPHYR_VERSION_GT(2, 5)
21+
22+
// Note: CONFIG_OPENOCD_SUPPORT was deprecated in Zephyr 2.6 and fully removed in the 3.x line. To
23+
// maintain backward compatibility with older versions of Zephyr we inline the check here.
24+
//
25+
// When support for Zephyr <= 2.5 is removed, we should adopt an approach like the following
26+
// https://github.com/memfault/memfault-firmware-sdk/pull/26
27+
28+
#if !CONFIG_OPENOCD_SUPPORT
29+
#error "CONFIG_OPENOCD_SUPPORT=y must be added to your prj.conf"
30+
#endif
31+
32+
#endif
1933

2034
#if CONFIG_MEMFAULT_METRICS
2135
#include "memfault/metrics/metrics.h"

scripts/mflt-build-id/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build/

0 commit comments

Comments
 (0)