Commit graph

5 commits

Author SHA1 Message Date
Sean Anderson
fb84517d52 serial: smh: Fake tstc
ARM semihosting provides no provisions for determining if there is
pending input. The only way to determine if there is console input is to
do a read (and block until the user types something). For this reason,
we always return true for tstc (since you will always get input if you
try). However, this behavior can cause problems for code which expects
tstc to eventually be empty. In query_console_serial, there is the
following construct:

	/* empty input buffer */
	while (tstc())
		getchar();

with the current implementation, this effectively turns into an infinite
loop. To avoid this, fake tstc by returning false half of the time. This
is generally OK because the other common construct looks like

	do {
		if (tstc())
			process(getchar());
	} while (!timeout());

so it's fine if we only read a new character every other loop. This will
break things like CYGACC_COMM_IF_GETC_TIMEOUT, but that could be
reworked to test on the timeout instead of calling tstc again (and
ymodem over semihosted serial is not that useful in the first place).

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
2022-06-06 18:01:21 -04:00
Sean Anderson
bfae2744dd serial: smh: Check return value of strndup
strndup can fail. Check for it.

Fixes: 4855b39be ("serial: smh: Implement puts for DM")
Signed-off-by: Sean Anderson <sean.anderson@seco.com>
2022-05-05 15:06:02 -04:00
Sean Anderson
34855b39be serial: smh: Implement puts for DM
This adds an implementation of puts for DM. The implementation is not as
clean as for the non-DM puts because we have to handle non-nul-terminated
string. We also handle short writes (though these are probably very
unusual).

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
2022-04-14 15:39:15 -04:00
Sean Anderson
2332590c48 serial: smh: Initialize serial only if semihosting is enabled
If semihosting is disabled, then the user has no debugger attached, and
will not see any messages. Don't create a serial device in this
instance, to (hopefully) fall back on another working serial device.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
2022-04-01 16:56:53 -04:00
Sean Anderson
74d11d37e2 serial: Add semihosting driver
This adds a serial driver which uses semihosting calls to read and write
to the host's console. For convenience, if CONFIG_DM_SERIAL is enabled,
we will instantiate a serial driver. This allows users to enable this
driver (which has no physical device) without modifying their device
trees or board files. We also implement a non-DM driver for SPL, or for
much faster output in U-Boot proper.

There are three ways to print to the console:

Method              Baud
================== =====
smh_putc in a loop   170
smh_puts            1600
smh_write with :tt 20000
================== =====

These speeds were measured using a 175 character message with a J-Link
adapter. For reference, U-Boot typically prints around 2700 characters
during boot on this board. There are two major factors affecting the
speed of these functions. First, each breakpoint incurs a delay. Second,
each debugger memory transaction incurs a delay. smh_putc has a
breakpoint and memory transaction for every character. smh_puts has one
breakpoint, but still has to use a transaction for every character. This
is because we don't know the length up front, so OpenOCD has to check if
each character is nul. smh_write has only one breakpoint and one memory
transfer.

DM serial drivers can only implement a putc interface, so we are stuck
with the slowest API. Non-DM drivers can implement puts, which is vastly
more efficient. When the driver starts up, we try to open :tt. Since
this is an extension, this may fail. If it does, we fall back to
smh_puts. We don't check :semihosting-features, since there are
nonconforming implementations (OpenOCD) which don't implement it (but
*do* implement :tt).

Some semihosting implementations (QEMU) don't handle READC properly. To
work around this, we try to use open/read (much like for stdin) if
possible.

There is no non-blocking I/O available, so we don't implement pending.
This will cause __serial_tstc to always return true. If
CONFIG_SERIAL_RX_BUFFER is enabled, _serial_tstc will try and read
characters forever. To avoid this, we depend on this config being
disabled.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
2022-04-01 15:03:13 -04:00