|  | .. _chapter-pw-cpu-exception: | 
|  |  | 
|  | .. default-domain:: cpp | 
|  |  | 
|  | .. highlight:: cpp | 
|  |  | 
|  | ---------------- | 
|  | 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 | 
|  | ===== | 
|  | An application using this module **must** connect ``pw_CpuExceptionEntry()`` to | 
|  | the platform's CPU exception handler interrupt so ``pw_CpuExceptionEntry()`` is | 
|  | called immediately upon a CPU exception. For specifics on how this may be done, | 
|  | see the backend documentation for your architecture. | 
|  |  | 
|  | Applications must also provide an implementation for | 
|  | ``pw::cpu_exception::HandleCpuException()``. 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. | 
|  |  | 
|  | Module Usage | 
|  | ============ | 
|  | Basic usage of this module entails applications supplying a definition for | 
|  | ``pw::cpu_exception::HandleCpuException()``. ``HandleCpuException()`` 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. | 
|  |  | 
|  | When writing an exception handler, prefer to use the functions provided by this | 
|  | interface rather than relying on the backend implementation of ``CpuState``. | 
|  | 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 ``CpuState`` | 
|  | 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. | 
|  |  | 
|  | Dependencies | 
|  | ============ | 
|  | * ``pw_span`` | 
|  | * ``pw_preprocessor`` | 
|  |  | 
|  | 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. | 
|  |  | 
|  | * A backend should provide a definition for the ``CpuState`` struct that | 
|  | provides suitable means to access and modify any captured CPU state. | 
|  | * If an application's exception handler 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. | 
|  | * A backend should implement the ``pw_CpuExceptionEntry()`` function that will | 
|  | call ``HandleCpuException()`` after performing any necessary actions prior | 
|  | to handing control to the application's exception handler (e.g. capturing | 
|  | necessary CPU state). |