diff --git a/semihosting/semihosting.go b/semihosting/semihosting.go new file mode 100644 index 0000000..95257db --- /dev/null +++ b/semihosting/semihosting.go @@ -0,0 +1,47 @@ +// Package semihosting implements parts of the ARM semihosting specification, +// for communicating over a debug connection. +// +// If you want to use it in OpenOCD, you have to enable it first with the +// following command: +// +// arm semihosting enable +package semihosting + +import ( + "device/arm" + "unsafe" +) + +// IOError is returned by I/O operations when they fail. +type IOError struct { + BytesWritten int +} + +func (e *IOError) Error() string { + return "semihosting: I/O error" +} + +// Write writes the given data to the given file descriptor. It returns an +// *IOError if the write was not successful. +func Write(fd uintptr, data []byte) error { + if len(data) == 0 { + return nil + } + params := struct { + fd uintptr + data unsafe.Pointer + len int + }{ + fd: fd, + data: unsafe.Pointer(&data[0]), + len: len(data), + } + unwritten := arm.SemihostingCall(arm.SemihostingWrite, uintptr(unsafe.Pointer(¶ms))) + if unwritten != 0 { + // Error: unwritten is the number of bytes not written. + return &IOError{ + BytesWritten: len(data) - unwritten, + } + } + return nil +} diff --git a/semihosting/stdio.go b/semihosting/stdio.go new file mode 100644 index 0000000..247d78b --- /dev/null +++ b/semihosting/stdio.go @@ -0,0 +1,20 @@ +package semihosting + +// These three file descriptors are connected to the host stdin/stdout/stderr, +// and can be used for logging. +var ( + Stdin = File{fd: 0} + Stdout = File{fd: 1} + Stderr = File{fd: 2} +) + +// File represents a semihosting file descriptor. +type File struct { + fd uintptr +} + +// Write writes the given data buffer to the file descriptor, returning an error +// if the write could not complete successfully. +func (f *File) Write(buf []byte) error { + return Write(f.fd, buf) +}