1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2024 Andes Technology Corporation
4 */
5
6 #include <compiler.h>
7 #include <console.h>
8 #include <drivers/semihosting_console.h>
9 #include <drivers/serial.h>
10 #include <kernel/semihosting.h>
11 #include <util.h>
12
13 /*
14 * struct semihosting_console_data - Structure for semihosting console driver
15 * @chip - General structure for each serial chip
16 * @fd - Handle of the file at @file_path when semihosting_console_init() is
17 * called, or -1 if using the semihosting console
18 */
19 struct semihosting_console_data {
20 struct serial_chip chip;
21 int fd;
22 };
23
24 static struct semihosting_console_data sh_console_data __nex_bss;
25
semihosting_console_putc(struct serial_chip * chip __unused,int ch)26 static void semihosting_console_putc(struct serial_chip *chip __unused, int ch)
27 {
28 semihosting_sys_writec(ch);
29 }
30
semihosting_console_getchar(struct serial_chip * chip __unused)31 static int semihosting_console_getchar(struct serial_chip *chip __unused)
32 {
33 return semihosting_sys_readc();
34 }
35
36 static const struct serial_ops semihosting_console_ops = {
37 .putc = semihosting_console_putc,
38 .getchar = semihosting_console_getchar,
39 };
40 DECLARE_KEEP_PAGER(semihosting_console_ops);
41
semihosting_console_fd_putc(struct serial_chip * chip __unused,int ch)42 static void semihosting_console_fd_putc(struct serial_chip *chip __unused,
43 int ch)
44 {
45 if (sh_console_data.fd >= 0)
46 semihosting_write(sh_console_data.fd, &ch, 1);
47 }
48
49 static const struct serial_ops semihosting_console_fd_ops = {
50 .putc = semihosting_console_fd_putc,
51 };
52 DECLARE_KEEP_PAGER(semihosting_console_fd_ops);
53
semihosting_console_init(const char * file_path)54 void semihosting_console_init(const char *file_path)
55 {
56 if (file_path) {
57 /* Output log to given file on the semihosting host system. */
58 sh_console_data.chip.ops = &semihosting_console_fd_ops;
59 sh_console_data.fd =
60 semihosting_open(file_path, O_RDWR | O_CREAT | O_TRUNC);
61 } else {
62 /* Output log to semihosting host debug console. */
63 sh_console_data.chip.ops = &semihosting_console_ops;
64 sh_console_data.fd = -1;
65 }
66
67 register_serial_console(&sh_console_data.chip);
68 }
69