1 /*
2  * Copyright (c) 2019 LuoZhongYao
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include <kernel.h>
7 #include <device.h>
8 #include <init.h>
9 
10 extern void __stdout_hook_install(int (*fn)(int));
11 
12 #define SYS_WRITEC 0x03
13 
arch_printk_char_out(int _c)14 int arch_printk_char_out(int _c)
15 {
16 	char c = _c;
17 
18 #if defined(CONFIG_CPU_CORTEX_M)
19 
20 	register unsigned long r0 __asm__("r0") = SYS_WRITEC;
21 	register void *r1 __asm__("r1") = &c;
22 
23 	__asm__ __volatile__ ("bkpt 0xab" : : "r" (r0), "r" (r1) : "memory");
24 
25 #elif defined(CONFIG_ARM64)
26 
27 	register unsigned long x0 __asm__("x0") = SYS_WRITEC;
28 	register void *x1 __asm__("x1") = &c;
29 
30 	__asm__ volatile ("hlt 0xf000" : : "r" (x0), "r" (x1) : "memory");
31 
32 #else
33 #error "unsupported CPU type"
34 #endif
35 
36 	return 0;
37 }
38 
semihost_console_init(const struct device * dev)39 static int semihost_console_init(const struct device *dev)
40 {
41 	ARG_UNUSED(dev);
42 
43 	/*
44 	 * The printk output callback is arch_printk_char_out by default and
45 	 * is installed at link time. That makes printk() usable very early.
46 	 *
47 	 * We still need to install the stdout callback manually at run time.
48 	 */
49 	__stdout_hook_install(arch_printk_char_out);
50 
51 	return 0;
52 }
53 
54 SYS_INIT(semihost_console_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
55