133 lines
6.0 KiB
ReStructuredText
133 lines
6.0 KiB
ReStructuredText
.. _module-pw_cpu_exception:
|
|
|
|
================
|
|
pw_cpu_exception
|
|
================
|
|
Pigweed's exception module provides a consistent interface for entering an
|
|
application's CPU exception handler. While the actual exception handling
|
|
behavior is left to an application to implement, this module deals with any
|
|
architecture-specific actions required before calling the application exception
|
|
handler. More specifically, the exception module collects CPU state that may
|
|
otherwise be clobbered by an application's exception handler.
|
|
|
|
-----
|
|
Setup
|
|
-----
|
|
This module has three facades, each of whose backends are set with a
|
|
different GN variable.
|
|
|
|
``pw_cpu_exception_ENTRY_BACKEND``
|
|
==================================
|
|
This is the library that handles early exception entry and prepares any CPU
|
|
state that must be available to the exception handler via the
|
|
pw_cpu_exception_State object. The backend for this facade is
|
|
architecture-specific.
|
|
|
|
An application using this module **must** connect ``pw_cpu_exception_Entry()`` to
|
|
the platform's CPU exception handler interrupt so ``pw_cpu_exception_Entry()`` is
|
|
called immediately upon a CPU exception. For specifics on how this may be done,
|
|
see the backend documentation for your architecture.
|
|
|
|
``pw_cpu_exception_HANDLER_BACKEND``
|
|
====================================
|
|
This facade is backed by an application-specific handler that determines what to
|
|
do when an exception is encountered. This may be capturing a crash report before
|
|
resetting the device, or in some cases handling the exception to allow execution
|
|
to continue.
|
|
|
|
Applications must also provide an implementation for
|
|
``pw_cpu_exception_DefaultHandler()``. The behavior of this functions is entirely
|
|
up to the application/project, but some examples are provided below:
|
|
|
|
* Enter an infinite loop so the device can be debugged by JTAG.
|
|
* Reset the device.
|
|
* Attempt to handle the exception so execution can continue.
|
|
* Capture and record additional device state and save to flash for a crash
|
|
report.
|
|
* A combination of the above, using logic that fits the needs of your project.
|
|
|
|
``pw_cpu_exception_SUPPORT_BACKEND``
|
|
====================================
|
|
This facade provides architecture-independent functions that may be helpful for
|
|
dumping CPU state in various forms. This allows an application to create an
|
|
application-specific handler that is portable across multiple architectures.
|
|
|
|
Avoiding circular dependencies with ``pw_cpu_exception_ENTRY_BACKEND``
|
|
======================================================================
|
|
The entry facade is hard tied to the definition of the
|
|
``pw_cpu_exception_State``, so spliting them into separate facades would require
|
|
extra configurations along with extra compatibility checks to ensure they are
|
|
never mismatched.
|
|
|
|
In GN, this circular dependency is avoided by collecting the backend's full
|
|
implementation including the entry method through the
|
|
``pw_cpu_exception:entry_impl`` group. When ``pw_cpu_exception_ENTRY_BACKEND``
|
|
is set, ``$dir_pw_cpu_exception:entry_impl`` must listed in the
|
|
``pw_build_LINK_DEPS`` variable. See :ref:`module-pw_build-link-deps`.
|
|
|
|
Entry backends must provide their own ``*.impl`` target that collects their
|
|
entry implementation.
|
|
|
|
------------
|
|
Module Usage
|
|
------------
|
|
Basic usage of this module entails applications supplying a definition for
|
|
``pw_cpu_exception_DefaultHandler()``. ``pw_cpu_exception_DefaultHandler()`` should
|
|
contain any logic to determine if a exception can be recovered from, as well as
|
|
necessary actions to properly recover. If the device cannot recover from the
|
|
exception, the function should **not** return.
|
|
|
|
``pw_cpu_exception_DefaultHandler()`` is called indirectly, and may be overridden
|
|
at runtime via ``pw_cpu_exception_SetHandler()``. The handler can also be reset to
|
|
point to ``pw_cpu_exception_DefaultHandler()`` by calling
|
|
``pw_cpu_exception_RestoreDefaultHandler()``.
|
|
|
|
When writing an exception handler, prefer to use the functions provided by this
|
|
interface rather than relying on the backend implementation of
|
|
``pw_cpu_exception_State``. This allows better code portability as it helps
|
|
prevent an application fault handler from being tied to a single backend.
|
|
|
|
For example; when logging or dumping CPU state, prefer ``ToString()`` or
|
|
``RawFaultingCpuState()`` over directly accessing members of a
|
|
``pw_cpu_exception_State`` object.
|
|
|
|
Some exception handling behavior may require architecture-specific CPU state to
|
|
attempt to correct a fault. In this situation, the application's exception
|
|
handler will be tied to the backend implementation of the CPU exception module.
|
|
|
|
--------------------
|
|
Backend Expectations
|
|
--------------------
|
|
CPU exception backends do not provide an exception handler, but instead provide
|
|
mechanisms to capture CPU state for use by an application's exception handler,
|
|
and allow recovery from CPU exceptions when possible.
|
|
|
|
* The entry backend should provide a definition for the
|
|
``pw_cpu_exception_State`` object through
|
|
``pw_cpu_exception_backend/state.h``.
|
|
* In GN, the entry backend should also provide a ``.impl`` suffixed form of
|
|
the entry backend target which collects the actual entry implementation to
|
|
avoid circular dependencies due to the state definition in the entry backend
|
|
target.
|
|
* The entry backend should implement the ``pw_cpu_exception_Entry()`` function
|
|
that will call ``pw_cpu_exception_HandleException()`` after performing any
|
|
necessary actions prior to handing control to the application's exception
|
|
handler (e.g. capturing necessary CPU state).
|
|
* If an application's exception handler backend modifies the captured CPU
|
|
state, the state should be treated as though it were the original state of
|
|
the CPU when the exception occurred. The backend may need to manually
|
|
restore some of the modified state to ensure this on exception handler
|
|
return.
|
|
|
|
-------------
|
|
Compatibility
|
|
-------------
|
|
Most of the pw_cpu_exception module is C-compatible. The exception to this is
|
|
the "support" facade and library, which requires C++.
|
|
|
|
------------
|
|
Dependencies
|
|
------------
|
|
* ``pw_span``
|
|
* ``pw_preprocessor``
|