From df32aad757935c8953c844ffaa455fa940b4b405 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Mon, 15 Apr 2013 21:42:46 +0400 Subject: [PATCH] semihosting: improve handling of console I/O This implements special handling for SYS_OPEN to catch requests for ":tt" which is reserved by ARM for console input/output. They're mapped to the appropriate GDB file descriptors automatically. An additional file handle offset is introduced because ARM doesn't consider zero handle to be valid. Signed-off-by: Paul Fertser --- README | 18 +++++++++++------- src/cortexm.c | 40 +++++++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/README b/README index b47e22b..9c10013 100644 --- a/README +++ b/README @@ -47,15 +47,19 @@ RAM. Semihosting support =================== -Basic armv6m/armv7m semihosting is supported, i.e. you can build your -application in a special way to use host's stdin and stdout right -inside gdb simply by calling printf(), scanf() and other input-output -functions. To make use of it, add --specs=rdimon.specs and -lrdimon to +Standard ARMv6-M/ARMv7-M semihosting is supported, i.e. you can build +your application in a special way to have calls to certain functions +(open(), close(), read(), write(), lseek(), rename(), unlink(), +stat(), isatty(), system()) executed on the debugging host itself. To +make use of these facilities, add --specs=rdimon.specs and -lrdimon to the linker flags for your firmware. -All writes are treated as writes to the stdout, all reads are done -from stdin; SYS_ISTTY always returns true, SYS_ERRNO -- EINTR; -SYS_OPEN and SYS_FLEN return dummy non-zero values. +If you're going to use stdin, stdout or stderr (e.g. via +printf()/scanf()) and you're not using newlib's crt0 (by specifying +-nostartfiles), you need to add this to your initialisation: + +void initialise_monitor_handles(void); +initialise_monitor_handles(); Project layout ============== diff --git a/src/cortexm.c b/src/cortexm.c index 179fb36..130f683 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -28,6 +28,7 @@ * Issues: * There are way too many magic numbers used here. */ +#include #include #include #include @@ -949,41 +950,60 @@ static int cortexm_hostio_request(target *t) FILEIO_O_WRONLY | FILEIO_O_CREAT | FILEIO_O_APPEND,/*a*/ FILEIO_O_RDWR | FILEIO_O_CREAT | FILEIO_O_APPEND,/*a+*/ }; + uint32_t pflag = flags[params[1] >> 1]; + char filename[4]; + + target_mem_read_bytes(t, filename, params[0], sizeof(filename)); + /* handle requests for console i/o */ + if (!strcmp(filename, ":tt")) { + if (pflag == FILEIO_O_RDONLY) + arm_regs[0] = STDIN_FILENO; + else if (pflag & FILEIO_O_TRUNC) + arm_regs[0] = STDOUT_FILENO; + else + arm_regs[0] = STDERR_FILENO; + arm_regs[0]++; + target_regs_write(t, arm_regs); + return 1; + } + gdb_putpacket_f("Fopen,%08X/%X,%08X,%08X", params[0], params[2] + 1, - flags[params[1] >> 1], 0644); + pflag, 0644); break; } case SYS_CLOSE: /* close */ - gdb_putpacket_f("Fclose,%08X", params[0]); + gdb_putpacket_f("Fclose,%08X", params[0] - 1); break; case SYS_READ: /* read */ priv->byte_count = params[2]; gdb_putpacket_f("Fread,%08X,%08X,%08X", - params[0], params[1], params[2]); + params[0] - 1, params[1], params[2]); break; case SYS_WRITE: /* write */ priv->byte_count = params[2]; gdb_putpacket_f("Fwrite,%08X,%08X,%08X", - params[0], params[1], params[2]); + params[0] - 1, params[1], params[2]); break; case SYS_ISTTY: /* isatty */ - gdb_putpacket_f("Fisatty,%08X", params[0]); + gdb_putpacket_f("Fisatty,%08X", params[0] - 1); break; case SYS_SEEK: /* lseek */ gdb_putpacket_f("Flseek,%08X,%08X,%08X", - params[0], params[1], FILEIO_SEEK_SET); + params[0] - 1, params[1], FILEIO_SEEK_SET); break; case SYS_RENAME:/* rename */ gdb_putpacket_f("Frename,%08X/%X,%08X/%X", - params[0], params[1] + 1, + params[0] - 1, params[1] + 1, params[2], params[3] + 1); break; case SYS_REMOVE:/* unlink */ - gdb_putpacket_f("Funlink,%08X/%X", params[0], params[1] + 1); + gdb_putpacket_f("Funlink,%08X/%X", params[0] - 1, + params[1] + 1); break; case SYS_SYSTEM:/* system */ - gdb_putpacket_f("Fsystem,%08X/%X", params[0], params[1] + 1); + gdb_putpacket_f("Fsystem,%08X/%X", params[0] - 1, + params[1] + 1); break; case SYS_FLEN: /* Not supported, fake success */ @@ -1015,6 +1035,8 @@ static void cortexm_hostio_reply(target *t, int32_t retcode, uint32_t errcode) if (((priv->syscall == SYS_READ) || (priv->syscall == SYS_WRITE)) && (retcode > 0)) retcode = priv->byte_count - retcode; + if ((priv->syscall == SYS_OPEN) && (retcode != -1)) + retcode++; arm_regs[0] = retcode; target_regs_write(t, arm_regs); priv->errno = errcode;