1.. _showcase-sense-tutorial-crash-handler: 2 3===================================== 415. Handle crashes and view snapshots 5===================================== 6When a system crashes it can be difficult to debug the cause of the 7crash. To help with this, :ref:`pw_system <module-pw_system>` provides 8a crash handler built on :ref:`module-pw_cpu_exception` which is invoked 9when a CPU exception is triggered. 10 11The :ref:`pw_system <module-pw_system>` crash handler will automatically 12create a crash snapshot on exception and reboot the system. This snapshot can 13then be downloaded onto a host system for analysis. 14 15 16.. _showcase-sense-tutorial-crash-handler-crash: 17 18---------------- 19Generate a crash 20---------------- 21``pw_system`` provides an RPC to crash the system by triggering a 22`HardFault <https://developer.arm.com/documentation/107706/0100/System-exceptions/Fault-exceptions-and-their-causes>`_. 23To invoke this RPC, type the following into the **Python Repl** 24 25.. code-block:: pycon 26 27 >>> device.rpcs.pw.system.proto.DeviceService.Crash() 28 29If you're using the :ref:`full setup <showcase-sense-tutorial-full>`, on 30system restart, the presence of a crash snapshot will be detected, and 31the following will be in the system logs: 32 33.. code-block:: text 34 35 INF pw_system RpcDevice 00:00:00.000 pw_system main 36 ERR pw_system RpcDevice 00:00:00.000 ========================== 37 ERR pw_system RpcDevice 00:00:00.000 ======CRASH DETECTED====== 38 ERR pw_system RpcDevice 00:00:00.000 ========================== 39 ERR pw_system RpcDevice 00:00:00.000 Crash snapshots available. 40 ERR pw_system RpcDevice 00:00:00.000 Run `device.get_crash_snapshots()` to download and clear the snapshots. 41 INF pw_system RpcDevice 00:00:00.000 System init 42 43 44On a :ref:`basic setup <showcase-sense-tutorial-basic>`, the snapshot 45will still be generated, but logs won't be visible in the console. When 46the system restarts, the connection to the console is broken so logs 47will not be displayed. After invoking the ``Crash()`` RPC, exit the console 48and :ref:`start it again <showcase-sense-tutorial-pico-rpc-interact>` to 49re-establish the connection. 50 51.. _showcase-sense-tutorial-crash-handler-view: 52 53--------------------- 54View a crash snapshot 55--------------------- 56 57The crash snapshot contains relevant information to debug crashes, such 58as register state thread backtraces and un-flushed logs. If there is a 59crash snapshot on the system, it can be downloaded to the host with the 60following RPC. 61 62.. code-block:: pycon 63 64 >>> device.get_crash_snapshots() 65 66This RPC will download the snapshot, decode it and save it in a 67temporary directory, the location of which will be printed to the 68console as follows: 69 70.. code-block:: text 71 72 INF Wrote crash snapshot to: /var/folders/2j/sjk9390d5rxc3c9ycwcf3mdh0103lh/T/crash_0.txt 73 74It's also possible to specify the path as part of the RPC call: 75 76.. code-block:: pycon 77 78 >>> device.get_crash_snapshots("/path/") 79 80The decoded text file should look similar to this truncated example: 81 82.. code-block:: 83 84 Device crash cause: 85 pw_system/device_service_pwpb.cc:38 Crash: RPC triggered crash 86 87 Reason token: 0x735f7770 88 CPU Arch: ARMV8M 89 90 Exception caused by a usage fault. 91 92 Active Crash Fault Status Register (CFSR) fields: 93 UNDEFINSTR Undefined Instruction UsageFault. 94 The processor has attempted to execute an undefined 95 instruction. When this bit is set to 1, the PC value stacked 96 for the exception return points to the undefined instruction. 97 An undefined instruction is an instruction that the processor 98 cannot decode. 99 100 All registers: 101 pc 0x10000f0a pw::system::DeviceServicePwpb::Crash(pw::system::proto::pwpb::CrashRequest::Message const&, pw::system::proto::pwpb::CrashResponse::Message&) (/b/pw_system/device_service_pwpb.cc:38) 102 lr 0x10012787 pw::StringBuilder::FormatVaList(char const*, std::__va_list) (/build/pw_string/string_builder.cc:102) 103 psr 0x41000000 104 msp 0x20081fe0 __scratch_y_end__ (??:?) 105 psp 0x2000a100 pw::system::rpc_thread_context (freertos_target_hooks.cc:0) 106 exc_return 0xfffffffd 107 cfsr 0x00010000 108 msplim 0x00000000 109 psplim 0x20002288 110 mmfar 0xe000ed34 __scratch_y_end__ (??:?) 111 bfar 0xe000ed38 __scratch_y_end__ (??:?) 112 icsr 0x00400806 113 hfsr 0x00000000 114 shcsr 0x00070008 115 control 0x00000000 116 r0 0x2000a0e0 pw::system::rpc_thread_context (freertos_target_hooks.cc:0) 117 r1 0x0000003e pw_assert_basic_HandleFailure (/b/pw_assert_basic/basic_handler.cc:74) 118 r2 0x0000002b pw_assert_basic_HandleFailure (/b/pw_assert_basic/basic_handler.cc:74) 119 r3 0x2000a100 pw::system::rpc_thread_context (freertos_target_hooks.cc:0) 120 r4 0x10019596 121 r5 0x2000a178 pw::system::rpc_thread_context (freertos_target_hooks.cc:0) 122 r6 0x10019eec pw::system::proto::pw_rpc::pwpb::DeviceService::Service<pw::system::DeviceServicePwpb>::kPwRpcMethods (??:?) 123 r7 0x2000a108 pw::system::rpc_thread_context (freertos_target_hooks.cc:0) 124 r8 0x2000a118 pw::system::rpc_thread_context (freertos_target_hooks.cc:0) 125 r9 0x2000a16e pw::system::rpc_thread_context (freertos_target_hooks.cc:0) 126 r10 0x2000b4f0 pw::system::(anonymous namespace)::server (hdlc_rpc_server.cc:0) 127 r11 0x2000a22c pw::system::rpc_thread_context (freertos_target_hooks.cc:0) 128 r12 0x00000008 pw_assert_HandleFailure (/b/pw_assert_basic/assert_basic.cc:20) 129 130 Thread State 131 6 threads running, RpcThread active at the time of capture. 132 ~~~~~~~~~ 133 134 Thread (RUNNING): RpcThread <-- [ACTIVE] 135 Est CPU usage: unknown 136 Stack info 137 Current usage: 0x2000a288 - 0x2000a100 (392 bytes, 1.20%) 138 Est peak usage: 944 bytes, 2.88% 139 Stack limits: 0x2000a288 - 0x2000228c (32764 bytes) 140 Stack Trace (most recent call first): 141 1: at void pw::rpc::internal::PwpbMethod::CallSynchronousUnary<pw::system::proto::pwpb::RebootRequest::Message, pw::system::proto::pwpb::RebootResponse::Message>(pw::rpc::internal::CallContext const&, pw::rpc::internal::Packet const&, pw::system::proto::pwpb::RebootRequest::Message&, pw::system::proto::pwpb::RebootResponse::Message&) const (0x10000F59) 142 in /build/pw_rpc/pwpb/public/pw_rpc/pwpb/internal/method.h:258 143 2: at void pw::rpc::internal::PwpbMethod::CallSynchronousUnary<pw::system::proto::pwpb::CrashRequest::Message, pw::system::proto::pwpb::CrashResponse::Message>(pw::rpc::internal::CallContext const&, pw::rpc::internal::Packet const&, pw::system::proto::pwpb::CrashRequest::Message&, pw::system::proto::pwpb::CrashResponse::Message&) const (0x10001137) 144 in /build/pw_rpc/pwpb/public/pw_rpc/pwpb/internal/method.h:267 145 3: at xQueueSemaphoreTake (0x10013049) 146 in /build/external/freertos+/queue.c:1555 147 4: at void pw::rpc::internal::PwpbMethod::SynchronousUnaryInvoker<pw::system::proto::pwpb::CrashRequest::Message, pw::system::proto::pwpb::CrashResponse::Message>(pw::rpc::internal::CallContext const&, pw::rpc::internal::Packet const&) (0x10000F4F) 148 in /build/pw_rpc/pwpb/public/pw_rpc/pwpb/internal/method.h:322 149 5: at pw::rpc::Server::ProcessPacket(pw::rpc::internal::Packet) (0x1000EA9D) 150 in /build/pw_rpc/public/pw_rpc/internal/method.h:0 151 6: at pw::rpc::Server::ProcessPacket(pw::span<std::byte const, 4294967295u>) (0x1000E9CD) 152 in /build/pw_rpc/server.cc:40 153 7: at pw::system::RpcDispatchThread::Run() (0x10008625) 154 in /build/pw_system/hdlc_rpc_server.cc:127 155 8: at pw::thread::freertos::Context::ThreadEntryPoint(void*) (0x1000EFA5) 156 in /build/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/function.h:362 157 9: at prvTaskExitError (0x100137C9) 158 in /build/external/freertos+/portable/GCC/ARM_CM33_NTZ/non_secure/port.c:634 159 160 ... 161 162 Device Logs: 163 [RpcDevice] pw_system 0 pw_system main targets/rp2040/boot.cc:56 164 [RpcDevice] pw_system 0 System init pw_system/init.cc:65 165 [RpcDevice] pw_system 0 Registering RPC services pw_system/init.cc:75 166 167 ... 168 169 170.. _showcase-sense-tutorial-crash-handler-summary: 171 172------- 173Summary 174------- 175On this page, we met ``pw_cpu_exception``, the CPU exception handler entry point. 176We also learned how to generate crashes and download the resulting crash snapshot. 177 178Next, head over to :ref:`showcase-sense-tutorial-outro` to wrap up your 179tour of Pigweed. 180