console: Add semihosting console

Many chips have only one serial port. When the serial port is occupied
by other devices, there is a lack of a console to output debugging
information. Semihosting can provide a console. The disadvantage of
semihosting is that a debugger must be connected, so it can only be
used for online debugging.

Signed-off-by: ZhongYao Luo <LuoZhongYao@gmail.com>
Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
diff --git a/CODEOWNERS b/CODEOWNERS
index 0da97fc..456cbf3 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -139,6 +139,7 @@
 /drivers/can/*mcp2515*                    @karstenkoenig
 /drivers/clock_control/*nrf*              @nordic-krch
 /drivers/counter/                         @nordic-krch
+/drivers/console/semihost_console.c       @luozhongyao
 /drivers/counter/counter_cmos.c           @andrewboie
 /drivers/counter/maxim_ds3231.c           @pabigot
 /drivers/crypto/*nrf_ecb*                 @maciekfabia @anangl
diff --git a/drivers/console/CMakeLists.txt b/drivers/console/CMakeLists.txt
index dfd8331..ddb5652 100644
--- a/drivers/console/CMakeLists.txt
+++ b/drivers/console/CMakeLists.txt
@@ -11,3 +11,4 @@
 zephyr_sources_if_kconfig(native_posix_console.c)
 zephyr_sources_if_kconfig(uart_mux.c)
 zephyr_sources_if_kconfig(gsm_mux.c)
+zephyr_sources_if_kconfig(semihost_console.c)
diff --git a/drivers/console/Kconfig b/drivers/console/Kconfig
index 33a907f..0603254 100644
--- a/drivers/console/Kconfig
+++ b/drivers/console/Kconfig
@@ -291,6 +291,20 @@
 	help
 	  Device driver initialization priority.
 
+config SEMIHOST_CONSOLE
+	bool "Use semihosting for console"
+	select CONSOLE_HAS_DRIVER
+	depends on CPU_CORTEX_M
+	help
+	  Enable this option to use semihosting for console.
+	  Semihosting is a mechanism that enables code running on an ARM target
+	  to communicate and use the Input/Output facilities on a host computer
+	  that is running a debugger.
+	  Additional information can be found in:
+	  https://developer.arm.com/docs/dui0471/k/what-is-semihosting/what-is-semihosting
+	  This option is compatible with hardware and with QEMU, through the
+	  (automatic) use of the -semihosting-config switch when invoking it.
+
 module = UART_CONSOLE
 module-str = UART console
 source "subsys/logging/Kconfig.template.log_config"
diff --git a/drivers/console/semihost_console.c b/drivers/console/semihost_console.c
new file mode 100644
index 0000000..fbe276c
--- /dev/null
+++ b/drivers/console/semihost_console.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019 LuoZhongYao
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <kernel.h>
+#include <device.h>
+#include <init.h>
+#include <sys/printk.h>
+
+extern void __printk_hook_install(int (*fn)(int));
+extern void __stdout_hook_install(int (*fn)(int));
+
+static int semihost_console_out(int ch)
+{
+	static unsigned char c;
+
+	c = ch;
+	__asm__ __volatile__ (
+		"movs	r1, %0\n"
+		"movs	r0, #3\n"
+		"bkpt	0xab\n"
+		:
+		: "r" (&c)
+		: "r0", "r1");
+	return ch;
+}
+
+static int semihost_console_init(struct device *dev)
+{
+	ARG_UNUSED(dev);
+
+	__printk_hook_install(semihost_console_out);
+	__stdout_hook_install(semihost_console_out);
+
+	return 0;
+}
+
+SYS_INIT(semihost_console_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);