Skip to content

Commit

Permalink
[spinel] add support for logging crash dumps (#10061)
Browse files Browse the repository at this point in the history
This commit adds a new feature that allows platforms to log crash logs.

### Additions
- `void otPlatLogCrashDump(void)` - API that logs a crash dump using
  OpenThread Logging APIs
- `SPINEL_PROP_RCP_LOG_CRASH_DUMP` - spinel prop that calls
  `otPlatLogCrashDump()` when `Set`
- `SPINEL_CAP_RCP_LOG_CRASH_DUMP` - spinel capability denoting that a
  RCP supports logging crash dumps

### Usage
- For `ot-cli-ftd|mtd`, `otPlatLogCrashDump()` is called at the end of
  app initialization, before the main loop. See [main.c]
- For Host/RCP setups, during initialization, the Host gets the RCP
  capabilities. If the RCP has the `SPINEL_CAP_RCP_LOG_CRASH_DUMP`
  capability, the Host will `Set` the `SPINEL_PROP_RCP_LOG_CRASH_DUMP`
  property, triggering the RCP to call `otPlatLogCrashDump()`.
  - If RCP Recovery is enabled, the this will also happen once the RCP
    has been restored
  • Loading branch information
lmnotran authored Apr 29, 2024
1 parent 2408c89 commit 502797c
Show file tree
Hide file tree
Showing 15 changed files with 100 additions and 1 deletion.
1 change: 1 addition & 0 deletions etc/cmake/options.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ ot_option(OT_OTNS OPENTHREAD_CONFIG_OTNS_ENABLE "OTNS")
ot_option(OT_PING_SENDER OPENTHREAD_CONFIG_PING_SENDER_ENABLE "ping sender" ${OT_APP_CLI})
ot_option(OT_PLATFORM_BOOTLOADER_MODE OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE "platform bootloader mode")
ot_option(OT_PLATFORM_KEY_REF OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE "platform key reference secure storage")
ot_option(OT_PLATFORM_LOG_CRASH_DUMP OPENTHREAD_CONFIG_PLATFORM_LOG_CRASH_DUMP_ENABLE "platform log crash dump")
ot_option(OT_PLATFORM_NETIF OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE "platform netif")
ot_option(OT_PLATFORM_POWER_CALIBRATION OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE "power calibration")
ot_option(OT_PLATFORM_UDP OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE "platform UDP")
Expand Down
5 changes: 5 additions & 0 deletions examples/apps/cli/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <openthread/diag.h>
#include <openthread/tasklet.h>
#include <openthread/platform/logging.h>
#include <openthread/platform/misc.h>

#include "openthread-system.h"
#include "cli/cli_config.h"
Expand Down Expand Up @@ -140,6 +141,10 @@ int main(int argc, char *argv[])
IgnoreError(otCliSetUserCommands(kCommands, OT_ARRAY_LENGTH(kCommands), instance));
#endif

#if OPENTHREAD_CONFIG_PLATFORM_LOG_CRASH_DUMP_ENABLE
otPlatLogCrashDump();
#endif

while (!otSysPseudoResetWasRequested())
{
otTaskletsProcess(instance);
Expand Down
11 changes: 11 additions & 0 deletions examples/platforms/simulation/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <setjmp.h>
#include <unistd.h>

#include <openthread/logging.h>
#include <openthread/platform/misc.h>

#include "openthread-system.h"
Expand Down Expand Up @@ -108,3 +109,13 @@ otPlatMcuPowerState otPlatGetMcuPowerState(otInstance *aInstance)

return gPlatMcuPowerState;
}

#if OPENTHREAD_CONFIG_PLATFORM_LOG_CRASH_DUMP_ENABLE
otError otPlatLogCrashDump(void)
{
otLogCritPlat("LOGGING SIMULATED CRASH DUMP");
otLogCritPlat("Reset Reason: %d", sPlatResetReason);

return OT_ERROR_NONE;
}
#endif
10 changes: 10 additions & 0 deletions include/openthread/platform/misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,16 @@ otError otPlatSetMcuPowerState(otInstance *aInstance, otPlatMcuPowerState aState
*/
otPlatMcuPowerState otPlatGetMcuPowerState(otInstance *aInstance);

/**
* Logs a crash dump using OpenThread logging APIs
*
* @note This API is an optional logging platform API. It's up to the platform layer to implement it.
*
* @retval OT_ERROR_NONE Crash dump was logged successfully
* @retval OT_ERROR_NOT_CAPABLE Platform is not capable of logging a crash dump
*/
otError otPlatLogCrashDump(void);

/**
* @}
*
Expand Down
2 changes: 2 additions & 0 deletions script/test
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ build_simulation()
"-DOT_MESSAGE_USE_HEAP=OFF"
"-DOT_NETDATA_PUBLISHER=ON"
"-DOT_PING_SENDER=ON"
"-DOT_PLATFORM_LOG_CRASH_DUMP=ON"
"-DOT_REFERENCE_DEVICE=ON"
"-DOT_SERVICE=ON"
"-DOT_SRP_CLIENT=ON"
Expand Down Expand Up @@ -173,6 +174,7 @@ build_posix()
"-DBUILD_TESTING=ON"
"-DOT_MESSAGE_USE_HEAP=ON"
"-DOT_PLATFORM_BOOTLOADER_MODE=ON"
"-DOT_PLATFORM_LOG_CRASH_DUMP=ON"
"-DOT_THREAD_VERSION=${version}"
)

Expand Down
14 changes: 14 additions & 0 deletions src/core/config/misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,20 @@
#define OPENTHREAD_CONFIG_BLE_TCAT_ENABLE 0
#endif

/**
* @def OPENTHREAD_CONFIG_PLATFORM_LOG_CRASH_DUMP_ENABLE
*
* Define to 1 to enable crash dump logging.
*
* On platforms that support crash dump logging, this feature will log a crash dump using the OT Debug Log service.
*
* Logging a crash dump requires the platform to implement the `otPlatLogCrashDump()` function.
*
*/
#ifndef OPENTHREAD_CONFIG_PLATFORM_LOG_CRASH_DUMP_ENABLE
#define OPENTHREAD_CONFIG_PLATFORM_LOG_CRASH_DUMP_ENABLE 0
#endif

/**
* @}
*
Expand Down
9 changes: 9 additions & 0 deletions src/lib/spinel/logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,15 @@ void Logger::LogSpinelFrame(const uint8_t *aFrame, uint16_t aLength, bool aTx)
}
break;

case SPINEL_PROP_RCP_LOG_CRASH_DUMP:
{
const char *name;
name = "log-crash-dump";

start += Snprintf(start, static_cast<uint32_t>(end - start), ", %s", name);
}
break;

case SPINEL_PROP_MAC_ENERGY_SCAN_RESULT:
case SPINEL_PROP_PHY_CHAN_MAX_POWER:
{
Expand Down
14 changes: 13 additions & 1 deletion src/lib/spinel/radio_spinel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ bool RadioSpinel::sSupportsLogStream =

bool RadioSpinel::sSupportsResetToBootloader = false; ///< RCP supports resetting into bootloader mode.

bool RadioSpinel::sSupportsLogCrashDump = false; ///< RCP supports logging a crash dump.

otRadioCaps RadioSpinel::sRadioCaps = OT_RADIO_CAPS_NONE;

RadioSpinel::RadioSpinel(void)
Expand Down Expand Up @@ -147,6 +149,12 @@ void RadioSpinel::Init(SpinelInterface &aSpinelInterface,
SuccessOrExit(error = Get(SPINEL_PROP_HWADDR, SPINEL_DATATYPE_EUI64_S, sIeeeEui64.m8));
InitializeCaps(supportsRcpApiVersion, supportsRcpMinHostApiVersion);

if (sSupportsLogCrashDump)
{
LogDebg("RCP supports crash dump logging. Requesting crash dump.");
SuccessOrExit(error = Set(SPINEL_PROP_RCP_LOG_CRASH_DUMP, nullptr));
}

if (!aSkipRcpCompatibilityCheck)
{
SuccessOrDie(CheckRcpApiVersion(supportsRcpApiVersion, supportsRcpMinHostApiVersion));
Expand Down Expand Up @@ -212,8 +220,9 @@ void RadioSpinel::InitializeCaps(bool &aSupportsRcpApiVersion, bool &aSupportsRc

sSupportsLogStream = mSpinelDriver.CoprocessorHasCap(SPINEL_CAP_OPENTHREAD_LOG_METADATA);
aSupportsRcpApiVersion = mSpinelDriver.CoprocessorHasCap(SPINEL_CAP_RCP_API_VERSION);
sSupportsResetToBootloader = mSpinelDriver.CoprocessorHasCap(SPINEL_CAP_RCP_RESET_TO_BOOTLOADER);
aSupportsRcpMinHostApiVersion = mSpinelDriver.CoprocessorHasCap(SPINEL_CAP_RCP_MIN_HOST_API_VERSION);
sSupportsResetToBootloader = mSpinelDriver.CoprocessorHasCap(SPINEL_CAP_RCP_RESET_TO_BOOTLOADER);
sSupportsLogCrashDump = mSpinelDriver.CoprocessorHasCap(SPINEL_CAP_RCP_LOG_CRASH_DUMP);
}

otError RadioSpinel::CheckRadioCapabilities(void)
Expand Down Expand Up @@ -2001,6 +2010,9 @@ void RadioSpinel::RecoverFromRcpFailure(void)
}

--mRcpFailureCount;

SuccessOrDie(Set(SPINEL_PROP_RCP_LOG_CRASH_DUMP, nullptr));

LogNote("RCP recovery is done");

exit:
Expand Down
1 change: 1 addition & 0 deletions src/lib/spinel/radio_spinel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1247,6 +1247,7 @@ class RadioSpinel : private Logger
static bool sIsReady; ///< NCP ready.
static bool sSupportsLogStream; ///< RCP supports `LOG_STREAM` property with OpenThread log meta-data format.
static bool sSupportsResetToBootloader; ///< RCP supports resetting into bootloader mode.
static bool sSupportsLogCrashDump; ///< RCP supports logging a crash dump.

#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0

Expand Down
2 changes: 2 additions & 0 deletions src/lib/spinel/spinel.c
Original file line number Diff line number Diff line change
Expand Up @@ -1427,6 +1427,7 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
{SPINEL_PROP_SERVER_LEADER_SERVICES, "SERVER_LEADER_SERVICES"},
{SPINEL_PROP_RCP_API_VERSION, "RCP_API_VERSION"},
{SPINEL_PROP_RCP_MIN_HOST_API_VERSION, "RCP_MIN_HOST_API_VERSION"},
{SPINEL_PROP_RCP_LOG_CRASH_DUMP, "RCP_LOG_CRASH_DUMP"},
{SPINEL_PROP_UART_BITRATE, "UART_BITRATE"},
{SPINEL_PROP_UART_XON_XOFF, "UART_XON_XOFF"},
{SPINEL_PROP_15_4_PIB_PHY_CHANNELS_SUPPORTED, "15_4_PIB_PHY_CHANNELS_SUPPORTED"},
Expand Down Expand Up @@ -1608,6 +1609,7 @@ const char *spinel_capability_to_cstr(spinel_capability_t capability)
{SPINEL_CAP_RCP_API_VERSION, "RCP_API_VERSION"},
{SPINEL_CAP_RCP_MIN_HOST_API_VERSION, "RCP_MIN_HOST_API_VERSION"},
{SPINEL_CAP_RCP_RESET_TO_BOOTLOADER, "RCP_RESET_TO_BOOTLOADER"},
{SPINEL_CAP_RCP_LOG_CRASH_DUMP, "RCP_LOG_CRASH_DUMP"},
{SPINEL_CAP_MAC_ALLOWLIST, "MAC_ALLOWLIST"},
{SPINEL_CAP_MAC_RAW, "MAC_RAW"},
{SPINEL_CAP_OOB_STEERING_DATA, "OOB_STEERING_DATA"},
Expand Down
11 changes: 11 additions & 0 deletions src/lib/spinel/spinel.h
Original file line number Diff line number Diff line change
Expand Up @@ -1296,6 +1296,7 @@ enum
SPINEL_CAP_RCP_API_VERSION = (SPINEL_CAP_RCP__BEGIN + 0),
SPINEL_CAP_RCP_MIN_HOST_API_VERSION = (SPINEL_CAP_RCP__BEGIN + 1),
SPINEL_CAP_RCP_RESET_TO_BOOTLOADER = (SPINEL_CAP_RCP__BEGIN + 2),
SPINEL_CAP_RCP_LOG_CRASH_DUMP = (SPINEL_CAP_RCP__BEGIN + 3),
SPINEL_CAP_RCP__END = 80,

SPINEL_CAP_OPENTHREAD__BEGIN = 512,
Expand Down Expand Up @@ -4399,6 +4400,16 @@ enum
*/
SPINEL_PROP_RCP_MIN_HOST_API_VERSION = SPINEL_PROP_RCP__BEGIN + 1,

/// Crash Dump
/** Format: Empty : Write only
*
* Required capability: SPINEL_CAP_RADIO and SPINEL_CAP_RCP_LOG_CRASH_DUMP.
*
* Writing to this property instructs the RCP to log a crash dump if available.
*
*/
SPINEL_PROP_RCP_LOG_CRASH_DUMP = SPINEL_PROP_RCP__BEGIN + 2,

SPINEL_PROP_RCP__END = 0xFF,

SPINEL_PROP_INTERFACE__BEGIN = 0x100,
Expand Down
4 changes: 4 additions & 0 deletions src/ncp/ncp_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1947,6 +1947,10 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CAPS>(void)
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_RCP_RESET_TO_BOOTLOADER));
#endif

#if OPENTHREAD_CONFIG_PLATFORM_LOG_CRASH_DUMP_ENABLE
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_RCP_LOG_CRASH_DUMP));
#endif

#if OPENTHREAD_PLATFORM_POSIX
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_POSIX));
#endif
Expand Down
8 changes: 8 additions & 0 deletions src/ncp/ncp_base_dispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,13 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey)
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SERVER_ALLOW_LOCAL_DATA_CHANGE),
#endif
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD

#if OPENTHREAD_CONFIG_PLATFORM_LOG_CRASH_DUMP_ENABLE && OPENTHREAD_RADIO
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_RCP_LOG_CRASH_DUMP),
#endif

#if OPENTHREAD_MTD || OPENTHREAD_FTD
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_CNTR_RESET),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_CNTR_ALL_MAC_COUNTERS),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_CNTR_MLE_COUNTERS),
Expand All @@ -487,6 +494,7 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey)
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_CNTR_MAC_RETRY_HISTOGRAM),
#endif
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD

#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_RCP_MAC_KEY),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_RCP_MAC_FRAME_COUNTER),
Expand Down
5 changes: 5 additions & 0 deletions src/ncp/ncp_base_radio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <openthread/link.h>
#include <openthread/link_raw.h>
#include <openthread/ncp.h>
#include <openthread/platform/misc.h>
#include <openthread/platform/multipan.h>
#include <openthread/platform/radio.h>
#include <openthread/platform/time.h>
Expand Down Expand Up @@ -614,6 +615,10 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_RCP_ENH_ACK_PROBING>(
}
#endif

#if OPENTHREAD_CONFIG_PLATFORM_LOG_CRASH_DUMP_ENABLE
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_RCP_LOG_CRASH_DUMP>(void) { return otPlatLogCrashDump(); }
#endif

} // namespace Ncp
} // namespace ot

Expand Down
4 changes: 4 additions & 0 deletions tests/unit/test_platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -844,4 +844,8 @@ OT_TOOL_WEAK void otPlatDnssdUnregisterKey(otInstance *aInstance

#endif // OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE

#if OPENTHREAD_CONFIG_PLATFORM_LOG_CRASH_DUMP_ENABLE
OT_TOOL_WEAK otError otPlatLogCrashDump(void) { return OT_ERROR_NONE; }
#endif

} // extern "C"

0 comments on commit 502797c

Please sign in to comment.