Spurious interrupts from M.2 E-key UART1

Whilst testing some FreeBSD/riscv interrupt controller reworking I noticed that we see crazy numbers of interrupts coming from uart1 (uart0 is fine):

jrtc27@unmatched:~$ vmstat -i | grep ,40\\\|rate
interrupt                                             total       rate
plic0,40:                                         274516098     121558

(and that’s with the device disabled for a while so the average has fallen off; I’ve seen it as high as ~190 kHz)

Given that this is the UART wired to the M.2 E-key slot, which is empty on my board, I’m wondering whether a pull-up has been forgotten on the RX line internally (there isn’t one on the board according to the schematic, and presumably uart0 doesn’t need one since it’s always connected at both ends), so the signal is floating and thus leading to spurious received characters?

On Linux it seems that, whilst the count is 0 in normal use, if I attach to /dev/ttySIF1 with screen then /proc/interrupts does start to show the count going up quite quickly, albeit not quite so absurdly high (still ~2 kHz…). Presumably Linux lazily enables/disables the UART, whereas FreeBSD keeps its UARTs fully working even when not open (and not the console), and maybe it’s also throttling. I guess that explains why it went unnoticed, if my suspicion is indeed correct?

Thanks for reporting this behavior Jessica.

It seems that the Unmatched board has a floating input on the UART1_RX line which may be the source of this interrupt noise.

One option to eliminate the noise would be to insert an M.2 E-key device that drives this signal. Unfortunately I’m not aware of any specific device that does this.

Would you be able to try an experiment to attempt to eliminate this interrupt noise? UART1_RX signal is routed to J8 header pin 13. There is also ground pin on J8 header pin 23 and a UART1_TX signal on J8 pin 11.

  • One option for the experiment would be to connect J8.13 to J8.23 with a hook lead or jumper wire.
  • Another option for the experiment would be to connect UART1_RX to UART1_TX (this assumes UART1_TX isn’t being driven by M.2 E-key device) creating a UART loop back configuration and this connection could be made from J8.11 to J8.13 with a standard 0.1" pitch jumper shunt.

Be careful connecting to J8 to not short any other signals and note there’s also power on this connector. You would probably want to make these experiment connections with the board power off.

Grounding it doesn’t help, presumably because 0 is the start bit for UART communications, not 1 (or an edge). Creating a physical loopback does completely stop all interrupts.

So, indeed, seems there should be a pull-up as I suspected in my original post.

There is also 1.8V on the J8.2 pin that you could connect UART1_RX to for a 1 signal.

That does indeed also work, as one would expect.

I guess this also points out that the SiFive UART neither detects, nor currently has any provision to report (without a trivial extension to ie/ip, though that seems not worth it given the platform specs will be mandating a 16550-compatible UART going forwards), framing errors, since the stop bit will also be being sampled as 0 when left floating or grounded.

Sadly this is not supported, meaning there is no BREAK support either, so no magic SysRq under Linux with either on-chip port including the usual console one. It is a very simple UART.

Does Linux not have a way to configure that? On FreeBSD you can enable (and choose in your kernel config what the default is) using CR ~ ^B/^P/^R to break/panic/reboot as a secondary alternative to a real UART break. I’d expect Linux to have long ago added an equivalent…

I don’t know, I never had a need to figure out. This is the first UART I came across that does not support BREAK, and I’ve been using Linux since before it had magic SysRq support in the first place, let alone for serial ports (I actually implemented the feature in a couple of Linux UART hardware drivers). In any case a real BREAK is safer to use than a random sequence that may potentially legitimately appear in the input stream.

mips_ejtag_fdc and hvc_console seem to have special code to allow ^O in place of BREAK, so I guess if you want something to work for the SiFive UART you could do something similar. I can’t obviously see something at a device-independent layer like exists in FreeBSD; CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE is close, except it has the implicit BREAK prefix that you can’t control. Perhaps someone should extend Linux with this useful feature in FreeBSD. I’ll note that virtio-console also doesn’t send BREAKs (you could extend the spec for the control queue to signal them, but that doesn’t help older implementations), so it’d be useful for people using VMs, too.