The semihosting->stdin_fd is initially in blocking mode. Due to this there is a possibility that the system software blocks waiting for a key-press from the user. This can adversely affect various housekeeping aspects of system software such as the scheduling of the system software tasks/processes/threads.
Specifically, in my case I am booting the Linux kernel on RISCV that routes all console read and write character requests to the openSBI firmware. Since the openSBI firmware blocks waiting for a key-press and openocd is waiting in getchar() the entire Linux kernel scheduling is blocked due to which there are various stalls in the kernel. This patch introduces a new command called semihosting_stdfd that enables us to put any of the standard input/output/error fds into non-blocking mode. After applying this patch and running the semihosting_std command my scheduling and kernel thread stalls were removed and I could get the Linux bash prompt and could successfully run shell commands and observe their outputs in semihosting console. This same command can be extended if anyone wants to add more controls to the semihosting standard file descriptors. Also added documentation for this new command. Signed-off-by: Kautuk Consul <kcon...@ventanamicro.com> --- doc/openocd.texi | 7 ++++ src/target/semihosting_common.c | 58 +++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/doc/openocd.texi b/doc/openocd.texi index 2a8626b80..b0bd976b0 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9579,6 +9579,13 @@ Set the base directory for semihosting I/O, either an absolute path or a path re Use "." for the current directory. @end deffn +@deffn {Command} {arm semihosting_stdfd} ['in'|'out'|'err'] ['blocking'|'nonblocking'] +@cindex ARM semihosting +Set/unset the O_NONBLOCK file status flag in the semihosting->std[in|out|err]_fd file descriptor. This file status +flag affects the appropriate standard file descriptor's blocking/non-blocking status thus affecting the +responsiveness of the semihosting console to inputs/outputs from/to standard input/output/error file descriptors. +@end deffn + @section ARMv4 and ARMv5 Architecture @cindex ARMv4 @cindex ARMv5 diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c index dc0dae2c8..94a4883f0 100644 --- a/src/target/semihosting_common.c +++ b/src/target/semihosting_common.c @@ -2038,6 +2038,57 @@ COMMAND_HANDLER(handle_common_semihosting_basedir_command) return ERROR_OK; } +COMMAND_HANDLER(handle_common_semihosting_stdfd_command) +{ + struct target *target = get_current_target(CMD_CTX); + + if (!target) { + LOG_ERROR("No target selected"); + return ERROR_FAIL; + } + + struct semihosting *semihosting = target->semihosting; + if (!semihosting) { + command_print(CMD, "semihosting not supported for current target"); + return ERROR_FAIL; + } + + if (!semihosting->is_active) { + command_print(CMD, "semihosting not yet enabled for current target"); + return ERROR_FAIL; + } + + int flags; + int fd; + + if (CMD_ARGC < 2 || CMD_ARGC > 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (strcmp(CMD_ARGV[0], "in") == 0) + fd = semihosting->stdin_fd; + else if (strcmp(CMD_ARGV[0], "out") == 0) + fd = semihosting->stdout_fd; + else if (strcmp(CMD_ARGV[0], "err") == 0) + fd = semihosting->stderr_fd; + else + return ERROR_COMMAND_SYNTAX_ERROR; + + if (strcmp(CMD_ARGV[1], "blocking") == 0) { + flags = fcntl(fd, F_GETFL, 0); + flags & O_NONBLOCK ? fcntl(fd, F_SETFL, flags & (~O_NONBLOCK)) : 1; + } else if (strcmp(CMD_ARGV[1], "nonblocking") == 0) { + flags = fcntl(fd, F_GETFL, 0); + flags & O_NONBLOCK ? 1 : fcntl(fd, F_SETFL, flags | O_NONBLOCK); + } else { + return ERROR_COMMAND_SYNTAX_ERROR; + } + + command_print(CMD, "semihosting %s standard fd set to %s", + CMD_ARGV[0], CMD_ARGV[1]); + + return ERROR_OK; +} + const struct command_registration semihosting_common_handlers[] = { { .name = "semihosting", @@ -2088,5 +2139,12 @@ const struct command_registration semihosting_common_handlers[] = { .usage = "[dir]", .help = "set the base directory for semihosting I/O operations", }, + { + .name = "semihosting_stdfd", + .handler = handle_common_semihosting_stdfd_command, + .mode = COMMAND_EXEC, + .usage = "['in'|'out'|'err'] ['blocking'|'nonblocking']", + .help = "control the semihosting->std*_fd file descriptor flags", + }, COMMAND_REGISTRATION_DONE }; -- 2.34.1