Demo CLI for Zephyr RTOS
The demo CLI lets you explore features of the SDK components before integrating the SDK into your product. You might also find it helpful to adapt the CLI to your product and use it to exercise your own Memfault implementation.
This guide explains the commands available in the demo CLI built for Zephyr-based platforms and how to interpret their output.
Enabling the Demo CLI
The demo CLI is enabled automatically through Zephyr's build system, however here are the steps to confirm the demo CLI is part of your build:
-
Set the required Kconfigs in prj.conf, other conf files, or through default values:
CONFIG_SHELL=y
CONFIG_MEMFAULT=y
CONFIG_MEMFAULT_SHELL=yNote that for NCS, there is an additional set of shell commands, which are enabled by default when
CONFIG_MEMFAULT_SHELL=y
but are explicitly enabled with:CONFIG_MEMFAULT_NRF_SHELL=y
Running a Command
The CLI displays a prompt to indicate it is ready to accept a command. To see if the CLI is running, press enter and the prompt should be printed:
uart:~$ mflt
To run a command, type mflt
followed by its name and press enter. Try the
mflt
command to get started.
Command Reference
mflt
The mflt
command shows all available commands. Type mflt
and press enter:
uart:~$ mflt
mflt - Memfault Test Commands
Subcommands:
clear_core :clear coredump collected
export :dump chunks collected by Memfault SDK using
https://mflt.io/chunk-data-export
get_core :check if coredump is stored and present
get_device_info :display device information
get_latest_release :checks to see if new ota payload is available
coredump_size :print coredump computed size and storage capacity
Heartbeat_dump :dump current Memfault metrics Heartbeat state
post_chunks :Post Memfault data to cloud
test :commands to verify memfault data collection
(https://mflt.io/mcu-test-commands)
uart:~$
Some reference implementations have more commands than others. For example, some
targets have network connectivity and can send data directly to the Memfault
cloud via the post_chunks
command. Devices without this
ability will not have that command.
get_device_info
The get_device_info
command shows the information configured in the reference
implementation's memfault_platform_get_device_info()
:
uart:~$ get_device_info
[08:50:44.140,000] <inf> mflt: S/N: DEMOSERIAL
[08:50:44.140,000] <inf> mflt: SW type: zephyr-app
[08:50:44.140,000] <inf> mflt: SW version: 1.0.0+35a4cfddd2
[08:50:44.140,000] <inf> mflt: HW version: qemu_cortex_m3
uart:~$
This information is sent to Memfault with any communications to identify the device and the firmware it is running.
test [sub-command]
for crashes
Most test
commands exercise Memfault through crashing:
test assert
- trigger a Memfault asserttest busfault
- trigger a C asserttest hang
- trigger a busfaulttest hardfault
- trigger a hardfaulttest memmanage
- trigger a memory management faulttest usagefault
- trigger a usage faulttest zassert
- trigger a Zephyr asserttest double_free
- trigger a double free errortest badptr
- trigger a fault via a store to a bad addresstest isr_badptr
- trigger a fault via a store to a bad address from an ISR
The crash will be intercepted by the fault handler in the Memfault panics
component, a coredump will be generated and stored, and then the device reboots.
Typically, Build ID and device info will be printed on boot, making it easy to
tell that we have rebooted. For example:
uart:~$ mflt test assert
[00:00:13.290,000] <err> os: ***** USAGE FAULT *****
[00:00:13.290,000] <err> os: Attempt to execute undefined instruction
[00:00:13.290,000] <err> os: r0/a1: 0x00008001 r1/a2: 0x20001fd0 r2/a3: 0x20007148
[00:00:13.290,000] <err> os: r3/a4: 0x0000e1e9 r12/ip: 0x000125b6 r14/lr: 0x000074a5
[00:00:13.290,000] <err> os: xpsr: 0x21000000
[00:00:13.290,000] <err> os: r4/v1: 0x00000000 r5/v2: 0x00000001 r6/v3: 0x000125b6
[00:00:13.290,000] <err> os: r7/v4: 0x20001fe0 r8/v5: 0x20002060 r9/v6: 0x0000f600
[00:00:13.290,000] <err> os: r10/v7: 0x00000002 r11/v8: 0x00000000 psp: 0x20001fb0
[00:00:13.290,000] <err> os: EXC_RETURN: 0xfffffffd
[00:00:13.290,000] <err> os: Faulting instruction address (r15/pc): 0x000074a4
*** Booting Zephyr OS build zephyr-v3.5.0 ***
[00:00:00.000,000] <inf> mflt: GNU Build ID: f7477dc0a82cb2275bb2f3578d9192e426ca09ab
[00:00:00.000,000] <inf> main: 👋 Memfault Demo App! Board qemu_cortex_m3
[00:00:00.000,000] <inf> mflt: S/N: DEMOSERIAL
[00:00:00.000,000] <inf> mflt: SW type: zephyr-app
[00:00:00.000,000] <inf> mflt: SW version: 1.0.0+35a4cfddd2
[00:00:00.000,000] <inf> mflt: HW version: qemu_cortex_m3
uart:~$
If you do not see these messages and the prompt return, nor any other
indications that the system reset, then something may have gone wrong in the
fault handler. Another possibility is that a debugger is attached and it is
sitting on a breakpoint. The fault handler in most reference implementations
will break into the debugger if one is attached. In GDB, you should be able to
use stepi
to resume, but see the README
for the specific reference
implementation you are using in case it has other instructions.
Once the prompt has returned, the storage can be checked with the
get_core
command. It can then be cleared with
clear_core
or read out of the coredump storage with
export
.
Once a coredump has been stored in the coredump storage, it will remain there
until either storage is cleared (clear_core
command) or read
out (export
command). If you crash again without doing one of
these, saving the coredump will fail silently. The device will still crash and
reset but the existing coredump will be overwritten.
get_core
The get_core
command displays the state of the coredump storage.
If a coredump is present in the coredump storage:
uart:~$ mflt get_core
[00:00:57.670,000] <inf> mflt: Has coredump with size: 3572
uart:~$
If a coredump is not present:
uart:~$ mflt get_core
[00:01:33.540,000] <inf> mflt: No coredump present!
uart:~$
Running get_core
only displays information. It does not affect the state of
the coredump storage.
clear_core
The clear_core
command unconditionally invalidates the coredump storage so
that a new coredump can be stored:
uart:~$ mflt clear_core
[00:01:54.730,000] <inf> mflt: Invalidating coredump
uart:~$
The clear_core
command will show the same output regardless of whether a
coredump was present in the coredump storage or not.
heartbeat_dump
The heartbeat_dump
command will print out the current values of the Heartbeat
metrics. If a value has not been written to a metric in the current Heartbeat
window, it's value will be shown as null
.
uart:~$ mflt Heartbeat_dump
[00:02:19.140,000] <inf> mflt: Heartbeat keys/values:
[00:02:19.140,000] <inf> mflt: MemfaultSdkMetric_IntervalMs: 139140
[00:02:19.140,000] <inf> mflt: MemfaultSdkMetric_UnexpectedRebootCount: null
[00:02:19.140,000] <inf> mflt: operational_hours: null
[00:02:19.140,000] <inf> mflt: operational_crashfree_hours: null
[00:02:19.140,000] <inf> mflt: TimerTaskFreeStack: null
[00:02:19.140,000] <inf> mflt: Heap_BytesFree: null
[00:02:19.140,000] <inf> mflt: MainStack_MinBytesFree: null
uart:~$
The Heartbeat metrics will only reset after a Heartbeat interval has expired or
by running the heartbeat
command.
test Heartbeat
The test Heartbeat
command captures the current Heartbeat, writes it to event
storage, and resets the running Heartbeat metrics.
uart:~$ mflt test Heartbeat
Triggering Heartbeat
[00:02:46.150,000] <inf> mflt: Heartbeat keys/values:
[00:02:46.150,000] <inf> mflt: MemfaultSdkMetric_IntervalMs: 166150
[00:02:46.150,000] <inf> mflt: MemfaultSdkMetric_UnexpectedRebootCount: null
[00:02:46.150,000] <inf> mflt: operational_hours: null
[00:02:46.150,000] <inf> mflt: operational_crashfree_hours: null
[00:02:46.150,000] <inf> mflt: TimerTaskFreeStack: 744
[00:02:46.160,000] <inf> mflt: Heap_BytesFree: 4020
[00:02:46.160,000] <inf> mflt: MainStack_MinBytesFree: 3224
uart:~$
The current values of the Heartbeat metrics may or may not get printed like
above depending on if memfault_metrics_heartbeat_debug_print()
is being called
in memfault_metrics_heartbeat_collect_data()
.
memfault_metrics_heartbeat_collect_data()
is a function that can be overridden
with a user definition if they want to set certain metric values at the end of a
Heartbeat right before collection.
test reboot
The test reboot
command records a reboot reason,
the current PC and LR, and then forces a system reboot. This command does not
cause a coredump capture since the reboot recorded is considered an expected
reboot. Unexpected reboot reboots can also be recorded, and are typically paired
with a coredump to aid with debugging.
test logs
The test logs
command writes test logs to Memfault's logging
buffer.
uart:~$ mflt test logs
Raw log!
[00:03:34.480,000] <inf> mflt: Info log!
[00:03:34.480,000] <wrn> mflt: Warning log!
[00:03:34.480,000] <err> mflt: Error log!
uart:~$
test log_capture
The test_log_capture
command captures the current log buffer contents, so they
will be ready once data is exported.
test trace
The test trace
command captures a Trace Event and writes
it to the event storage.
uart:~$ mflt test trace
uart:~$
Once a trace has been captured, it can be read out of the event storage with the
export
command.
The event storage is completely separate from the coredump storage. The commands
get_core
and clear_core
work only on the coredump storage. There are no
equivalents for the event storage.
export
The export
command reads out all data from both the coredump storage and the
event storage. It then formats this data into a base64-encoded
chunk that can be sent to the Memfault
cloud using one of the
strategies described here.
# example export command output
uart:~$ mflt export
MC:CAKnAgIDAQpqemVwaHlyLWFwcAlwMS4wLjArMzVhNGNmZGRkMgZucWVtdV9jb3J0ZXhfbTMLRvdHfcCoLASkARmAAQIZ0WADGeHpBQD3qQ==:
MC:SE8CpwIBAwEKanplcGh5ci1hcHAJcDEuMC4wKzM1YTRjZmRkZDIGbnFlbXVfY29ydGV4X20zC0b3R33AqCwEogIAAYcAA/b2GQyYGQ+0GQw=:
...
uart:~$
The export
command has the side effect of clearing the data. After the
packetizer consumes the coredump storage
and the event storage, they will both be cleared and ready for new data.
If the upload succeeds but you don't see the data processed on Memfault, go to the Processing Log under the "Integration Hub" sub-menu. The Processing Log contains details on what data has been received and processed by Memfault, as well as any error that may have occurred. Note that you need to upload the symbols to get a complete analysis of uploaded coredumps.
post_chunks
The post_chunks
command is available on targets with direct network
connectivity:
uart:~$ mflt post_chunks
Posting Memfault Data
uart:~$
It will read out all data from both the coredump storage and event storage and
then send the data directly to the Memfault cloud. The target must already be
configured on a network and be able to make an HTTPS
connection to the
Memfault cloud servers. A valid Memfault Project Key must also be configured.
See the instructions in the reference implementation for how to do this.
The post_chunks
command has the side effect of clearing the data. After the
packetizer consumes the coredump storage
and the event storage, they will both be cleared and ready for new data.
If the upload succeeds but you don't see the data processed on Memfault, you probably need to upload the symbols.
test self
The test self
command runs tests on the most important subsystems of Memfault
to validate proper integration of the SDK.
get_latest_url
The get_latest_url
command queries Memfault for a OTA update payload. If there
is one available for this device, then the download URL will be printed.
uart:~$ mflt get_latest_url
[00:01:15.304,000] <inf> mflt: Download URL: '<your download url>'
If there is no OTA payload, the command will return immediately:
uart:~$ mflt get_latest_url
Checking for OTA update
Up to date!
get_latest_release
The get_latest_release
command queries Memfault for a OTA update payload. If
there is one available for this device, then the system will proceed to pull the
payload. If CONFIG_MEMFAULT_ZEPHYR_FOTA_BACKEND_MCUBOOT=y
, then the payload
will be written into the secondary slot, and the system will reboot with the new
image.
uart:~$ mflt get_latest_release
[00:01:17.304,000] <inf> mflt: Downloading OTA payload, size=1048576 bytes
[00:01:39.644,000] <inf> mflt: OTA download complete! Rebooting...
*** Booting Zephyr OS build v3.6.0 ***
Otherwise, if CONFIG_MEMFAULT_ZEPHYR_FOTA_BACKEND_DUMMY=y
, then the payload
will not be installed on the device. This option is useful for testing the
download operation.
uart:~$ mflt get_latest_release
[00:01:15.304,000] <inf> mflt: Checking for OTA update
[00:01:17.304,000] <inf> mflt: Downloading OTA payload, size=1048576 bytes
[00:01:39.644,000] <inf> mflt: OTA download complete!
If there is no OTA payload, the command will return immediately:
uart:~$ mflt get_latest_release
[00:01:15.304,000] <inf> mflt: Checking for OTA update
[00:01:17.304,000] <inf> mflt: Up to date!
For further information on performing OTA updates, see the OTA integration guide.
nRF Connect SDK (NCS) Commands
If you are using the nRF Connect SDK, go instead through the mflt_nrf
command
menu for OTA testing.
uart:~$ mflt_nrf
mflt_nrf - Memfault nRF Connect SDK Test Commands
Subcommands:
fota :Perform a FOTA using Memfault client
get_latest_url :Get the latest URL for the latest FOTA
uart:~$
get_latest_url
The mflt_nrf get_latest_url
command queries Memfault for a OTA update payload.
If one is available, the download URL will be printed:
uart:~$ mflt_nrf get_latest_url
[00:01:15.304,000] <inf> mflt: Download URL: '<your download url>'
mflt_nrf fota
Similar to the mflt get_latest_release
command, the mflt_nrf fota
command
queries Memfault for a OTA update payload. If there is one available for this
device, then the system will proceed to pull the payload. Once the payload is
downloaded completely, the system will reboot with the new image.
uart:~$ mflt get_latest_release
[00:00:22.308,074] <inf> Checking for OTA update
[00:00:22.308,074] <inf> mflt: FOTA Update Available. Starting Download!
[00:00:22.308,074] <inf> download_client: Downloading: <your download url>
[00:00:22.308,074] <inf> mflt: FOTA In Progress
[00:00:22.308,074] <inf> download_client: Setting up TLS credentials, sec tag count 1
[00:00:22.308,197] <inf> download_client: Connecting to <download url>
[00:00:24.139,343] <inf> download_client: Downloaded 1024/428252 bytes (0%)
[00:00:24.718,231] <inf> download_client: Downloaded 2048/428252 bytes (0%)
...
[00:02:45.686,706] <inf> download_client: Downloaded 427008/428252 bytes (99%)
uart:~$ *** Booting nRF Connect SDK v2.5.99-dev1-461-gacec825d9b5c ***
SDK Components
This list summarizes which demo CLI commands are used to test each SDK component:
- Core
- Panics
test [sub-command]
for crashesget_core
clear_core
- Logs
- Trace Events
- Metrics
- OTA
get_latest_release
- (NCS)
mflt_nrf get_latest_url
- (NCS)
mflt_nrf fota
Data can be exported and cleared with: