GPIO in C weirdness with fseek/fwrite

I’m having some weirdness that I don’t quite understand. I’m trying to just toggle a GPIO pin (GPIO30) on and off using C and just the file subsystem. Everything seems to work if there is a delay between the fseek and the fwrite. See this pastebin for the relevant code http://pastebin.com/Ftvv0nvE. As it is, it works. If you uncomment the code, instead of creating a square wave on the oscilloscope, it just creates pulse spikes (i.e. short on times). Can someone explain what is happening? I’m working off a stock BeagleBone Black, no updates (I wanted to make sure the code worked on all versions, as people would be getting their BBB and trying it directly).

Paul Tan.
http://exadler.blogspot.com
http://exadler.com

Hi Paul

If you don't object to using a library there is libsoc[1] which is made for this exact purpose. If nothing else, you could see if the same behavior is observed using it?

https://github.com/jackmitch/libsoc

Cheers,
Jack.

Thanks, I’ll try to see if there is a difference with libsoc or not. However, I did manage to get it working with low level unix i/o (open, write) instead of the buffered stream i/o (fopen, fwrite). It works correctly, I didn’t need a seek operation, and I was able to get pulse widths down to 10uS reliably. Interesting difference though: fwrite to “/sys/class/gpio/export” succeeds even if GPIO30 was already exported, but write to “/sys/class/gpio/export” fails if GPIO30 was already exported.

In case anyone’s wondering why I’m trying to get really short pulses, I’m trying to connect an iGaging DRO slides to a BeagleBone Black (yeah, I’m trying to CNC my lathe using a DRO closed loop servo with my Dual Motor Controller Capes). Scoping out my iGaging DRO, I found that the builtin controller uses 24uS pulses with a 128uS duty cycle. I’m working off of Yuriy’s work on the Arduino (http://www.yuriystoys.com/p/android-dro.html), but trying it on the BeagleBone.

Paul Tan.
http://exadler.com
http://exadler.blogspot.com

Hi Jack,

Sorry, I meant to say Hi Paui,

For fairly short duration pulses like that, you may want to consider
using the PRU to handle generating the pulses. It looks like the stuff
you're working from is already divided between the UI (handled by Linux)
and the low-level comms (handled by an Arduino). Basically, you can
migrate the Arduino stuff to the PRU and probably have less overall hassle.

I have some example code for step/dir pulses and PWM using the PRU
driving GPIO pins as part of LinuxCNC. I also have some timing details
on PRU read and write latency when talking to the GPIO registers:

https://github.com/cdsteinkuehler/linuxcnc/blob/MachineKit-ubc/src/hal/drivers/hal_pru_generic/pru_generic.p#L135

I might be wrong but I think doing fseek() on a GPIO “device” isn’t quite correct.

A GPIO device is more like a char device not a block device were you can actually seek it. So you are only limited to write 1 or 0, the delay in between is set by you plus all the variance that a common not-RT OS adds to it. We know that these are exposed on /sys fs and not on /dev where you can actually see if you are dealing with a char or block device.

For a more precise bit banging PRUSS is the way to do it IMHO.

I did the fseek because it didn’t work without the fseek, and I agree that it doesn’t make sense to fseek a psuedo device. You might be right in that the fseek was just adding delays or doing an fflush of the buffers. (The other reason was that I found examples on the Internet using fseek)

When I converted over to unix io, I no longer needed the seeks.

I just wanted to get this working quickly and will probably convert over to using the PRU later.

Thanks for the input.

Thanks for feedback. I didn’t realize that linuxcnc was using the PRU.

I will look into that code.

Here are some links to start:

http://blog.boxysean.com/2012/08/12/first-steps-with-the-beaglebone-pru/

http://www.element14.com/community/community/knode/single-board_computers/next-gen_beaglebone/blog/2013/05/22/bbb--working-with-the-pru-icssprussv2

You can always read/write to the gpio registers using mmap. This gets a somewhat unsteady 4MHz on-off-on-… toggle even with slow python.

Hello Charles, Paul, Dave, Jack, ect.

I’m also looking to make use of this style DRO with a BBB. I didn’t know the LinuxCNC BBB used the PRU, very cool. I’m going to start looking over that code in more detail.

I agree that the PRU is the way to go, and I tend to think a good approach is to write a fairly simple time stamping program that simply keeps a running list of pulses with time stamp, then the main processor decodes based on time stamps. If such a program existed, I could see it being used for a great many applications, not just the DRO. Does anyone know if there is PRU code that does time stamping of IO pulses?

Hi,

Hello Charles, Paul, Dave, Jack, ect.

I’m also looking to make use of this style DRO with a BBB. I didn’t know the LinuxCNC BBB used the PRU, very cool. I’m going to start looking over that code in more detail.

I agree that the PRU is the way to go, and I tend to think a good approach is to write a fairly simple time stamping program that simply keeps a running list of pulses with time stamp, then the main processor decodes based on time stamps. If such a program existed, I could see it being used for a great many applications, not just the DRO. Does anyone know if there is PRU code that does time stamping of IO pulses?

I wrote a generic gpio input driver I called gpio-event which timestamps gpio input events and delivers them to a userspace program. So while its not PRU based, if you’re going to write a PRU based one, you may want to look at what was done for ideas.

You can find the source code over here:
https://github.com/dhylands/projects/tree/master/linux/gpio-event

It consists of a kernel module, and a sample app that uses it.

I originally wrote it for the gumstix, but its should be generic linux driver stuff and should work fine on the beagleboard. It’s been a while since I’ve built it myself, so I’m not sure it builds on the newest kernels, but I’d be happy to help out getting it to build if you run into any problems.

There is some documentation, along with a high-level overview of the various functions over here:
http://wiki.gumstix.org/index.php?title=GPIO_Event_Driver

Hello Dave,

Thanks for the link / reference, I’m studying it now.