Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lirc_rpi is sensitive to interrupt latency #906

Closed
P33M opened this issue Mar 23, 2015 · 23 comments
Closed

lirc_rpi is sensitive to interrupt latency #906

P33M opened this issue Mar 23, 2015 · 23 comments

Comments

@P33M
Copy link
Contributor

P33M commented Mar 23, 2015

With high network traffic or an IRQ latency fuzzer, lirc_rpi starts to generate errors in the decoded stream. The root cause is that IRQ latency between the edge-triggered GPIO interrupt going off and being able to read the timestamp at which it occurred causes incorrect decoding.

The minimum pulse width that needs to be correctly recorded is 562.5uS (NEC protocol "0" bit). Sony SIRC has a slightly longer duration at 600uS. RC-5 and RC-6 are slower.

There is no scope for moving GPIO interrupts to the FIQ pin. The ARMCTRL routing only allows for a single interrupt to be wired up to the FIQ pin at any one time.

The proposed solution is to move to a polled method. On Pi 1, the FIQ is triggered reliably from a 8kHz source clock (USB start-of-frame, which is almost never masked) giving 125uS sample points. This is sufficient resolution to decode GPIO edges into mark-space bitstreams from an IR receiver. On Pi 2, the option exists to use an (as yet undocumented) local timer to trigger a FIQ on a completely independent core in the same fashion.

The Pi 1 solution makes IR decoding dependent on the use of the USB FIQ, but nearly everyone uses that anyway so the dependency should be minimal.

In either case, the polling routine would read the GPIO level register for the pin(s) in question and do a delta comparison. If a delta is found, it would then read the system time counter (STC, monotonic increase at 1uS intervals) and write both the value and the delta to a ring-buffer-like interface and then stimulate an interrupt. On Pi 1, a DMA engine with a dummy read transfer can be used to provoke an interrupt. On Pi 2, the local mailboxes can be used.

The Pi 2 solution would be a lot more robust and include other use cases such as logic analysis with reasonable (kHz) sampling rates.

@P33M
Copy link
Contributor Author

P33M commented Apr 13, 2015

BCM2836 ARM-local peripherals are now documented (which includes the independent "USB timer"):
https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2835/README.md

@Ruffio
Copy link

Ruffio commented Aug 14, 2016

@P33M has your issue been resolved? If yes, then please close this issue.

@mattgrogan
Copy link

What's the status on this? I'm having a similar issue.

@julianscheel
Copy link
Contributor

I'd also be interested in the USB FIQ based approach on RPi1. @P33M have you ever done some coding on this?

@julianscheel
Copy link
Contributor

@P33M I just had a quick look at it. When you say the USB FIQ shall be used, I'm a bit unsure how to that. I don't think multiple interrupt handlers can be bound to the fiq and obviously dwc_otg is already claiming the fiq, so it would have to relinquish it while lirc_rpi would be using it. How would you intend to do it?

@P33M
Copy link
Contributor Author

P33M commented Jan 4, 2017

My original idea was to cheat.
Using the USB's start-of-frame interrupt, you get a guaranteed interrupt every 125uS which could be used to perform other tasks, like sample GPIOs 0-26 and stuff the result in a ring buffer. This would allow for software decode of received IR codes. The LIRC driver would then become an odd platform device registered by the USB driver (bad).

My subsequent idea, possible on Pi2/3, was to use the new "magic" oscillator-driven timer that is muxed into the FIQ/IRQ line and accomplish the same result, but with the added bonus that IR would still work in device mode with USB disconnected.

With the subsequent release of the Zero, there's no guarantee of a USB SOF interrupt source (port disconnected or in device mode) and the "magic" timer doesn't exist. As such, back to the drawing board methinks.

@P33M P33M closed this as completed Jan 4, 2017
@julianscheel
Copy link
Contributor

@P33M I see, that would indeed by hackish...
I am actually looking for something usable on a Raspberry Pi 1, as we have quite a lot of them in the wild and IR detection rate is quite bad, while video is decoded.

Why did you close the issue? It actually still exists :)

@P33M
Copy link
Contributor Author

P33M commented Jan 4, 2017

I opened the issue with a proposed workaround - but the workaround won't be of any benefit if you're on a bcm2835 product.

The same problem also exists with Dallas 1-wire, WS2812 "smart" LEDs, DHTnn-type sensors, or anything that waggles a GPIO in a time-sensitive fashion. It's an endemic problem until we work out a way of getting microsecond-accurate GPIO sampling.

One avenue of investigation would be to use the SMI peripheral as a 1-bit logic analyser - something I need to remember to poke Luke about, since he got it working last year or so.

@julianscheel
Copy link
Contributor

@P33M Maybe open a new bug without the proposed solution, to not forget about this issue? :)
@Wren6991 any cosiderations about using SMI for this? It seems there is no public documentation for the SMI.

@Wren6991
Copy link
Contributor

Wren6991 commented May 24, 2017

It sounds fairly doable. SMI can sample bus widths as small as 8 bits, and by futzing with the clock sources it should be possible to go as slow as a 125us sample period. The timing is very deterministic; you set up the timing parameters, and the peripheral follows them. There's a decent-sized fifo (hundreds of bytes IIRC) to take up the slack, so at modest data rates it's quite easy for a DMA channel to keep the SMI spinning at a constant rate.

The documentation is still in the state of "the code is the documentation" unfortunately. The header file contains about as much information as I could squeeze in without actually copying and pasting from proprietary docs. The SMI NAND driver is a pretty clean example of registering an SMI client driver and pushing some data through it.

You could certainly make the hardware do your bidding by doing something like

  • Initiate a 2^32 byte transaction on SMI
  • Have a loop of 2 (or more) DMA SCBs which copy to a pair of buffers, a few kilobytes each, and interrupt for each copy completion
  • In the interrupt, scan through the buffer for anything that looks like LIRC traffic

Which would reduce the interrupt frequency by a factor of thousands. However, this wouldn't fit well on top of the existing SMI driver. The code already does most of these things, it should be possible to take the necessary parts from that driver.

@P33M
Copy link
Contributor Author

P33M commented May 24, 2017

Bonus feature request:

The SMI peripheral drives all its data bus pins as input or output depending on which sort of cycle is being performed - read=input, write=output. If you could use the runtime pinmux reconfiguration API to selectively mask pins that are not being actively used in the current transfer as inputs with a default pull state, you could connect arbitrary numbers of devices (n<=16) with arbitrary 1-wire communication protocols to the SMI pins.

I'm thinking of a use case where an IR receiver coexists happily with DHT22/1-wire device/whatever connected to separate data pins on the SMI bus - with data cycles implemented via a transfer queue that sets both the pinmux and timing on a per-transaction basis. It's an extension of the notional addressing that SMI already has, but for dumb devices that would otherwise require costly bitbashing.

@Wren6991
Copy link
Contributor

Wren6991 commented May 24, 2017

That's a great idea! Bagsy /dev/multiwire.

Only problem I see is that we are waiting for asynchronous events on some of these lines (e.g. LIRC) and we lose the ability to capture that when we are outputting. For the more common case (master-slave) that would be a great use of the peripheral.

Edit: also a great WS2812 controller

@julianscheel
Copy link
Contributor

@Wren6991 Thanks for the insights. Unfortunately, I'm not having enough spare time right now to take care of it, nor do we have a commercial need right now (we got rid of the IR receiver in that project). So it might be a while before I would dive into it, except someone else has a major need for it and wants to sponsor the work :)

@euphoria360
Copy link

I'm having the same issue too, and it's actually driving me crazy. The GPIO IR receivers are very popular in OS'es like LibreElec and OSMC which make RPi like a media Hub.
Any update on this?

@yaqwsx
Copy link
Contributor

yaqwsx commented Feb 23, 2018

I have the same issue on OSMC. I use IR receiver connected through GPIO. When there is a large traffic on USB, IR remote becomes unresponsive.

Is there any progress or at least workaround? Are there other possibilities to connect IR receiver to RPi to get around this issue?

@horchi
Copy link

horchi commented Jun 8, 2018

Same here :(

@pelwell
Copy link
Contributor

pelwell commented Jun 8, 2018

lirc_rpi is deprecated now. Have you tried gpio-ir instead? There is some discussion of it on this thread:
https://www.raspberrypi.org/forums/viewtopic.php?t=205490

@euphoria360
Copy link

I wonder why this doesn't get attention. Lot's of RPi buyers use it as Media Center and IR remotes are indistinguishable part of that.

@horchi
Copy link

horchi commented Jun 15, 2018

lirc_rpi is deprecated now. Have you tried gpio-ir instead? There is some discussion of it on this thread:
https://www.raspberrypi.org/forums/viewtopic.php?t=205490

should this make sense in relation tom the interrupt problem?
I tested gpio-ir right now but now change. Still the problem that every time I start using the signal of an DVB-S2 USB stick gpio lirc stop working.

@pelwell
Copy link
Contributor

pelwell commented Jun 15, 2018

The point is that you have zero chance of getting LIRC improvements, whereas a request for an optimised gpio-ir has at least a slim chance of getting some attention provided you create a new issue for it.

@HiassofT
Copy link
Contributor

HiassofT commented Jun 15, 2018

Getting rid of the interrupt latency is very tricky. As a lot of USB DVB receivers have an integrated IR receiver there's an easy workaround though, just that IR receiver instead of a GPIO IR receiver.

@horchi
Copy link

horchi commented Jun 15, 2018

yes my USB DVB receivers have an integrated IR too but I don't like to use it because it is not in the visible IR range since it looks ugly with all the wires ;)
In meantime I bought a FLIRC, but since it simulate 'only' a keyboard I can control the VDR with it, but not control additional script like irexec can do.
Not easy this days ;)

@HiassofT
Copy link
Contributor

Another option is to buy an MCE USB receiver, like the HP branded ones which you can get on ebay for 10-15 USD/EUR. They are very well supported in linux.

herrnst pushed a commit to herrnst/linux-raspberrypi that referenced this issue Jan 2, 2023
[ Upstream commit 529409e ]

When equivalent completed state is found and it has additional precision
restrictions, BPF verifier propagates precision to
currently-being-verified state chain (i.e., including parent states) so
that if some of the states in the chain are not yet completed, necessary
precision restrictions are enforced.

Unfortunately, right now this happens only for the last frame (deepest
active subprogram's frame), not all the frames. This can lead to
incorrect matching of states due to missing precision marker. Currently
this doesn't seem possible as BPF verifier forces everything to precise
when validated BPF program has any subprograms. But with the next patch
lifting this restriction, this becomes problematic.

In fact, without this fix, we'll start getting failure in one of the
existing test_verifier test cases:

  raspberrypi#906/p precise: cross frame pruning FAIL
  Unexpected success to load!
  verification time 48 usec
  stack depth 0+0
  processed 26 insns (limit 1000000) max_states_per_insn 3 total_states 17 peak_states 17 mark_read 8

This patch adds precision propagation across all frames.

Fixes: a3ce685 ("bpf: fix precision tracking")
Signed-off-by: Andrii Nakryiko <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Alexei Starovoitov <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
popcornmix pushed a commit that referenced this issue Jan 3, 2023
[ Upstream commit 529409e ]

When equivalent completed state is found and it has additional precision
restrictions, BPF verifier propagates precision to
currently-being-verified state chain (i.e., including parent states) so
that if some of the states in the chain are not yet completed, necessary
precision restrictions are enforced.

Unfortunately, right now this happens only for the last frame (deepest
active subprogram's frame), not all the frames. This can lead to
incorrect matching of states due to missing precision marker. Currently
this doesn't seem possible as BPF verifier forces everything to precise
when validated BPF program has any subprograms. But with the next patch
lifting this restriction, this becomes problematic.

In fact, without this fix, we'll start getting failure in one of the
existing test_verifier test cases:

  #906/p precise: cross frame pruning FAIL
  Unexpected success to load!
  verification time 48 usec
  stack depth 0+0
  processed 26 insns (limit 1000000) max_states_per_insn 3 total_states 17 peak_states 17 mark_read 8

This patch adds precision propagation across all frames.

Fixes: a3ce685 ("bpf: fix precision tracking")
Signed-off-by: Andrii Nakryiko <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Alexei Starovoitov <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
popcornmix pushed a commit that referenced this issue Jan 13, 2023
[ Upstream commit 529409e ]

When equivalent completed state is found and it has additional precision
restrictions, BPF verifier propagates precision to
currently-being-verified state chain (i.e., including parent states) so
that if some of the states in the chain are not yet completed, necessary
precision restrictions are enforced.

Unfortunately, right now this happens only for the last frame (deepest
active subprogram's frame), not all the frames. This can lead to
incorrect matching of states due to missing precision marker. Currently
this doesn't seem possible as BPF verifier forces everything to precise
when validated BPF program has any subprograms. But with the next patch
lifting this restriction, this becomes problematic.

In fact, without this fix, we'll start getting failure in one of the
existing test_verifier test cases:

  #906/p precise: cross frame pruning FAIL
  Unexpected success to load!
  verification time 48 usec
  stack depth 0+0
  processed 26 insns (limit 1000000) max_states_per_insn 3 total_states 17 peak_states 17 mark_read 8

This patch adds precision propagation across all frames.

Fixes: a3ce685 ("bpf: fix precision tracking")
Signed-off-by: Andrii Nakryiko <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Alexei Starovoitov <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants