pw_assert_basic: add a handler facade layer

Splits up the pw_assert_basic module to add a facade layer to
allow a user to provide a custom pw_assert_basic_HandleFailure()
implementation. The existing handler, previously named pw_Crash(),
was moved to a basic_handler facade which mirrors the
pw_cpu_exception structure and naming.

Unlike pw_cpu_exception, pw_assert_basic defaults to the
basic_handler backend.

This refactor should allow users, especially during initial
bringup, to trivially bring up assert support with target specific
handlers with less code duplication and complications.

Note that pw_assert_basic is still not recommended for production
use as it is rather heavy weight, we strongly recommend using
tokenized asserts.

Change-Id: I3a0c0aacc9a88d44b35b24ad0a13dd7e2badc209
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/28520
Commit-Queue: Ewout van Bekkum <ewout@google.com>
Reviewed-by: Keir Mierle <keir@google.com>
diff --git a/pw_assert_basic/docs.rst b/pw_assert_basic/docs.rst
index 45ff8f7..2ddc367 100644
--- a/pw_assert_basic/docs.rst
+++ b/pw_assert_basic/docs.rst
@@ -7,5 +7,60 @@
 --------
 Overview
 --------
-This is a simple assert backend to implement the ``pw_assert`` facade.
+This is a simple assert backend to implement the ``pw_assert`` facade which
+relies on a single function ``pw_assert_basic_HandleFailure`` handler facade
+which defaults to the ``basic_handler`` backend. Users may be interested in
+overriding this default in case they need to do things like transition to
+crash time logging or implementing application specific reset and/or hang
+behavior.
 
+.. attention::
+
+  This log backend comes with a very large ROM and potentially RAM cost. It is
+  intended mostly for ease of initial bringup. We encourage teams to use
+  tokenized asserts since they are much smaller both in terms of ROM and RAM.
+
+Custom handler backend example
+------------------------------
+Here is a typical usage example implementing a simple handler backend which uses
+a UART backed sys_io implementation to print during crash time and then reboots.
+Note that this example uses CMSIS and a psuedo STM HAL, as a backend implementer
+you are responsible for using whatever APIs make sense for your use case(s).
+
+.. code-block:: cpp
+
+  #include "cmsis.h"
+  #include "hal.h"
+  #include "pw_string/string_builder.h"
+
+  using pw::sys_io::WriteLine;
+
+  extern "C" void pw_assert_basic_HandleFailure(
+      [[maybe_unused]] const char* file_name,
+      [[maybe_unused]] int line_number,
+      [[maybe_unused]] const char* function_name,
+      const char* message,
+      ...) {
+    // Global interrupt disable for a single core microcontroller.
+    __disable_irq();
+
+    // Re-initialize the UART to ensure it's safe to use at crash time.
+    HAL_UART_DeInit(sys_io_uart);
+    HAL_UART_Init(sys_io_uart);
+
+    WriteLine(
+        "  Welp, that didn't go as planned. "
+        "It seems we crashed. Terribly sorry! Assert reason:");
+    {
+      pw::StringBuffer<150> buffer;
+      buffer << "     ";
+      va_list args;
+      va_start(args, format);
+      buffer.FormatVaList(format, args);
+      va_end(args);
+      WriteLine(buffer.view());
+    }
+
+    // Reboot the microcontroller.
+    HAL_NVIC_SystemReset();
+  }