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/BUILD b/pw_assert_basic/BUILD
index 22d063c..a22a266 100644
--- a/pw_assert_basic/BUILD
+++ b/pw_assert_basic/BUILD
@@ -45,7 +45,30 @@
":headers",
"//pw_assert:facade",
"//pw_preprocessor",
+ ],
+)
+
+pw_cc_library(
+ name = "handler_facade",
+ hdrs = [
+ "public/pw_assert_basic/handler.h",
+ ],
+ deps = [
+ "//pw_preprocessor",
+ ],
+)
+
+pw_cc_library(
+ name = "pw_assert_basic_handler",
+ srcs = [
+ "basic_handler.cc",
+ ],
+ deps = [
+ ":headers",
+ "//pw_assert:facade",
+ "//pw_preprocessor",
"//pw_string",
"//pw_sys_io",
+ ":handler_facade",
],
)
diff --git a/pw_assert_basic/BUILD.gn b/pw_assert_basic/BUILD.gn
index a43c95c..a8682f1 100644
--- a/pw_assert_basic/BUILD.gn
+++ b/pw_assert_basic/BUILD.gn
@@ -14,8 +14,10 @@
import("//build_overrides/pigweed.gni")
+import("$dir_pw_build/facade.gni")
import("$dir_pw_build/target_types.gni")
import("$dir_pw_docgen/docs.gni")
+import("backend.gni")
config("default_config") {
include_dirs = [ "public" ]
@@ -25,25 +27,41 @@
include_dirs = [ "public_overrides" ]
}
+pw_facade("handler") {
+ backend = pw_assert_basic_HANDLER_BACKEND
+ public_configs = [ ":default_config" ]
+ public_deps = [ "$dir_pw_preprocessor" ]
+ public = [ "public/pw_assert_basic/handler.h" ]
+}
+
pw_source_set("pw_assert_basic") {
public_configs = [
":backend_config",
":default_config",
]
- deps = [ ":core" ]
- public = [ "public_overrides/pw_assert_backend/assert_backend.h" ]
+ deps = [
+ "$dir_pw_assert:facade",
+ "$dir_pw_preprocessor",
+ pw_assert_basic_HANDLER_BACKEND,
+ ]
+ public = [
+ "public/pw_assert_basic/assert_basic.h",
+ "public/pw_assert_basic/handler.h",
+ "public_overrides/pw_assert_backend/assert_backend.h",
+ ]
+ sources = [ "assert_basic.cc" ]
}
-pw_source_set("core") {
- public_configs = [ ":default_config" ]
+# A basic handler backend using sysio.
+pw_source_set("basic_handler") {
deps = [
+ ":handler.facade",
"$dir_pw_assert:facade",
"$dir_pw_preprocessor",
"$dir_pw_string",
"$dir_pw_sys_io",
]
- public = [ "public/pw_assert_basic/assert_basic.h" ]
- sources = [ "assert_basic.cc" ]
+ sources = [ "basic_handler.cc" ]
}
pw_doc_group("docs") {
diff --git a/pw_assert_basic/assert_basic.cc b/pw_assert_basic/assert_basic.cc
index e6a64f5..72f2e8c 100644
--- a/pw_assert_basic/assert_basic.cc
+++ b/pw_assert_basic/assert_basic.cc
@@ -12,155 +12,18 @@
// License for the specific language governing permissions and limitations under
// the License.
-// This is a very basic direct output log implementation with no buffering.
-
-//#define PW_LOG_MODULE_NAME "ASRT"
-//#include "pw_log/log.h"
-
-#include "pw_assert_basic/assert_basic.h"
-
-#include <cstring>
-
#include "pw_assert/options.h"
-#include "pw_preprocessor/util.h"
-#include "pw_string/string_builder.h"
-#include "pw_sys_io/sys_io.h"
-
-// If 1, call C's standard abort() function on assert failure.
-#ifndef PW_ASSERT_BASIC_ABORT
-#define PW_ASSERT_BASIC_ABORT 1
-#endif // PW_ASSERT_BASIC_ABORT
-
-// TODO(pwbug/17): Expose these through the config system.
-#define PW_ASSERT_BASIC_SHOW_BANNER 1
-#define PW_ASSERT_BASIC_USE_COLORS 1
-
-// ANSI color constants to control the terminal. Not Windows compatible.
-// clang-format off
-#if PW_ASSERT_BASIC_USE_COLORS
-#define MAGENTA "\033[35m"
-#define YELLOW "\033[33m"
-#define RED "\033[31m"
-#define GREEN "\033[32m"
-#define BLUE "\033[96m"
-#define BLACK "\033[30m"
-#define YELLOW_BG "\033[43m"
-#define WHITE_BG "\033[47m"
-#define RED_BG "\033[41m"
-#define BOLD "\033[1m"
-#define RESET "\033[0m"
-#else
-#define MAGENTA ""
-#define YELLOW ""
-#define RED ""
-#define GREEN ""
-#define BLUE ""
-#define BLACK ""
-#define YELLOW_BG ""
-#define WHITE_BG ""
-#define RED_BG ""
-#define BOLD ""
-#define RESET ""
-#endif // PW_ASSERT_BASIC_USE_COLORS
-// clang-format on
-
-static const char* kCrashBanner[] = {
- " ",
- " ▄████▄ ██▀███ ▄▄▄ ██████ ██░ ██ ",
- " ▒██▀ ▀█ ▓██ ▒ ██▒ ▒████▄ ▒██ ▒ ▓██░ ██▒ ",
- " ▒▓█ 💥 ▄ ▓██ ░▄█ ▒ ▒██ ▀█▄ ░ ▓██▄ ▒██▀▀██░ ",
- " ▒▓▓▄ ▄██▒ ▒██▀▀█▄ ░██▄▄▄▄██ ▒ ██▒ ░▓█ ░██ ",
- " ▒ ▓███▀ ░ ░██▓ ▒██▒ ▓█ ▓██▒ ▒██████▒▒ ░▓█▒░██▓ ",
- " ░ ░▒ ▒ ░ ░ ▒▓ ░▒▓░ ▒▒ ▓▒█░ ▒ ▒▓▒ ▒ ░ ▒ ░░▒░▒ ",
- " ░ ▒ ░▒ ░ ▒░ ▒ ▒▒ ░ ░ ░▒ ░ ░ ▒ ░▒░ ░ ",
- " ░ ░░ ░ ░ ▒ ░ ░ ░ ░ ░░ ░ ",
- " ░ ░ ░ ░ ░ ░ ░ ░ ░ ",
- " ░",
- " ",
-};
-
-using pw::sys_io::WriteLine;
-
-typedef pw::StringBuffer<150> Buffer;
-
-extern "C" void pw_Crash(const char* file_name,
- int line_number,
- const char* function_name,
- const char* message,
- ...) {
- // As a matter of usability, crashes should be visible; make it so.
-#if PW_ASSERT_BASIC_SHOW_BANNER
- WriteLine(RED);
- for (const char* line : kCrashBanner) {
- WriteLine(line);
- }
- WriteLine(RESET);
-#endif // PW_ASSERT_BASIC_SHOW_BANNER
-
- WriteLine(
- " Welp, that didn't go as planned. "
- "It seems we crashed. Terribly sorry!");
- WriteLine("");
- WriteLine(YELLOW " CRASH MESSAGE" RESET);
- WriteLine("");
- {
- Buffer buffer;
- buffer << " ";
- va_list args;
- va_start(args, message);
- buffer.FormatVaList(message, args);
- va_end(args);
- WriteLine(buffer.view());
- }
-
- WriteLine("");
- WriteLine(YELLOW " CRASH FILE & LINE" RESET);
- WriteLine("");
- {
- Buffer buffer;
- buffer.Format(" %s:%d", file_name, line_number);
- WriteLine(buffer.view());
- }
- WriteLine("");
- WriteLine(YELLOW " CRASH FUNCTION" RESET);
- WriteLine("");
- {
- Buffer buffer;
- buffer.Format(" %s", function_name);
- WriteLine(buffer.view());
- }
- WriteLine("");
-
- // TODO(pwbug/95): Perhaps surprisingly, this doesn't actually crash the
- // device. At some point we'll have a reboot BSP function or similar, but for
- // now this is acceptable since no one is using this basic backend.
- if (!PW_ASSERT_BASIC_DISABLE_NORETURN) {
- if (PW_ASSERT_BASIC_ABORT) {
- abort();
- } else {
- WriteLine(MAGENTA " HANG TIME" RESET);
- WriteLine("");
- WriteLine(
- " ... until a debugger joins. System is waiting in a while(1)");
- while (1) {
- }
- }
- PW_UNREACHABLE;
- } else {
- WriteLine(MAGENTA " NOTE: YOU ARE IN ASSERT BASIC TEST MODE" RESET);
- WriteLine("");
- WriteLine(" This build returns from the crash handler for testing.");
- WriteLine(" If you see this message in production, your build is ");
- WriteLine(" incorrectly configured. Search for");
- WriteLine(" PW_ASSERT_BASIC_DISABLE_NORETURN to fix it.");
- WriteLine("");
- }
-}
+#include "pw_assert_basic/handler.h"
extern "C" void pw_assert_HandleFailure(void) {
#if PW_ASSERT_ENABLE_DEBUG
- pw_Crash("", 0, "", "Crash: PW_ASSERT() or PW_DASSERT() failure");
+ pw_assert_basic_HandleFailure(
+ nullptr, -1, nullptr, "Crash: PW_ASSERT() or PW_DASSERT() failure");
#else
- pw_Crash("", 0, "", "Crash: PW_ASSERT() failure. Note: PW_DASSERT disabled");
+ pw_assert_basic_HandleFailure(
+ nullptr,
+ -1,
+ nullptr,
+ "Crash: PW_ASSERT() failure. Note: PW_DASSERT disabled");
#endif // PW_ASSERT_ENABLE_DEBUG
}
diff --git a/pw_assert_basic/backend.gni b/pw_assert_basic/backend.gni
new file mode 100644
index 0000000..49e9d33
--- /dev/null
+++ b/pw_assert_basic/backend.gni
@@ -0,0 +1,29 @@
+# Copyright 2020 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+import("//build_overrides/pigweed.gni")
+
+declare_args() {
+ # Handler backend for the pw_assert_basic module which implements
+ # pw_assert_basic_HandleFailure, this defaults to the basic_handler.
+ #
+ # Note: Don't confuse pw_assert_BACKEND and pw_assert_basic_HANDLER_BACKEND:
+ # 1) pw_assert_BACKEND must be set to dir_pw_assert_basic in order to
+ # use this module which ensures that asserts always invoke
+ # pw_assert_basic_HandleFailure.
+ # 2) pw_assert_basic_HANDLER_BACKEND allows you to switch out the
+ # implementation of the handler which is invoked (i.e.
+ # pw_assert_basic_HandleFailure).
+ pw_assert_basic_HANDLER_BACKEND = "$dir_pw_assert_basic:basic_handler"
+}
diff --git a/pw_assert_basic/basic_handler.cc b/pw_assert_basic/basic_handler.cc
new file mode 100644
index 0000000..db2ed8c
--- /dev/null
+++ b/pw_assert_basic/basic_handler.cc
@@ -0,0 +1,162 @@
+// Copyright 2020 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+// This is a very basic direct output log implementation with no buffering.
+
+//#define PW_LOG_MODULE_NAME "ASRT"
+//#include "pw_log/log.h"
+
+#include <cstring>
+
+#include "pw_assert/options.h"
+#include "pw_assert_basic/handler.h"
+#include "pw_preprocessor/util.h"
+#include "pw_string/string_builder.h"
+#include "pw_sys_io/sys_io.h"
+
+// If 1, call C's standard abort() function on assert failure.
+#ifndef PW_ASSERT_BASIC_ABORT
+#define PW_ASSERT_BASIC_ABORT 1
+#endif // PW_ASSERT_BASIC_ABORT
+
+// TODO(pwbug/17): Expose these through the config system.
+#define PW_ASSERT_BASIC_SHOW_BANNER 1
+#define PW_ASSERT_BASIC_USE_COLORS 1
+
+// ANSI color constants to control the terminal. Not Windows compatible.
+// clang-format off
+#if PW_ASSERT_BASIC_USE_COLORS
+#define MAGENTA "\033[35m"
+#define YELLOW "\033[33m"
+#define RED "\033[31m"
+#define GREEN "\033[32m"
+#define BLUE "\033[96m"
+#define BLACK "\033[30m"
+#define YELLOW_BG "\033[43m"
+#define WHITE_BG "\033[47m"
+#define RED_BG "\033[41m"
+#define BOLD "\033[1m"
+#define RESET "\033[0m"
+#else
+#define MAGENTA ""
+#define YELLOW ""
+#define RED ""
+#define GREEN ""
+#define BLUE ""
+#define BLACK ""
+#define YELLOW_BG ""
+#define WHITE_BG ""
+#define RED_BG ""
+#define BOLD ""
+#define RESET ""
+#endif // PW_ASSERT_BASIC_USE_COLORS
+// clang-format on
+
+static const char* kCrashBanner[] = {
+ " ",
+ " ▄████▄ ██▀███ ▄▄▄ ██████ ██░ ██ ",
+ " ▒██▀ ▀█ ▓██ ▒ ██▒ ▒████▄ ▒██ ▒ ▓██░ ██▒ ",
+ " ▒▓█ 💥 ▄ ▓██ ░▄█ ▒ ▒██ ▀█▄ ░ ▓██▄ ▒██▀▀██░ ",
+ " ▒▓▓▄ ▄██▒ ▒██▀▀█▄ ░██▄▄▄▄██ ▒ ██▒ ░▓█ ░██ ",
+ " ▒ ▓███▀ ░ ░██▓ ▒██▒ ▓█ ▓██▒ ▒██████▒▒ ░▓█▒░██▓ ",
+ " ░ ░▒ ▒ ░ ░ ▒▓ ░▒▓░ ▒▒ ▓▒█░ ▒ ▒▓▒ ▒ ░ ▒ ░░▒░▒ ",
+ " ░ ▒ ░▒ ░ ▒░ ▒ ▒▒ ░ ░ ░▒ ░ ░ ▒ ░▒░ ░ ",
+ " ░ ░░ ░ ░ ▒ ░ ░ ░ ░ ░░ ░ ",
+ " ░ ░ ░ ░ ░ ░ ░ ░ ░ ",
+ " ░",
+ " ",
+};
+
+using pw::sys_io::WriteLine;
+
+typedef pw::StringBuffer<150> Buffer;
+
+extern "C" void pw_assert_basic_HandleFailure(const char* file_name,
+ int line_number,
+ const char* function_name,
+ const char* format,
+ ...) {
+ // As a matter of usability, crashes should be visible; make it so.
+#if PW_ASSERT_BASIC_SHOW_BANNER
+ WriteLine(RED);
+ for (const char* line : kCrashBanner) {
+ WriteLine(line);
+ }
+ WriteLine(RESET);
+#endif // PW_ASSERT_BASIC_SHOW_BANNER
+
+ WriteLine(
+ " Welp, that didn't go as planned. "
+ "It seems we crashed. Terribly sorry!");
+ WriteLine("");
+ WriteLine(YELLOW " CRASH MESSAGE" RESET);
+ WriteLine("");
+ {
+ Buffer buffer;
+ buffer << " ";
+ va_list args;
+ va_start(args, format);
+ buffer.FormatVaList(format, args);
+ va_end(args);
+ WriteLine(buffer.view());
+ }
+
+ if (file_name != nullptr && line_number != -1) {
+ WriteLine("");
+ WriteLine(YELLOW " CRASH FILE & LINE" RESET);
+ WriteLine("");
+ {
+ Buffer buffer;
+ buffer.Format(" %s:%d", file_name, line_number);
+ WriteLine(buffer.view());
+ }
+ }
+ if (function_name != nullptr) {
+ WriteLine("");
+ WriteLine(YELLOW " CRASH FUNCTION" RESET);
+ WriteLine("");
+ {
+ Buffer buffer;
+ buffer.Format(" %s", function_name);
+ WriteLine(buffer.view());
+ }
+ }
+
+ // TODO(pwbug/95): Perhaps surprisingly, this doesn't actually crash the
+ // device. At some point we'll have a reboot BSP function or similar, but for
+ // now this is acceptable since no one is using this basic backend.
+ if (!PW_ASSERT_BASIC_DISABLE_NORETURN) {
+ if (PW_ASSERT_BASIC_ABORT) {
+ abort();
+ } else {
+ WriteLine("");
+ WriteLine(MAGENTA " HANG TIME" RESET);
+ WriteLine("");
+ WriteLine(
+ " ... until a debugger joins. System is waiting in a while(1)");
+ while (1) {
+ }
+ }
+ PW_UNREACHABLE;
+ } else {
+ WriteLine("");
+ WriteLine(MAGENTA " NOTE: YOU ARE IN ASSERT BASIC TEST MODE" RESET);
+ WriteLine("");
+ WriteLine(" This build returns from the crash handler for testing.");
+ WriteLine(" If you see this message in production, your build is ");
+ WriteLine(" incorrectly configured. Search for");
+ WriteLine(" PW_ASSERT_BASIC_DISABLE_NORETURN to fix it.");
+ WriteLine("");
+ }
+}
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();
+ }
diff --git a/pw_assert_basic/public/pw_assert_basic/assert_basic.h b/pw_assert_basic/public/pw_assert_basic/assert_basic.h
index 269c0a6..cc933d0 100644
--- a/pw_assert_basic/public/pw_assert_basic/assert_basic.h
+++ b/pw_assert_basic/public/pw_assert_basic/assert_basic.h
@@ -13,42 +13,26 @@
// the License.
#pragma once
+#include "pw_assert_basic/handler.h"
#include "pw_preprocessor/compiler.h"
#include "pw_preprocessor/util.h"
-// This is needed for testing the basic crash handler.
-// TODO(pwbug/17): Replace when Pigweed config system is added.
-#define PW_ASSERT_BASIC_DISABLE_NORETURN 0
-#if PW_ASSERT_BASIC_DISABLE_NORETURN
-#define PW_ASSERT_NORETURN
-#else
-#define PW_ASSERT_NORETURN PW_NO_RETURN
-#endif
-
-PW_EXTERN_C_START
-
-// Crash, including a message with the listed attributes.
-void pw_Crash(const char* file_name,
- int line_number,
- const char* function_name,
- const char* message,
- ...) PW_PRINTF_FORMAT(4, 5) PW_ASSERT_NORETURN;
-
-PW_EXTERN_C_END
+// Die with a message with many attributes included. This is the crash macro
+// frontend that funnels everything into the C handler provided by the user,
+// pw_assert_basic_HandleFailure().
+#define PW_HANDLE_CRASH(...) \
+ pw_assert_basic_HandleFailure( \
+ __FILE__, __LINE__, __func__ PW_COMMA_ARGS(__VA_ARGS__))
// Die with a message with many attributes included. This is the crash macro
-// frontend that funnels everything into the C handler above, pw_Crash().
-#define PW_HANDLE_CRASH(...) \
- pw_Crash(__FILE__, __LINE__, __func__ PW_COMMA_ARGS(__VA_ARGS__))
-
-// Die with a message with many attributes included. This is the crash macro
-// frontend that funnels everything into the C handler above, pw_Crash().
-#define PW_HANDLE_ASSERT_FAILURE(condition_string, message, ...) \
- pw_Crash(__FILE__, \
- __LINE__, \
- __func__, \
- "Check failed: " condition_string \
- ". " message PW_COMMA_ARGS(__VA_ARGS__))
+// frontend that funnels everything into the C handler provided by the user,
+// pw_assert_basic_HandleFailure().
+#define PW_HANDLE_ASSERT_FAILURE(condition_string, message, ...) \
+ pw_assert_basic_HandleFailure(__FILE__, \
+ __LINE__, \
+ __func__, \
+ "Check failed: " condition_string \
+ ". " message PW_COMMA_ARGS(__VA_ARGS__))
// Sample assert failure message produced by the below implementation:
//
@@ -65,7 +49,8 @@
arg_b_val, \
type_fmt, \
message, ...) \
- pw_Crash(__FILE__, \
+ pw_assert_basic_HandleFailure( \
+ __FILE__, \
__LINE__, \
__func__, \
"Check failed: " \
diff --git a/pw_assert_basic/public/pw_assert_basic/handler.h b/pw_assert_basic/public/pw_assert_basic/handler.h
new file mode 100644
index 0000000..33dd354
--- /dev/null
+++ b/pw_assert_basic/public/pw_assert_basic/handler.h
@@ -0,0 +1,45 @@
+// Copyright 2020 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+#pragma once
+
+#include "pw_preprocessor/compiler.h"
+#include "pw_preprocessor/util.h"
+
+// This is needed for testing the basic crash handler.
+// TODO(pwbug/17): Replace when Pigweed config system is added.
+#define PW_ASSERT_BASIC_DISABLE_NORETURN 0
+#if PW_ASSERT_BASIC_DISABLE_NORETURN
+#define PW_ASSERT_NORETURN
+#else
+#define PW_ASSERT_NORETURN PW_NO_RETURN
+#endif
+
+PW_EXTERN_C_START
+
+// Application-defined assert failure handler for pw_assert_basic.
+// file_name - may be nullptr if not available
+// line_number - may be -1 if not available
+// function_name - may be nullptr if not available
+// format & varags - The assert reason can be built using the format string and
+// the varargs.
+//
+// Applications must define this function; it is not defined by pw_assert_basic.
+void pw_assert_basic_HandleFailure(const char* file_name,
+ int line_number,
+ const char* function_name,
+ const char* format,
+ ...)
+ PW_PRINTF_FORMAT(4, 5) PW_ASSERT_NORETURN;
+
+PW_EXTERN_C_END