aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Fertser2013-04-15 21:42:46 +0400
committerGareth McMullin2013-05-18 15:33:58 +1200
commitdf32aad757935c8953c844ffaa455fa940b4b405 (patch)
treeb1e201e8a2b979c98c127f2a51f87932dc817c35
parent5020d1f05db920cd0633982016c0b1978a310d20 (diff)
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 <fercerpav@gmail.com>
-rw-r--r--README18
-rw-r--r--src/cortexm.c40
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 <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -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;