0

I like to sample a signal which is generated by the pins of my Raspberry Pi. I made the experience that high sample rates are difficult to realize.

First I done a fast approach with Python(super slow). Then I changed to ANSI C + the bcm2835.h lib. I gained significant performance gains.

Now I am asking my self the question: How to do the best sampling under Linux?

My tries were undertaken in user space. But what is about, switching to kernel space? I can write a simple character device kernel module. In this module the pins are periodically checked. If the state changed some information is put into a buffer. This i/o buffer is polled by a synchronous file read for a application in user space. The best solution for me would be, if the pin checking can be done with a fixed frequency(sample period should be constant for signal processing).

The set up for this could be:

@kernel: character module + kernel thread + gpio device tree interface + DSP at constant sampling time

@user space: i/o app reading synchronous from character module

Ideas/tips?

Stefan Jaritz
  • 1,999
  • 7
  • 36
  • 60
  • 1
    Doing it in kernel would be an advantage if you could use some kind of interrupt when the GPIO changes. If you are to write a kernel-mode thread, then you are proably better with a real-time thread in user-space. – rodrigo May 27 '17 at 21:30
  • 1
    If you would like to do this in user space, you need to be sure you have recent kernel and installed `libgpiod`. – 0andriy May 27 '17 at 23:00
  • The libgpiod is using the "gpio.h" kernel interface. The character module is reading form the pins like a file. ppoll + timeout is used to validate if a change happened. The lib bcm2845 is using a memory map to access the GPIO registers. I think is the fastest way because the mmu only translates the logical address to the physical one. Using the mmap is avoiding the device layer when checking the pins. What is about the combination mmap + thread that read cyclic a part of the memory? – Stefan Jaritz May 28 '17 at 10:16
  • @StefanJaritz in case you would like to shoot the feet, you may find easier ways to do that instead of racingly poke some addresses in MMIO space. – 0andriy May 29 '17 at 20:58
  • @0andriy this is true. In my case I have some custom hw attached to the pins. Think there is no need to use an extra interface for accessing the pins. As far as I have seen 'kernel/gpio.h' seems to be a good compromise for reading the pins. What is with the periodically check on them? What is the better choice: A Kernel Thread or a thread in userspace? – Stefan Jaritz May 30 '17 at 17:42
  • I can't answer to this. It's solely your choice. – 0andriy May 30 '17 at 17:44

1 Answers1

2

I have a solution for you.

I have written such a module:

https://github.com/Appyx/gpio-reflect

You can synchronously read any signal from the GPIO pins.

You can use the output and calculate the signal with your sampling rate. Just divide the periods.

Appyx
  • 1,145
  • 1
  • 12
  • 21
  • This code is detecting the change of a pin. This is event based. The question I was asking is about to sample a pin(s) on a constant timebase (p.e. read pin 1,56 and 96 every 100ms). Although connecting the pin (file souce) with an interrupt seems to be a state-of-the-art solution. @Appyx solution is based on http://derekmolloy.ie/kernel-gpio-programming-buttons-and-leds/ – Stefan Jaritz Jun 19 '17 at 08:10
  • 1
    ya i know, but you can take the sending example and just replace the gpio function. The best solution would be a constant sampling with a hr_timer and then writing the values to the read buffer. – Appyx Jun 19 '17 at 09:13
  • What's better - using a hrtimer instead of a kernel thread to periodically read/write a pin? A good hrtimer example could be found here: https://gist.github.com/maggocnx/5946907 – Stefan Jaritz Jun 19 '17 at 13:52
  • A hrtimer is better because with a thread you get a polling solution. With the timer you have a very precise timing while still having the event-based approach. – Appyx Jun 19 '17 at 13:57