xref: /aosp_15_r20/external/pigweed/pw_cpu_exception/docs.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1.. _module-pw_cpu_exception:
2
3================
4pw_cpu_exception
5================
6Pigweed's exception module provides a consistent interface for entering an
7application's CPU exception handler. While the actual exception handling
8behavior is left to an application to implement, this module deals with any
9architecture-specific actions required before calling the application exception
10handler. More specifically, the exception module collects CPU state that may
11otherwise be clobbered by an application's exception handler.
12
13-----
14Setup
15-----
16This module has three facades, each of whose backends must be provided by the
17target or application.
18
19Entry facade
20============
21This is the library that handles early exception entry and prepares any CPU
22state that must be available to the exception handler via the
23pw_cpu_exception_State object. The backend for this facade is
24architecture-specific.
25
26An application using this module **must** connect ``pw_cpu_exception_Entry()`` to
27the platform's CPU exception handler interrupt so ``pw_cpu_exception_Entry()`` is
28called immediately upon a CPU exception. For specifics on how this may be done,
29see the backend documentation for your architecture.
30
31The GN variable to set the backend for this facade is
32``pw_cpu_exception_ENTRY_BACKEND``.
33
34Handler facade
35==============
36This facade is backed by an application-specific handler that determines what to
37do when an exception is encountered. This may be capturing a crash report before
38resetting the device, or in some cases handling the exception to allow execution
39to continue.
40
41Applications must also provide an implementation for
42``pw_cpu_exception_DefaultHandler()``. The behavior of this functions is entirely
43up to the application/project, but some examples are provided below:
44
45* Enter an infinite loop so the device can be debugged by JTAG.
46* Reset the device.
47* Attempt to handle the exception so execution can continue.
48* Capture and record additional device state and save to flash for a crash
49  report.
50* A combination of the above, using logic that fits the needs of your project.
51
52The GN variable to set the backend for this facade is
53``pw_cpu_exception_HANDLER_BACKEND``.
54
55Support facade
56==============
57This facade provides architecture-independent functions that may be helpful for
58dumping CPU state in various forms. This allows an application to create an
59application-specific handler that is portable across multiple architectures.
60
61The GN variable to set the backend for this facade is
62``pw_cpu_exception_SUPPORT_BACKEND``.
63
64Avoiding circular dependencies with the entry facade
65====================================================
66The entry facade is hard tied to the definition of the
67``pw_cpu_exception_State``, so spliting them into separate facades would require
68extra configurations along with extra compatibility checks to ensure they are
69never mismatched.
70
71In GN, this circular dependency is avoided by collecting the backend's full
72implementation including the entry method through the
73``pw_cpu_exception:entry_impl`` group. When ``pw_cpu_exception_ENTRY_BACKEND``
74is set, ``$dir_pw_cpu_exception:entry_impl`` must listed in the
75``pw_build_LINK_DEPS`` variable. See :ref:`module-pw_build-link-deps`.
76
77Entry backends must provide their own ``*.impl`` target that collects their
78entry implementation.
79
80In Bazel, this circular dependency is avoided by putting the backend's full
81implementation including the entry method into a separate override-able
82``entry_backend_impl`` library. When the entry facade is being used, the
83application should add a dependency on the
84``//pw_cpu_exception:entry_backend_impl`` label_flag.
85
86------------
87Module Usage
88------------
89Basic usage of this module entails applications supplying a definition for
90``pw_cpu_exception_DefaultHandler()``. ``pw_cpu_exception_DefaultHandler()`` should
91contain any logic to determine if a exception can be recovered from, as well as
92necessary actions to properly recover. If the device cannot recover from the
93exception, the function should **not** return.
94
95``pw_cpu_exception_DefaultHandler()`` is called indirectly, and may be overridden
96at runtime via ``pw_cpu_exception_SetHandler()``. The handler can also be reset to
97point to ``pw_cpu_exception_DefaultHandler()`` by calling
98``pw_cpu_exception_RestoreDefaultHandler()``.
99
100When writing an exception handler, prefer to use the functions provided by this
101interface rather than relying on the backend implementation of
102``pw_cpu_exception_State``. This allows better code portability as it helps
103prevent an application fault handler from being tied to a single backend.
104
105For example; when logging or dumping CPU state, prefer ``ToString()`` or
106``RawFaultingCpuState()`` over directly accessing members of a
107``pw_cpu_exception_State`` object.
108
109Some exception handling behavior may require architecture-specific CPU state to
110attempt to correct a fault. In this situation, the application's exception
111handler will be tied to the backend implementation of the CPU exception module.
112
113--------------------
114Backend Expectations
115--------------------
116CPU exception backends do not provide an exception handler, but instead provide
117mechanisms to capture CPU state for use by an application's exception handler,
118and allow recovery from CPU exceptions when possible.
119
120* The entry backend should provide a definition for the
121  ``pw_cpu_exception_State`` object through
122  ``pw_cpu_exception_backend/state.h``.
123* In GN, the entry backend should also provide a ``.impl`` suffixed form of the
124  entry backend target which collects the actual entry implementation to avoid
125  circular dependencies due to the state definition in the entry backend target.
126* The entry backend should implement the ``pw_cpu_exception_Entry()`` function
127  that will call ``pw_cpu_exception_HandleException()`` after performing any
128  necessary actions prior to handing control to the application's exception
129  handler (e.g. capturing necessary CPU state).
130* If an application's exception handler backend modifies the captured CPU state,
131  the state should be treated as though it were the original state of the CPU
132  when the exception occurred. The backend may need to manually restore some of
133  the modified state to ensure this on exception handler return.
134
135-------------
136Compatibility
137-------------
138Most of the pw_cpu_exception module is C-compatible. The exception to this is
139the "support" facade and library, which requires C++.
140
141------------
142Dependencies
143------------
144- :ref:`module-pw_span`
145- :ref:`module-pw_preprocessor`
146
147.. toctree::
148   :hidden:
149   :maxdepth: 1
150
151   Backends <backends>
152