diff --git a/Kconfig b/Kconfig
index 0ce1787a86307162b2425dac359c19a6c988800e..8735d494abf09b4fa7a3bba5db1d23e911a6c82e 100644
--- a/Kconfig
+++ b/Kconfig
@@ -21,6 +21,15 @@ config PRINT_BUFSIZE
 	int
 	default 128
 
+config ASSERT
+	bool "Build assertion checks in the code"
+	default y
+	  help
+	    Build assertions in the code, to catch unexpected situations.
+	    When an assertion fails the code loops over repeating the
+	    error message every second. OTOH, panic() is always built,
+	    with no Kconfig -- and it does the same, unconditionally.
+  
 config RAMSIZE
 	int
 	default 65536 if WR_SWITCH
diff --git a/include/assert.h b/include/assert.h
new file mode 100644
index 0000000000000000000000000000000000000000..c4aa7f16158ad59b8d3e9cc9e7af654f23db05a7
--- /dev/null
+++ b/include/assert.h
@@ -0,0 +1,33 @@
+#ifndef __ASSERT_H__
+#define __ASSERT_H__
+
+/*
+ * Both panic and assert loop over the console, re-printing the
+ * message, so you can connnect to a paniced node and see the message
+ * that caused the panic.  assert_warn(condition) is once only, like
+ * warn_on(!condition) in the kernel.
+ */
+
+extern void panic(const char *fmt, ...)
+        __attribute__((format(printf,1,2)));
+
+#define assert(cond, fmt, ...) \
+	if (CONFIG_HAS_ASSERT && !(cond)) \
+		__assert(__func__, __LINE__, 1 /* forever */, fmt  __VA_ARGS__)
+
+#define assert_warn(cond, fmt, ...) \
+	if (CONFIG_HAS_ASSERT && !(cond)) \
+		__assert(__func__, __LINE__, 0 /* once */, fmt  __VA_ARGS__)
+
+
+extern void __assert(const char *func, int line, int forever,
+		     const char *fmt, ...)
+	__attribute__((format(printf, 4, 5)));
+
+#ifdef CONFIG_ASSERT
+#  define CONFIG_HAS_ASSERT 1
+#else
+#  define CONFIG_HAS_ASSERT 0
+#endif
+
+#endif /* __ASSERT_H__ */
diff --git a/lib/assert.c b/lib/assert.c
new file mode 100644
index 0000000000000000000000000000000000000000..eef81bc486bc2cd868a1bd8431cd29cc314e5e12
--- /dev/null
+++ b/lib/assert.c
@@ -0,0 +1,37 @@
+#include <stdarg.h>
+#include <assert.h>
+#include <wrc.h>
+
+void panic(const char *fmt, ...)
+{
+	va_list args;
+
+	while (1) {
+		pp_printf("Panic: ");
+		va_start(args, fmt);
+		vprintf(fmt, args);
+		va_end(args);
+		usleep(1000 * 1000);
+	}
+}
+
+void __assert(const char *func, int line, int forever,
+		     const char *fmt, ...)
+{
+	va_list args;
+
+	while (1) {
+		pp_printf("Assertion failed (%s:%i)", func, line);
+		if (fmt && fmt[0]) {
+			pp_printf(": ");
+			va_start(args, fmt);
+			vprintf(fmt, args);
+			va_end(args);
+		} else {
+			pp_printf(".\n");
+		}
+		if (!forever)
+			break;
+		usleep(1000 * 1000);
+	}
+}
diff --git a/lib/lib.mk b/lib/lib.mk
index 9d797e9a5877c1c9b1dbe359b5eb9d51529146d6..9034edea91e32d3289f3e480efb9c6fddd884530 100644
--- a/lib/lib.mk
+++ b/lib/lib.mk
@@ -1,4 +1,5 @@
 obj-y += lib/util.o
+obj-y += lib/assert.o
 
 obj-$(CONFIG_LM32) += \
 	lib/atoi.o \