xref: /aosp_15_r20/external/pigweed/docs/showcases/sense/tutorial/crash_handler.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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