User avatar
mbferguson
Posts: 31
Joined: Thu Nov 15, 2018 2:33 pm

Nanosleep in C gives 60us overhead on Raspberry Pi

Wed Dec 05, 2018 11:32 pm

I'm trying to toggle the GPIO pin at a pulse width of 100ns. I have used a singe core by isolating core 2 on my four core Raspberry Pi model 3b, and then running my program on that core with taskset command.

Here's my code:

Image

This was taken from https://elinux.org/RPi_GPIO_Code_Samples which gives an example mapping in C for the GPIO pin manipulation.

I reduced the wait time to a single nanosecond, purely for demonstration purposes. I initially had 100L in place of 1L, where L is simply long since the function nanosleep requires that data type.

This is the oscilloscope output from GPIO pin 7:
Image

How can I get a 100 nanosecond width pulse?

Deleting the nanosleep calls gives around 9ns width, but is triangular likely due to capacitances in the lines.

Image

Is there a dummy function call that only takes a few cycles of the CPU to complete?

User avatar
mbferguson
Posts: 31
Joined: Thu Nov 15, 2018 2:33 pm

Re: Nanosleep in C gives 60us overhead on Raspberry Pi

Wed Dec 05, 2018 11:42 pm

Using the following command gave this:

$ sudo chrt -v -r 99 /usr/bin/taskset -c 2 ./myfile

Image

Only 15us, but still not close to 100ns.

pootle
Posts: 434
Joined: Wed Sep 04, 2013 10:20 am
Location: Staffordshire

Re: Nanosleep in C gives 60us overhead on Raspberry Pi

Thu Dec 06, 2018 12:19 am

Your not going to do this reliably direct from software, anything running in a process is subject to the vagaries of the scheduler and also interrupt processing can stop a process in its tracks for significant periods (if your timing to microsecond level or less).

Without external hardware assist, the best you can probably achieve is to use DMA to drive the gpio pins. You can use pigpio waveforms to do most of the leg work of this and achieve robust reliable timings down to a couple of microseconds.

If you really want a 100ns pulse, best to build a small external circuit to generate the pulse that you can trigger from the pi (as long as you don't want to do this more than around 1/2 milion times a second).

If you're not worried about some pulses going wildly wrong because of interrrupts and the like, then driving pgio direct as you have done is the answer., but do it in assembler with a couple of register manipulating instructions (don't do anythng that accesses memory) to pad it to the right time, might do the trick. Best to write this in assembler to avoid the C compiler 'optimizing' things the wrong way.

W. H. Heydt
Posts: 15840
Joined: Fri Mar 09, 2012 7:36 pm
Location: Vallejo, CA (US)

Re: Nanosleep in C gives 60us overhead on Raspberry Pi

Thu Dec 06, 2018 12:44 am

pootle wrote:
Thu Dec 06, 2018 12:19 am
Your not going to do this reliably direct from software, anything running in a process is subject to the vagaries of the scheduler and also interrupt processing can stop a process in its tracks for significant periods (if your timing to microsecond level or less).
Probably. A monostable multivibrator (aka "one shot") would seem the be the simplest way to do this.

User avatar
mbferguson
Posts: 31
Joined: Thu Nov 15, 2018 2:33 pm

Re: Nanosleep in C gives 60us overhead on Raspberry Pi

Thu Dec 06, 2018 12:54 am

There have been some peeps on here that got very high MHz frequencies, much greater than 5MHz. Is it really necessary to use a vibrator multistablor?

W. H. Heydt
Posts: 15840
Joined: Fri Mar 09, 2012 7:36 pm
Location: Vallejo, CA (US)

Re: Nanosleep in C gives 60us overhead on Raspberry Pi

Thu Dec 06, 2018 1:29 am

mbferguson wrote:
Thu Dec 06, 2018 12:54 am
There have been some peeps on here that got very high MHz frequencies, much greater than 5MHz. Is it really necessary to use a vibrator multistablor?
You could read those threads to find out how they did it. They may not have been targeting a specific pulse width, though.

User avatar
mbferguson
Posts: 31
Joined: Thu Nov 15, 2018 2:33 pm

Re: Nanosleep in C gives 60us overhead on Raspberry Pi

Thu Dec 06, 2018 1:36 am

By deleting the nanosleep calls, and adding in a bunch of if statements that don't do anything, I was able to get pretty close to 100ns.

But the oscilloscope is jumping back and forth between two waves, the 100ns, and 200ns images below.

Image

Image

What could be causing this? Daemon magic? Interrupts? If it's running on its own isolated core, how can I avoid these problems.

rayjoh
Posts: 27
Joined: Thu May 23, 2013 11:48 am

Re: Nanosleep in C gives 60us overhead on Raspberry Pi

Thu Dec 06, 2018 6:21 pm

mbferguson wrote:
Thu Dec 06, 2018 1:36 am
But the oscilloscope is jumping back and forth between two waves, the 100ns, and 200ns images below.
It might be the CPU switching between 600 and 1200Mhz
-- Raymond

User avatar
joan
Posts: 15949
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Nanosleep in C gives 60us overhead on Raspberry Pi

Thu Dec 06, 2018 8:05 pm

Why are you not using one of the GPIO capable of being driven by the hardware clock or one of the GPIO capable of being driven by the hardware PWM? I can't think of a reason for doing this in software.

User avatar
DavidS
Posts: 4583
Joined: Thu Dec 15, 2011 6:39 am
Location: USA

Re: Nanosleep in C gives 60us overhead on Raspberry Pi

Thu Dec 06, 2018 8:10 pm

You have two choices, those being to use the HW PWM to cereate your square wave, or if the HW PWM pins are being used for something else already you can go to baremetal programming, where you can easilly get the accuracy you are looking for.
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers.

fanoush
Posts: 896
Joined: Mon Feb 27, 2012 2:37 pm

Re: Nanosleep in C gives 60us overhead on Raspberry Pi

Thu Dec 06, 2018 11:31 pm

Also you could possibly use existing hardware like SPI, I2S, UART to send 'fake' data to generate what you want? e.g on esp8266 I2S was (ab)used to generate tv-out signal.

User avatar
HermannSW
Posts: 5183
Joined: Fri Jul 22, 2016 9:09 pm
Location: Eberbach, Germany

Re: Nanosleep in C gives 60us overhead on Raspberry Pi

Tue Dec 11, 2018 6:41 pm

Why doing that in software?

I used "gpio"/"pigs" tool commands to setup PWM in this thread to get 4.8MHz, 50MHz and even 125MHz cleanly on Pi Zero:
viewtopic.php?t=157907#p1087893
Image


P.S:
I just recently did a laser clock with Arduino Due at 10µs resolution using this simple script, calling "micros()" and doing no delay allowed for >300,000 updates/second, and that with a CPU clock of "only" 84MHz:
https://forum.arduino.cc/index.php?topi ... msg3974683

Code: Select all

...
  for(;;) {
    delay(0);
    i=(micros()/10)%10;
    digitalWrite( 9 + i%5, i/5 );
  }
...
Since you lock your program to a single core, why not use 100% of CPU time and doing the same on PI?
With 1200MHz CPU clock and "clock_gettime(CLOCK_REALTIME, &time1)" giving you timestamps at ns resolution you should get your 100ns width (it is only 5MHz).

This is "slowed down" laser clock at 1ms resolution, video taken with with Raspberry v2 camera at 1007fps:
Image
https://hermann-sw.github.io/planar_graph_playground
https://stamm-wilbrandt.de/en#raspcatbt
https://github.com/Hermann-SW/memrun
https://github.com/Hermann-SW/Raspberry_v1_camera_global_external_shutter
https://stamm-wilbrandt.de/en/Raspberry_camera.html

Return to “General discussion”