Snap for 11902131 from c82a8dcb56c4a741b20ccb7ac7063b9bd0d5b234 to 24Q3-release

Change-Id: Ibefc7a058c7483152191cf47c5d454432292d153
diff --git a/etc/cmake/options.cmake b/etc/cmake/options.cmake
index da77ef0..c87a02b 100644
--- a/etc/cmake/options.cmake
+++ b/etc/cmake/options.cmake
@@ -231,6 +231,7 @@
 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")
diff --git a/examples/apps/cli/main.c b/examples/apps/cli/main.c
index 62f7e3f..d0c6be2 100644
--- a/examples/apps/cli/main.c
+++ b/examples/apps/cli/main.c
@@ -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"
@@ -140,6 +141,10 @@
     IgnoreError(otCliSetUserCommands(kCommands, OT_ARRAY_LENGTH(kCommands), instance));
 #endif
 
+#if OPENTHREAD_CONFIG_PLATFORM_LOG_CRASH_DUMP_ENABLE
+    otPlatLogCrashDump();
+#endif
+
     while (!otSysPseudoResetWasRequested())
     {
         otTaskletsProcess(instance);
diff --git a/examples/platforms/simulation/misc.c b/examples/platforms/simulation/misc.c
index 07739a2..a6d7337 100644
--- a/examples/platforms/simulation/misc.c
+++ b/examples/platforms/simulation/misc.c
@@ -31,6 +31,7 @@
 #include <setjmp.h>
 #include <unistd.h>
 
+#include <openthread/logging.h>
 #include <openthread/platform/misc.h>
 
 #include "openthread-system.h"
@@ -108,3 +109,13 @@
 
     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
diff --git a/include/openthread/platform/misc.h b/include/openthread/platform/misc.h
index b1b2021..ecde9ba 100644
--- a/include/openthread/platform/misc.h
+++ b/include/openthread/platform/misc.h
@@ -208,6 +208,16 @@
 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);
+
+/**
  * @}
  *
  */
diff --git a/script/test b/script/test
index a9a71b3..ceab700 100755
--- a/script/test
+++ b/script/test
@@ -104,6 +104,7 @@
         "-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"
@@ -173,6 +174,7 @@
         "-DBUILD_TESTING=ON"
         "-DOT_MESSAGE_USE_HEAP=ON"
         "-DOT_PLATFORM_BOOTLOADER_MODE=ON"
+        "-DOT_PLATFORM_LOG_CRASH_DUMP=ON"
         "-DOT_THREAD_VERSION=${version}"
     )
 
diff --git a/src/core/config/misc.h b/src/core/config/misc.h
index 70e0c12..0b09cf2 100644
--- a/src/core/config/misc.h
+++ b/src/core/config/misc.h
@@ -600,6 +600,20 @@
 #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
+
+/**
  * @}
  *
  */
diff --git a/src/lib/spinel/logger.cpp b/src/lib/spinel/logger.cpp
index 46636c7..c017613 100644
--- a/src/lib/spinel/logger.cpp
+++ b/src/lib/spinel/logger.cpp
@@ -340,6 +340,15 @@
     }
     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:
     {
diff --git a/src/lib/spinel/radio_spinel.cpp b/src/lib/spinel/radio_spinel.cpp
index b250f09..c3f7d91 100644
--- a/src/lib/spinel/radio_spinel.cpp
+++ b/src/lib/spinel/radio_spinel.cpp
@@ -63,6 +63,8 @@
 
 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;
 
 inline bool RadioSpinel::IsFrameForUs(spinel_iid_t aIid)
@@ -164,6 +166,12 @@
 
     VerifyOrDie(IsRcp(supportsRcpApiVersion, supportsRcpMinHostApiVersion), OT_EXIT_RADIO_SPINEL_INCOMPATIBLE);
 
+    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));
@@ -309,6 +317,11 @@
             aSupportsRcpMinHostApiVersion = true;
         }
 
+        if (capability == SPINEL_CAP_RCP_LOG_CRASH_DUMP)
+        {
+            sSupportsLogCrashDump = true;
+        }
+
         capsData += unpacked;
         capsLength -= static_cast<spinel_size_t>(unpacked);
     }
@@ -2183,6 +2196,9 @@
     }
 
     --mRcpFailureCount;
+
+    SuccessOrDie(Set(SPINEL_PROP_RCP_LOG_CRASH_DUMP, nullptr));
+
     LogNote("RCP recovery is done");
 
 exit:
diff --git a/src/lib/spinel/radio_spinel.hpp b/src/lib/spinel/radio_spinel.hpp
index 5f55c75..0b1af77 100644
--- a/src/lib/spinel/radio_spinel.hpp
+++ b/src/lib/spinel/radio_spinel.hpp
@@ -1284,6 +1284,7 @@
     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
 
diff --git a/src/lib/spinel/spinel.c b/src/lib/spinel/spinel.c
index c85d244..683e58f 100644
--- a/src/lib/spinel/spinel.c
+++ b/src/lib/spinel/spinel.c
@@ -1427,6 +1427,7 @@
         {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"},
@@ -1608,6 +1609,7 @@
         {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"},
diff --git a/src/lib/spinel/spinel.h b/src/lib/spinel/spinel.h
index c1865f3..4d5fc28 100644
--- a/src/lib/spinel/spinel.h
+++ b/src/lib/spinel/spinel.h
@@ -1296,6 +1296,7 @@
     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,
@@ -4399,6 +4400,16 @@
      */
     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,
diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp
index 96e3625..6b99b4d 100644
--- a/src/ncp/ncp_base.cpp
+++ b/src/ncp/ncp_base.cpp
@@ -1947,6 +1947,10 @@
     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
diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp
index 48bd97e..112f502 100644
--- a/src/ncp/ncp_base_dispatcher.cpp
+++ b/src/ncp/ncp_base_dispatcher.cpp
@@ -479,6 +479,13 @@
 #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),
@@ -487,6 +494,7 @@
         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),
diff --git a/src/ncp/ncp_base_radio.cpp b/src/ncp/ncp_base_radio.cpp
index cad3ef5..299f341 100644
--- a/src/ncp/ncp_base_radio.cpp
+++ b/src/ncp/ncp_base_radio.cpp
@@ -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>
@@ -614,6 +615,10 @@
 }
 #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
 
diff --git a/tests/unit/test_platform.cpp b/tests/unit/test_platform.cpp
index 2904f60..000ac04 100644
--- a/tests/unit/test_platform.cpp
+++ b/tests/unit/test_platform.cpp
@@ -815,4 +815,8 @@
 
 #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"