From d997b2c918b8f2dc9d21d4b2efb9fdf387047fe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Tue, 5 May 2020 16:01:51 +0200 Subject: [PATCH 1/2] [WIP] libc: Fix PRIuXX defines --- libc/baselibc/include/inttypes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libc/baselibc/include/inttypes.h b/libc/baselibc/include/inttypes.h index ce4159a9cf..1f17c5d06b 100644 --- a/libc/baselibc/include/inttypes.h +++ b/libc/baselibc/include/inttypes.h @@ -50,7 +50,7 @@ __extern uintmax_t strntoumax(const char *, char **, int, size_t); #define PRIi8 "i" #define PRIi16 "i" -#define PRIi32 "i" +#define PRIi32 "li" #define PRIi64 __PRI64_RANK "i" #define PRIiLEAST8 "i" @@ -86,7 +86,7 @@ __extern uintmax_t strntoumax(const char *, char **, int, size_t); #define PRIu8 "u" #define PRIu16 "u" -#define PRIu32 "u" +#define PRIu32 "lu" #define PRIu64 __PRI64_RANK "u" #define PRIuLEAST8 "u" From 6be6ef8cb43bf0f04e533ebf16dcd2e1f27222a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Mon, 25 May 2020 13:50:26 +0200 Subject: [PATCH 2/2] sys/memfault: Add integration with Memfault https://memfault.com/ --- .../memfault_metrics_heartbeat_config.def | 1 + .../memfault_trace_reason_user_config.def | 2 + apps/bleprph_memfault/pkg.yml | 42 +++ apps/bleprph_memfault/src/bleprph.c | 253 ++++++++++++++++++ apps/bleprph_memfault/src/bleprph.h | 63 +++++ apps/bleprph_memfault/src/gatt_svr.c | 57 ++++ apps/bleprph_memfault/src/main.c | 223 +++++++++++++++ apps/bleprph_memfault/src/misc.c | 43 +++ apps/bleprph_memfault/syscfg.yml | 73 +++++ kernel/os/pkg.yml | 3 + kernel/os/src/arch/cortex_m4/os_fault.c | 34 +++ sys/memfault/pkg.yml | 48 ++++ sys/memfault/src/memfault_common.h | 20 ++ sys/memfault/src/memfault_demo_cli.c | 96 +++++++ sys/memfault/src/memfault_platform_core.c | 140 ++++++++++ .../src/memfault_platform_debug_log.c | 72 +++++ .../memfault_platform_flash_backed_coredump.c | 164 ++++++++++++ sys/memfault/syscfg.yml | 41 +++ 18 files changed, 1375 insertions(+) create mode 100644 apps/bleprph_memfault/include/memfault_metrics_heartbeat_config.def create mode 100644 apps/bleprph_memfault/include/memfault_trace_reason_user_config.def create mode 100644 apps/bleprph_memfault/pkg.yml create mode 100644 apps/bleprph_memfault/src/bleprph.c create mode 100644 apps/bleprph_memfault/src/bleprph.h create mode 100644 apps/bleprph_memfault/src/gatt_svr.c create mode 100644 apps/bleprph_memfault/src/main.c create mode 100644 apps/bleprph_memfault/src/misc.c create mode 100644 apps/bleprph_memfault/syscfg.yml create mode 100644 sys/memfault/pkg.yml create mode 100644 sys/memfault/src/memfault_common.h create mode 100644 sys/memfault/src/memfault_demo_cli.c create mode 100644 sys/memfault/src/memfault_platform_core.c create mode 100644 sys/memfault/src/memfault_platform_debug_log.c create mode 100644 sys/memfault/src/memfault_platform_flash_backed_coredump.c create mode 100644 sys/memfault/syscfg.yml diff --git a/apps/bleprph_memfault/include/memfault_metrics_heartbeat_config.def b/apps/bleprph_memfault/include/memfault_metrics_heartbeat_config.def new file mode 100644 index 0000000000..8164be3bca --- /dev/null +++ b/apps/bleprph_memfault/include/memfault_metrics_heartbeat_config.def @@ -0,0 +1 @@ +MEMFAULT_METRICS_KEY_DEFINE(MainTaskStackHwm, kMemfaultMetricType_Unsigned) diff --git a/apps/bleprph_memfault/include/memfault_trace_reason_user_config.def b/apps/bleprph_memfault/include/memfault_trace_reason_user_config.def new file mode 100644 index 0000000000..e502935be9 --- /dev/null +++ b/apps/bleprph_memfault/include/memfault_trace_reason_user_config.def @@ -0,0 +1,2 @@ +MEMFAULT_TRACE_REASON_DEFINE(test) +MEMFAULT_TRACE_REASON_DEFINE(MemfaultDemoCli_Error) diff --git a/apps/bleprph_memfault/pkg.yml b/apps/bleprph_memfault/pkg.yml new file mode 100644 index 0000000000..ca681e9738 --- /dev/null +++ b/apps/bleprph_memfault/pkg.yml @@ -0,0 +1,42 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +pkg.name: apps/bleprph_memfault +pkg.type: app +pkg.description: Simple BLE peripheral application demonstrating Memfault SDK. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: +pkg.cflags: + - "-DMEMFAULT_TRACE_REASON_USER_DEFS_FILE=\"memfault_trace_reason_user_config.def\"" +pkg.deps: + - "@mcuboot/boot/bootutil" + - "@apache-mynewt-core/kernel/os" + - "@apache-mynewt-nimble/nimble/host" + - "@apache-mynewt-nimble/nimble/host/services/gap" + - "@apache-mynewt-nimble/nimble/host/services/gatt" + - "@apache-mynewt-nimble/nimble/host/store/config" + - "@apache-mynewt-nimble/nimble/transport" + - "@apache-mynewt-core/sys/console/full" + - "@apache-mynewt-core/sys/log/full" + - "@apache-mynewt-core/sys/log/modlog" + - "@apache-mynewt-core/sys/stats/full" + - "@apache-mynewt-core/mgmt/oicmgr" + - "@apache-mynewt-core/sys/sysinit" + - "@apache-mynewt-core/sys/shell" + - "@apache-mynewt-core/sys/id" + - "@apache-mynewt-core/sys/memfault" diff --git a/apps/bleprph_memfault/src/bleprph.c b/apps/bleprph_memfault/src/bleprph.c new file mode 100644 index 0000000000..321e2dda20 --- /dev/null +++ b/apps/bleprph_memfault/src/bleprph.c @@ -0,0 +1,253 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "os/mynewt.h" +#include "syscfg/syscfg.h" +#include "oic/oc_gatt.h" + +/* BLE */ +#include "nimble/ble.h" +#include "host/ble_hs.h" +#include "services/gap/ble_svc_gap.h" + +#include "bleprph.h" + +static int +bleprph_gap_event(struct ble_gap_event *event, void *arg); + +/** + * Logs information about a connection to the console. + */ +static void +bleprph_print_conn_desc(struct ble_gap_conn_desc *desc) +{ + DFLT_LOG_INFO("handle=%d our_ota_addr_type=%d our_ota_addr=", + desc->conn_handle, desc->our_ota_addr.type); + print_addr(desc->our_ota_addr.val); + DFLT_LOG_INFO(" our_id_addr_type=%d our_id_addr=", + desc->our_id_addr.type); + print_addr(desc->our_id_addr.val); + DFLT_LOG_INFO(" peer_ota_addr_type=%d peer_ota_addr=", + desc->peer_ota_addr.type); + print_addr(desc->peer_ota_addr.val); + DFLT_LOG_INFO(" peer_id_addr_type=%d peer_id_addr=", + desc->peer_id_addr.type); + print_addr(desc->peer_id_addr.val); + DFLT_LOG_INFO(" conn_itvl=%d conn_latency=%d supervision_timeout=%d " + "encrypted=%d authenticated=%d bonded=%d\n", + desc->conn_itvl, desc->conn_latency, + desc->supervision_timeout, + desc->sec_state.encrypted, + desc->sec_state.authenticated, + desc->sec_state.bonded); +} + +/** + * Enables advertising with the following parameters: + * o General discoverable mode. + * o Undirected connectable mode. + */ +void +bleprph_advertise(void) +{ + struct ble_gap_adv_params adv_params; + struct ble_hs_adv_fields fields; + const char *name; + int rc; + + /** + * Set the advertisement data included in our advertisements: + * o Flags (indicates advertisement type and other general info). + * o Advertising tx power. + * o Device name. + * o service UUID. + */ + + memset(&fields, 0, sizeof fields); + + /* Advertise two flags: + * o Discoverability in forthcoming advertisement (general) + * o BLE-only (BR/EDR unsupported). + */ + fields.flags = BLE_HS_ADV_F_DISC_GEN | + BLE_HS_ADV_F_BREDR_UNSUP; + + /* Indicate that the TX power level field should be included; have the + * stack fill this value automatically. This is done by assiging the + * special value BLE_HS_ADV_TX_PWR_LVL_AUTO. + */ + fields.tx_pwr_lvl_is_present = 1; + fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; + + name = ble_svc_gap_device_name(); + fields.name = (uint8_t *) name; + fields.name_len = strlen(name); + fields.name_is_complete = 1; + +#if MYNEWT_VAL(ADVERTISE_128BIT_UUID) + /* Advertise the 128-bit CoAP-over-BLE service UUID in the scan response. */ + fields.uuids128 = (ble_uuid128_t []) { + BLE_UUID128_INIT(OC_GATT_UNSEC_SVC_UUID) + }; + fields.num_uuids128 = 1; + fields.uuids128_is_complete = 1; +#endif +#if MYNEWT_VAL(ADVERTISE_16BIT_UUID) + /* Advertise the 16-bit CoAP-over-BLE service UUID in the scan response. */ + fields.uuids16 = (ble_uuid16_t[]) { + BLE_UUID16_INIT(OC_GATT_SEC_SVC_UUID) + }; + fields.num_uuids16 = 1; + fields.uuids16_is_complete = 1; +#endif + rc = ble_gap_adv_set_fields(&fields); + if (rc != 0) { + DFLT_LOG_ERROR("error setting advertisement data; rc=%d\n", rc); + return; + } + + /* Begin advertising. */ + memset(&adv_params, 0, sizeof adv_params); + adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; + adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; + rc = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, + &adv_params, bleprph_gap_event, NULL); + if (rc != 0) { + DFLT_LOG_ERROR("error enabling advertisement; rc=%d\n", rc); + return; + } +} + +/** + * The nimble host executes this callback when a GAP event occurs. The + * application associates a GAP event callback with each connection that forms. + * bleprph uses the same callback for all connections. + * + * @param event The type of event being signalled. + * @param ctxt Various information pertaining to the event. + * @param arg Application-specified argument; unuesd by + * bleprph. + * + * @return 0 if the application successfully handled the + * event; nonzero on failure. The semantics + * of the return code is specific to the + * particular GAP event being signalled. + */ +static int +bleprph_gap_event(struct ble_gap_event *event, void *arg) +{ + struct ble_gap_conn_desc desc; + int rc; + + switch (event->type) { + case BLE_GAP_EVENT_CONNECT: + /* A new connection was established or a connection attempt failed. */ + DFLT_LOG_INFO("connection %s; status=%d ", + event->connect.status == 0 ? "established" : "failed", + event->connect.status); + if (event->connect.status == 0) { + rc = ble_gap_conn_find(event->connect.conn_handle, &desc); + assert(rc == 0); + bleprph_print_conn_desc(&desc); + } + DFLT_LOG_INFO("\n"); + + if (event->connect.status != 0) { + /* Connection failed; resume advertising. */ + bleprph_advertise(); + } else { + oc_ble_coap_conn_new(event->connect.conn_handle); + } + return 0; + + case BLE_GAP_EVENT_DISCONNECT: + DFLT_LOG_INFO("disconnect; reason=%d ", event->disconnect.reason); + bleprph_print_conn_desc(&event->disconnect.conn); + DFLT_LOG_INFO("\n"); + + oc_ble_coap_conn_del(event->disconnect.conn.conn_handle); + + /* Connection terminated; resume advertising. */ + bleprph_advertise(); + return 0; + + case BLE_GAP_EVENT_CONN_UPDATE: + /* The central has updated the connection parameters. */ + DFLT_LOG_INFO("connection updated; status=%d ", + event->conn_update.status); + rc = ble_gap_conn_find(event->connect.conn_handle, &desc); + assert(rc == 0); + bleprph_print_conn_desc(&desc); + DFLT_LOG_INFO("\n"); + return 0; + + case BLE_GAP_EVENT_ADV_COMPLETE: + DFLT_LOG_INFO("advertise complete; reason=%d\n", + event->adv_complete.reason); + bleprph_advertise(); + return 0; + + case BLE_GAP_EVENT_ENC_CHANGE: + /* Encryption has been enabled or disabled for this connection. */ + DFLT_LOG_INFO("encryption change event; status=%d ", + event->enc_change.status); + rc = ble_gap_conn_find(event->connect.conn_handle, &desc); + assert(rc == 0); + bleprph_print_conn_desc(&desc); + DFLT_LOG_INFO("\n"); + return 0; + + case BLE_GAP_EVENT_SUBSCRIBE: + DFLT_LOG_INFO("subscribe event; conn_handle=%d attr_handle=%d " + "reason=%d prevn=%d curn=%d previ=%d curi=%d\n", + event->subscribe.conn_handle, + event->subscribe.attr_handle, + event->subscribe.reason, + event->subscribe.prev_notify, + event->subscribe.cur_notify, + event->subscribe.prev_indicate, + event->subscribe.cur_indicate); + return 0; + + case BLE_GAP_EVENT_MTU: + DFLT_LOG_INFO("mtu update event; conn_handle=%d cid=%d mtu=%d\n", + event->mtu.conn_handle, + event->mtu.channel_id, + event->mtu.value); + return 0; + + case BLE_GAP_EVENT_REPEAT_PAIRING: + /* We already have a bond with the peer, but it is attempting to + * establish a new secure link. This app sacrifices security for + * convenience: just throw away the old bond and accept the new link. + */ + + /* Delete the old bond. */ + rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc); + assert(rc == 0); + ble_store_util_delete_peer(&desc.peer_id_addr); + + /* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should + * continue with the pairing operation. + */ + return BLE_GAP_REPEAT_PAIRING_RETRY; + } + + return 0; +} diff --git a/apps/bleprph_memfault/src/bleprph.h b/apps/bleprph_memfault/src/bleprph.h new file mode 100644 index 0000000000..bd08075096 --- /dev/null +++ b/apps/bleprph_memfault/src/bleprph.h @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLEPRPH_ +#define H_BLEPRPH_ + +#include "os/mynewt.h" +#include "modlog/modlog.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_hs_cfg; +struct ble_gatt_register_ctxt; + +extern struct log bleprph_log; + +/** GATT server. */ +#define GATT_SVR_SVC_ALERT_UUID 0x1811 +#define GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID 0x2A47 +#define GATT_SVR_CHR_NEW_ALERT 0x2A46 +#define GATT_SVR_CHR_SUP_UNR_ALERT_CAT_UUID 0x2A48 +#define GATT_SVR_CHR_UNR_ALERT_STAT_UUID 0x2A45 +#define GATT_SVR_CHR_ALERT_NOT_CTRL_PT 0x2A44 + +void +bleprph_advertise(void); + +void +gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg); + +int +gatt_svr_init(void); + +/** Misc. */ +void +print_bytes(const uint8_t *bytes, int len); + +void +print_addr(const void *addr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/apps/bleprph_memfault/src/gatt_svr.c b/apps/bleprph_memfault/src/gatt_svr.c new file mode 100644 index 0000000000..3f7f12f939 --- /dev/null +++ b/apps/bleprph_memfault/src/gatt_svr.c @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include "bsp/bsp.h" +#include "host/ble_hs.h" +#include "bleprph.h" + +void +gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) +{ + char buf[BLE_UUID_STR_LEN]; + + switch (ctxt->op) { + case BLE_GATT_REGISTER_OP_SVC: + DFLT_LOG_DEBUG("registered service %s with handle=%d\n", + ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf), + ctxt->svc.handle); + break; + + case BLE_GATT_REGISTER_OP_CHR: + DFLT_LOG_DEBUG("registering characteristic %s with " + "def_handle=%d val_handle=%d\n", + ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf), + ctxt->chr.def_handle, + ctxt->chr.val_handle); + break; + + case BLE_GATT_REGISTER_OP_DSC: + DFLT_LOG_DEBUG("registering descriptor %s with handle=%d\n", + ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf), + ctxt->dsc.handle); + break; + + default: + assert(0); + break; + } +} diff --git a/apps/bleprph_memfault/src/main.c b/apps/bleprph_memfault/src/main.c new file mode 100644 index 0000000000..3381ea4eac --- /dev/null +++ b/apps/bleprph_memfault/src/main.c @@ -0,0 +1,223 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include + +#include "os/mynewt.h" +#include "bsp/bsp.h" +#include "hal/hal_gpio.h" +#include "mgmt/mgmt.h" + +#include "oic/oc_api.h" +#include "oic/oc_gatt.h" +#include "cborattr/cborattr.h" + +#include "nimble/ble.h" +#include "host/ble_hs.h" +#include "services/gap/ble_svc_gap.h" + +/* Memfault */ +#include "memfault/core/platform/device_info.h" +#include "memfault/http/http_client.h" +#include "memfault/metrics/metrics.h" + +/* Application-specified header. */ +#include "bleprph.h" + + +void +memfault_platform_get_device_info(sMemfaultDeviceInfo *info) +{ + *info = (sMemfaultDeviceInfo) { + .device_serial = "DEMOSERIAL", + .software_type = "app", + .software_version = "0.0.1", + .hardware_version = MYNEWT_VAL(BSP_NAME), + }; +} + +sMfltHttpClientConfig g_mflt_http_client_config = { + .api_key = "", +}; + +void +memfault_metrics_heartbeat_collect_data(void) +{ + struct os_task *prev_task; + struct os_task_info oti; + char *name; + int found; + + name = "main"; + found = 0; + prev_task = NULL; + + while (1) { + prev_task = os_task_info_get_next(prev_task, &oti); + if (prev_task == NULL) { + break; + } + + if (strcmp(name, oti.oti_name) != 0) { + continue; + } else { + found = 1; + break; + } + } + + if (found) { + memfault_metrics_heartbeat_set_unsigned( + MEMFAULT_METRICS_KEY(MainTaskStackHwm), oti.oti_stkusage); + } +} + +static void +bleprph_on_reset(int reason) +{ + DFLT_LOG_ERROR("Resetting state; reason=%d\n", reason); +} + +static void +bleprph_on_sync(void) +{ + /* Begin advertising. */ + bleprph_advertise(); +} + +static void +app_get_light(oc_request_t *request, oc_interface_mask_t interface) +{ + bool value; + + if (hal_gpio_read(LED_BLINK_PIN)) { + value = true; + } else { + value = false; + } + oc_rep_start_root_object(); + switch (interface) { + case OC_IF_BASELINE: + oc_process_baseline_interface(request->resource); + case OC_IF_A: + oc_rep_set_boolean(root, value, value); + break; + default: + break; + } + oc_rep_end_root_object(); + oc_send_response(request, OC_STATUS_OK); +} + +static void +app_set_light(oc_request_t *request, oc_interface_mask_t interface) +{ + bool value; + int len; + uint16_t data_off; + struct os_mbuf *m; + struct cbor_attr_t attrs[] = { + [0] = { + .attribute = "value", + .type = CborAttrBooleanType, + .addr.boolean = &value, + .dflt.boolean = false + }, + [1] = { + } + }; + + len = coap_get_payload(request->packet, &m, &data_off); + if (cbor_read_mbuf_attrs(m, data_off, len, attrs)) { + oc_send_response(request, OC_STATUS_BAD_REQUEST); + } else { + hal_gpio_write(LED_BLINK_PIN, value == true); + oc_send_response(request, OC_STATUS_CHANGED); + } +} + +static void +omgr_app_init(void) +{ + oc_resource_t *res; + + oc_init_platform("MyNewt", NULL, NULL); + oc_add_device("/oic/d", "oic.d.light", "MynewtLed", "1.0", "1.0", NULL, + NULL); + + res = oc_new_resource("/light/1", 1, 0); + oc_resource_bind_resource_type(res, "oic.r.switch.binary"); + oc_resource_bind_resource_interface(res, OC_IF_A); + oc_resource_set_default_interface(res, OC_IF_A); + + oc_resource_set_discoverable(res); + oc_resource_set_periodic_observable(res, 1); + oc_resource_set_request_handler(res, OC_GET, app_get_light); + oc_resource_set_request_handler(res, OC_PUT, app_set_light); + oc_resource_set_request_handler(res, OC_POST, app_set_light); + oc_add_resource(res); +} + +static const oc_handler_t omgr_oc_handler = { + .init = omgr_app_init, +}; + +/** + * main + * + * The main task for the project. This function initializes the packages, + * then starts serving events from default event queue. + * + * @return int NOTE: this function should never return! + */ +int +main(void) +{ + int rc; + + /* Set initial BLE device address. */ + memcpy(g_dev_addr, (uint8_t[6]) {0x0a, 0xfa, 0xcf, 0xac, 0xfa, 0xc0}, 6); + + /* Initialize OS */ + sysinit(); + + /* Initialize the OIC */ + oc_main_init((oc_handler_t *) &omgr_oc_handler); + oc_ble_coap_gatt_srv_init(); + + ble_hs_cfg.reset_cb = bleprph_on_reset; + ble_hs_cfg.sync_cb = bleprph_on_sync; + ble_hs_cfg.gatts_register_cb = gatt_svr_register_cb; + ble_hs_cfg.store_status_cb = ble_store_util_status_rr; + + /* Set the default device name. */ + rc = ble_svc_gap_device_name_set("memfault"); + assert(rc == 0); + + /* Our light resource */ + hal_gpio_init_out(LED_BLINK_PIN, 1); + + while (1) { + os_eventq_run(os_eventq_dflt_get()); + } + /* Never exit */ + + return 0; +} diff --git a/apps/bleprph_memfault/src/misc.c b/apps/bleprph_memfault/src/misc.c new file mode 100644 index 0000000000..77b2b8bf99 --- /dev/null +++ b/apps/bleprph_memfault/src/misc.c @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "bleprph.h" + +/** + * Utility function to log an array of bytes. + */ +void +print_bytes(const uint8_t *bytes, int len) +{ + int i; + + for (i = 0; i < len; i++) { + DFLT_LOG_INFO("%s0x%02x", i != 0 ? ":" : "", bytes[i]); + } +} + +void +print_addr(const void *addr) +{ + const uint8_t *u8p; + + u8p = addr; + DFLT_LOG_INFO("%02x:%02x:%02x:%02x:%02x:%02x", + u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]); +} diff --git a/apps/bleprph_memfault/syscfg.yml b/apps/bleprph_memfault/syscfg.yml new file mode 100644 index 0000000000..bfade27c1e --- /dev/null +++ b/apps/bleprph_memfault/syscfg.yml @@ -0,0 +1,73 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + ADVERTISE_16BIT_UUID: + description: 'Advertise Runtime 16 bit service UUID' + value: 1 + ADVERTISE_128BIT_UUID: + description: 'Advertise Iotivity 128 bit service UUID' + value: 0 + MEMFAULT_MAX_CHUNK_SIZE: + description: > + The maximum amount of memfault data that can fit in a + single OIC message + value: 512 + +syscfg.vals: + # Use INFO log level to reduce code size. DEBUG is too large for nRF51. + LOG_LEVEL: 0 + + BLE_GATT_WRITE_MAX_ATTRS: 6 + BLE_HCI_EVT_HI_BUF_COUNT: 4 + BLE_HCI_EVT_LO_BUF_COUNT: 3 + + # Disable central and observer roles. + BLE_ROLE_BROADCASTER: 1 + BLE_ROLE_CENTRAL: 0 + BLE_ROLE_OBSERVER: 0 + BLE_ROLE_PERIPHERAL: 1 + + # Disable security manager + BLE_SM: 0 + BLE_LL_CFG_FEAT_LE_ENCRYPTION: 0 + BLE_LL_CFG_FEAT_LL_PRIVACY: 0 + + BLE_STORE_CONFIG_PERSIST: 0 + + # OC server, with bluetooth transport. + OC_SERVER: 1 + OC_TRANSPORT_GATT: 1 + + SHELL_TASK: 1 + STATS_CLI: 1 + LOG_CLI: 1 + STATS_NAMES: 1 + SYS_MEMFAULT_CLI: 1 + MEMFAULT_COREDUMP_FLASH_AREA: FLASH_AREA_IMAGE_1 + + STATS_MGMT: 1 + LOG_MGMT: 1 + MEMFAULT_MGMT: 1 + # Default task settings + OS_MAIN_STACK_SIZE: 1024 + + # Lots of smaller mbufs are required for smp-over-OIC using typical BLE + # ATT MTU values. + MSYS_1_BLOCK_COUNT: 20 + MSYS_1_BLOCK_SIZE: 150 diff --git a/kernel/os/pkg.yml b/kernel/os/pkg.yml index c0d853ff74..5c279e16d6 100644 --- a/kernel/os/pkg.yml +++ b/kernel/os/pkg.yml @@ -47,5 +47,8 @@ pkg.deps.OS_SYSVIEW: pkg.deps.OS_CRASH_LOG: - "@apache-mynewt-core/sys/reboot" +pkg.deps.SYS_MEMFAULT: + - "@apache-mynewt-core/sys/memfault" + pkg.init: os_pkg_init: 'MYNEWT_VAL(OS_SYSINIT_STAGE)' diff --git a/kernel/os/src/arch/cortex_m4/os_fault.c b/kernel/os/src/arch/cortex_m4/os_fault.c index 6809f90982..a201aa006f 100644 --- a/kernel/os/src/arch/cortex_m4/os_fault.c +++ b/kernel/os/src/arch/cortex_m4/os_fault.c @@ -33,6 +33,12 @@ #include "reboot/log_reboot.h" #endif +#if MYNEWT_VAL(SYS_MEMFAULT) +#include "memfault/panics/coredump.h" +#include "memfault/panics/arch/arm/cortex_m.h" +#include "memfault/panics/platform/coredump.h" +#endif + struct exception_frame { uint32_t r0; uint32_t r1; @@ -201,6 +207,34 @@ os_default_irq(struct trap_frame *tf) coredump_dump(®s, sizeof(regs)); #endif +#if MYNEWT_VAL(SYS_MEMFAULT) + sMfltExceptionFrame ef = { + .r0 = tf->ef->r0, + .r1 = tf->ef->r1, + .r2 = tf->ef->r2, + .r3 = tf->ef->r3, + .r12 = tf->ef->r12, + .lr = tf->ef->lr, + .pc = tf->ef->pc, + .xpsr = tf->ef->psr, + }; + + sMfltRegState reg = { + .exception_frame = &ef, + .r4 = tf->r4, + .r5 = tf->r5, + .r6 = tf->r6, + .r7 = tf->r7, + .r8 = tf->r8, + .r9 = tf->r9, + .r10 = tf->r10, + .r11 = tf->r11, + .exc_return = tf->lr, + }; + + memfault_fault_handler(®, kMfltRebootReason_HardFault); +#endif + #if MYNEWT_VAL(OS_CRASH_RESTORE_REGS) if (((SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) < 16) && hal_debugger_connected()) { diff --git a/sys/memfault/pkg.yml b/sys/memfault/pkg.yml new file mode 100644 index 0000000000..f58f23cea9 --- /dev/null +++ b/sys/memfault/pkg.yml @@ -0,0 +1,48 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: sys/memfault +pkg.description: Memfault integration package (https://memfault.com/) +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: +pkg.type: sdk +pkg.deps: + - "@apache-mynewt-core/kernel/os" + - "@apache-mynewt-core/sys/shell" + - "@apache-mynewt-core/sys/flash_map" + - "@apache-mynewt-core/hw/hal" + - "@apache-mynewt-core/mgmt/imgmgr" + - "@mcuboot/boot/bootutil" + +pkg.deps.MEMFAULT_MGMT: + - "@apache-mynewt-mcumgr/cmd/memfault_mgmt" +pkg.init: + memfault_platform_core_init: 501 +pkg.ign_dirs: +pkg.include_dirs: + - "ext/components/core/include" + - "ext/components/demo/include" + - "ext/components/http/include" + - "ext/components/metrics/include" + - "ext/components/panics/include" + - "ext/components/util/include" +pkg.src_dirs: + - "src" + - "ext/components/" diff --git a/sys/memfault/src/memfault_common.h b/sys/memfault/src/memfault_common.h new file mode 100644 index 0000000000..1018fdf0e3 --- /dev/null +++ b/sys/memfault/src/memfault_common.h @@ -0,0 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +void shell_mflt_register(void); diff --git a/sys/memfault/src/memfault_demo_cli.c b/sys/memfault/src/memfault_demo_cli.c new file mode 100644 index 0000000000..20eaf6bf3a --- /dev/null +++ b/sys/memfault/src/memfault_demo_cli.c @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "shell/shell.h" + +#include "memfault/demo/cli.h" +#include "memfault/metrics/metrics.h" + +#include "memfault_common.h" + +static int +prv_clear_core_cmd(int argc, char **argv) +{ + return memfault_demo_cli_cmd_clear_core(argc, argv); +} + +static int +prv_get_core_cmd(int argc, char **argv) +{ + return memfault_demo_cli_cmd_get_core(argc, argv); +} + +static int +prv_crash_example(int argc, char **argv) +{ + return memfault_demo_cli_cmd_crash(argc, argv); +} + +static int +prv_get_device_info(int argc, char **argv) +{ + return memfault_demo_cli_cmd_get_device_info(argc, argv); +} + +static int +prv_print_chunk_cmd(int argc, char **argv) +{ + return memfault_demo_cli_cmd_print_chunk(argc, argv); +} + +static int +prv_heartbeat_trigger(int argc, char **argv) +{ + memfault_metrics_heartbeat_debug_trigger(); + return 0; +} + +static int +prv_heartbeat_print(int argc, char **argv) +{ + memfault_metrics_heartbeat_debug_print(); + return 0; +} + +static const struct shell_cmd os_commands[] = { + SHELL_CMD("crash", prv_crash_example, NULL), + SHELL_CMD("clear_core", prv_clear_core_cmd, NULL), + SHELL_CMD("get_core", prv_get_core_cmd, NULL), + SHELL_CMD("get_device_info", prv_get_device_info, NULL), + SHELL_CMD("print_chunk", prv_print_chunk_cmd, NULL), + SHELL_CMD("heartbeat_trigger", prv_heartbeat_trigger, NULL), + SHELL_CMD("heartbeat_print", prv_heartbeat_print, NULL), + {0}, +}; + +void +shell_mflt_register(void) +{ + int rc; + +#if !MYNEWT_VAL(SYS_MEMFAULT_CLI) + return; +#endif + + rc = shell_register("mflt", os_commands); + SYSINIT_PANIC_ASSERT_MSG( + rc == 0, "Failed to register OS shell commands"); + + shell_register_default_module("mflt"); +} diff --git a/sys/memfault/src/memfault_platform_core.c b/sys/memfault/src/memfault_platform_core.c new file mode 100644 index 0000000000..4744cffa8f --- /dev/null +++ b/sys/memfault/src/memfault_platform_core.c @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "sysinit/sysinit.h" +#include "os/os.h" + +#include "memfault/core/debug_log.h" +#include "memfault/core/event_storage.h" +#include "memfault/core/trace_event.h" +#include "memfault/metrics/metrics.h" +#include "memfault/metrics/platform/timer.h" +#include "memfault/panics/reboot_tracking.h" +#include "memfault/panics/platform/coredump.h" + +#include "memfault_common.h" + +/* Your .ld file: + * MEMORY + * { + * [...] + * NOINIT (rw) : ORIGIN = , LENGTH = 64 + * } + * SECTIONS + * { + * .noinit (NOLOAD): { KEEP(*(*.mflt_reboot_info)) } > NOINIT + * } + */ +static uint8_t s_reboot_tracking[MEMFAULT_REBOOT_TRACKING_REGION_SIZE] + __attribute__((section(".mflt_reboot_info"))); + +static struct os_callout metrics_callout; +static uint32_t metrics_period_sec; +static MemfaultPlatformTimerCallback *metrics_callback; + +static void +metrics_callout_cb(struct os_event *ev) +{ + if (metrics_callback) { + metrics_callback(); + } + os_callout_reset(&metrics_callout, + os_time_ms_to_ticks32(metrics_period_sec * 1000)); +} + +void +memfault_platform_halt_if_debugging(void) +{ + if (hal_debugger_connected()) { + __asm("bkpt"); + } +} + +void +memfault_platform_reboot(void) +{ + os_reboot(HAL_RESET_REQUESTED); + MEMFAULT_UNREACHABLE; +} + +bool +memfault_platform_metrics_timer_boot(uint32_t period_sec, + MemfaultPlatformTimerCallback callback) +{ + metrics_period_sec = period_sec; + metrics_callback = callback; + metrics_callout_cb(NULL); + return true; +} + +uint64_t +memfault_platform_get_time_since_boot_ms(void) +{ + return (uint64_t) (os_get_uptime_usec() / 1000); +} + +void +memfault_platform_core_init(void) +{ + static uint8_t s_event_storage[MYNEWT_VAL(MEMFAULT_EVENT_STORAGE_SIZE)]; + int rc; + + SYSINIT_ASSERT_ACTIVE(); + os_callout_init(&metrics_callout, os_eventq_dflt_get(), + metrics_callout_cb, NULL); + SYSINIT_PANIC_ASSERT(metrics_callout.c_evq != NULL); + + const sResetBootupInfo reset_reason = { + .reset_reason_reg = NRF_POWER->RESETREAS, + }; + + memfault_reboot_tracking_boot(s_reboot_tracking, &reset_reason); + /* Note: MCU reset reason register bits are usually "sticky" and + * need to be cleared. + */ + NRF_POWER->RESETREAS |= NRF_POWER->RESETREAS; + + const sMemfaultEventStorageImpl *evt_storage = + memfault_events_storage_boot(s_event_storage, sizeof(s_event_storage)); + + /* Pass the storage to collect reset info */ + memfault_reboot_tracking_collect_reset_info(evt_storage); + /* Pass the storage to initialize the trace event module */ + memfault_trace_event_boot(evt_storage); + + /* NOTE: crash count represents the number of unexpected reboots since the + * last heartbeat was reported. In the simplest case if reboots are + * unexpected, this can just be set to 1 but see memfault/metrics/metrics.h + * how this can be tracked with the reboot_tracking module. + */ + sMemfaultMetricBootInfo boot_info = { + .unexpected_reboot_count = memfault_reboot_tracking_get_crash_count() + }; + rc = memfault_metrics_boot(evt_storage, &boot_info); + /* NOTE: a non-zero value indicates a configuration error took place */ + SYSINIT_PANIC_ASSERT(rc == 0); + + memfault_reboot_tracking_reset_crash_count(); + + sMfltCoredumpStorageInfo info; + memfault_platform_coredump_storage_get_info(&info); + + shell_mflt_register(); +} + diff --git a/sys/memfault/src/memfault_platform_debug_log.c b/sys/memfault/src/memfault_platform_debug_log.c new file mode 100644 index 0000000000..8c981dfade --- /dev/null +++ b/sys/memfault/src/memfault_platform_debug_log.c @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "console/console.h" +#include "memfault/core/platform/debug_log.h" + +#include + +#ifndef MEMFAULT_DEBUG_LOG_BUFFER_SIZE_BYTES +#define MEMFAULT_DEBUG_LOG_BUFFER_SIZE_BYTES (128) +#endif + +void +memfault_platform_log(eMemfaultPlatformLogLevel level, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + + char log_buf[MEMFAULT_DEBUG_LOG_BUFFER_SIZE_BYTES]; + vsnprintf(log_buf, sizeof(log_buf), fmt, args); + + const char *lvl_str = "???"; + switch (level) { + case kMemfaultPlatformLogLevel_Debug: + lvl_str = "dbg"; + break; + + case kMemfaultPlatformLogLevel_Info: + lvl_str = "inf"; + break; + + case kMemfaultPlatformLogLevel_Warning: + lvl_str = "wrn"; + break; + + case kMemfaultPlatformLogLevel_Error: + lvl_str = "err"; + break; + + default: + break; + } + console_printf("<%s> : %s\n", lvl_str, log_buf); + + va_end(args); +} + +void +memfault_platform_log_raw(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + console_printf("\n"); +} diff --git a/sys/memfault/src/memfault_platform_flash_backed_coredump.c b/sys/memfault/src/memfault_platform_flash_backed_coredump.c new file mode 100644 index 0000000000..c3bf5ee74c --- /dev/null +++ b/sys/memfault/src/memfault_platform_flash_backed_coredump.c @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include + +#include "flash_map/flash_map.h" +#include "hal/hal_bsp.h" +#include "img_mgmt/img_mgmt.h" +#include "syscfg/syscfg.h" +#include "sysflash/sysflash.h" + +#include "memfault/core/math.h" +#include "memfault/panics/platform/coredump.h" + + +const sMfltCoredumpRegion * +memfault_platform_coredump_get_regions(const sCoredumpCrashInfo *crash_info, + size_t *num_regions) +{ + static sMfltCoredumpRegion s_coredump_regions[1]; + int area_cnt; + + const struct hal_bsp_mem_dump *mem = hal_bsp_core_dump(&area_cnt); + s_coredump_regions[0].region_size = mem->hbmd_size; + s_coredump_regions[0].region_start = mem->hbmd_start; + s_coredump_regions[0].type = kMfltCoredumpRegionType_Memory; + + *num_regions = MEMFAULT_ARRAY_SIZE(s_coredump_regions); + + return s_coredump_regions; +} + +int +prv_flash_open(const struct flash_area **fa) +{ + int slot; + + if (flash_area_open(MYNEWT_VAL(MEMFAULT_COREDUMP_FLASH_AREA), fa)) { + return -OS_ERROR; + } + + /* Don't overwrite an image that has any flags set (pending, active, or + * confirmed). + */ + slot = flash_area_id_to_image_slot(MYNEWT_VAL(MEMFAULT_COREDUMP_FLASH_AREA)); + if (slot != -1 && img_mgmt_slot_in_use(slot)) { + return -OS_ERROR; + } + + return OS_OK; +} + +void +memfault_platform_coredump_storage_get_info(sMfltCoredumpStorageInfo *info) +{ + const struct flash_area *fa; + + if (prv_flash_open(&fa)) { + assert(0); + } + + *info = (sMfltCoredumpStorageInfo) { + .size = fa->fa_size, + .sector_size = fa->fa_size, + }; +} + +bool +memfault_platform_coredump_storage_read(uint32_t offset, void *data, + size_t read_len) +{ + const struct flash_area *fa; + + if (prv_flash_open(&fa)) { + return false; + } + + if ((offset + read_len) > fa->fa_size) { + return false; + } + + if (flash_area_read(fa, offset, data, read_len)) { + return false; + } + + return true; +} + +bool +memfault_platform_coredump_storage_erase(uint32_t offset, size_t erase_size) +{ + const struct flash_area *fa; + + if (prv_flash_open(&fa)) { + return false; + } + + if ((offset + erase_size) > fa->fa_size) { + return false; + } + + if (flash_area_erase(fa, offset, erase_size)) { + return false; + } + + return true; +} + +bool +memfault_platform_coredump_storage_write(uint32_t offset, const void *data, + size_t data_len) +{ + const struct flash_area *fa; + + if (prv_flash_open(&fa)) { + return false; + } + + if ((offset + data_len) > fa->fa_size) { + return false; + } + + if (flash_area_write(fa, offset, data, data_len)) { + return false; + } + + return true; +} + +void +memfault_platform_coredump_storage_clear(void) +{ + const struct flash_area *fa; + + if (prv_flash_open(&fa)) { + assert(0); + } + + /* Erasing whole area takes too much time and causes + * ble connection to time out. Instead erase only + * the magic value. + */ + if (flash_area_erase(fa, 0, sizeof(uint32_t))) { + assert(0); + } +} diff --git a/sys/memfault/syscfg.yml b/sys/memfault/syscfg.yml new file mode 100644 index 0000000000..2951f49637 --- /dev/null +++ b/sys/memfault/syscfg.yml @@ -0,0 +1,41 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + SYS_MEMFAULT: + description: Memfault is enabled + value: 1 + + SYS_MEMFAULT_CLI: + description: Memfault CLI is enabled + value: 0 + + MEMFAULT_EVENT_STORAGE_SIZE: + description: Storage size for Memfault events + value: 1024 + + MEMFAULT_COREDUMP_FLASH_AREA: + description: 'Flash area to write core files to.' + type: 'flash_owner' + value: + restrictions: + - '$notnull' + + MEMFAULT_MGMT: + description: 'Expose "memfault" command in mgmt.' + value: 0