0

I need to have precise timing on a multicore machine (Allwinner A20 processor) for home automation applications

  • using bit banging lirc (infrared remote simulation) to control some hifi and tv equipment
  • using RF-OOK to control some RF controlled plugs or TV/Projector screens, maybe more in the future

The problem:

  • The available kernel is only legacy (3.4.1xx or so), which uses BogoMIPS to control udelay()
  • The machine has two processors. "cat /proc/cpuinfo" shows 1914.96 BogoMIPS on the first processor and 1664.12 BogoMIPS on the second one
  • The timing and configuration files for LIRC always seemed to be extremely fiddly and IR receivers did not work well. After revisiting, I noticed (years later) that udelay seems to be using the 1664.12 BogoMIPS as a base programmatically, but it actually uses the 1914.94 BogoMIPS in reality. The timing is always around 15% faster than expected. I am pretty sure that this is because of the different timings of processors.
  • If I try using usleep or usleep_range, I need to get out of atomic context and timing is not working at all, in this case. I would actually like this, as e.g. listening to music experiences some scrambling whenever the lirc bit banging or the OOK is used.

Interestingly, I find in the dmesg: "Calibrating delay loop... 1914.96 BogoMIPS (lpj=3188736)"... So there may be something fishy with the kernel, but I do not know where to look for...

Knowing the problem, of course it can be taken into consideration when specifying the delays, but this seems like a terrible hack...

I have two questions actually

  • Is it possible to use usleep to get precise timing for a kernel module (precise meaning usec precision for immediately repeated delays of around 20 usecs), thus, not having atomic context
  • How can the udelay made more "deterministic" in terms of on which processor it should run while using the correct BogoMIPS constant for that processor

If it helps, kernel modules are here: https://github.com/matzrh/sunxi-lirc and https://github.com/matzrh/rfm12b-linux (the sun7i-spi patch)

  • 2
    Sounds like an XY problem. Use a small separate MCU for such real-time applications and connect via e.g. UART or USB. Linux is not really a good idea for such applications. – too honest for this site Jun 25 '17 at 03:55
  • a quick web search showed that the AllWinner hardware has high resolution timers with nanoseconds resolution that appear to have received kernel support somewhere around 2013. These seem to be accessible through the `nanosleep()` kernel interface. If your kernel is recent enough, you might get away with just replacing the `usleep()` calls with their `nanosleep()` counterparts. – mfro Jun 25 '17 at 08:04
  • 2
    @mfro: That does not guarantee the code will be running precisely at the planned time. There are reasons SoC for control applications integrate a Cortex-M for such tasks. – too honest for this site Jun 25 '17 at 12:52
  • @Olaf: I didn't say it does. The OP complained about the inaccuracy of `udelay()`and I just recommended to use `nanosleep()` with a recent kernel instead to improve that. – mfro Jun 25 '17 at 13:40
  • 1
    @mfro: OP apparently wants a precise timing in the us range. This is not accomplishable with standard kernel. For the hardware he uses even a RT kernel is unlikely to accomplish this timing. His second bullet implies he uses the term "precision" not with regard to the resulution, but guaranteed timeout, which nanosleep will not really change. – too honest for this site Jun 25 '17 at 13:59
  • Baremetal on that processor...maybe...you are still running out of dram most likely so you have timing hits. I agree with Olaf this is clearly a case of use a microcontroller (or cpld) for this task and have the host system talk to that through one of many different interfaces that are supported by the allwinner chips (spi, i2c, uart, etc) and/or you can bit bang with no real need for accuracy (spi, i2c). – old_timer Jun 26 '17 at 02:08
  • or maybe you can use one of these interfaces (spi/i2c) in a non-standard way to encourage the hardware to generate precisely timed pulses. but bit banging on a single threaded full sized arm, baremetal, maybe (need fast/consistent sram), multithreaded on an operating system, unlikely. – old_timer Jun 26 '17 at 02:10
  • Thanks for the hints, so far. It gives me some pointers. I cannot get out of atomic context so easily and use usleep / nansleep etc. The point is here that between two usleep calls and switching the gpio between high and low, timing cannot be controlled (it seems) it not in atomic context. Timing is precise enough +/- 10us, the problem is the proportional error due to the two BogoMIPS values that are confused by the kernel for some reason (or processor assignment just cannot be controlled). I like the idea to use SPI or some SOC functionalities/registers. I will dig into that. – user3117071 Jun 26 '17 at 21:42

0 Answers0