As part of my latest project, I’ve been trying to come to terms with how the GPIO’s (General Purpose Input / Output) on the Galileo work, there are several ways to program the Galileo I/O’s, mainly: GPO, SPI or ADC.
As the Galileo is running Linux and emulating the Arduino IDE, the GPIO’s run a lot slower than expected, as the chip copes with this overhead.
The GPIO’s on the Galileo are routed through the Cypress CY8C9540A chip, which drastically slows down the performance of these pins, however, not all of the GPIO pins are routed through the PWM.
While reading up on this, I found the below post by “deckard026354” on the Intel communities site, which states the Galileo has 2 dedicated IO’s with “significant data rates”.
I managed to get my hands on a Saleae Logic Analyser, which I used to measure the speeds of the GPIO.
I created a basic sketch on the Arduino IDE and measured the frequency at the Galileo outputs.
Default speed – 226Hz:
int led = 2; void setup() { pinMode(led, OUTPUT); } void loop() { digitalWrite(led, HIGH); digitalWrite(led, LOW); }
Output:
As expected, the wave form reads 226Hz, pretty slow though – so lets see what we can do about that.
Example-1 – outputs 477kHz waveform on IO2:
void setup() { // put your setup code here, to run once: pinMode(2, OUTPUT_FAST); } void loop() { // put your main code here, to run repeatedly: digitalWrite(2, HIGH); digitalWrite(2, LOW); }
Output:
The output measures 444KHz, not too shabby. Although I seem to me missing 33Hz… I’ve measured this a few times and am pretty sure it’s accurate. So it could possibly be down to the overhead from the Galileo emulating the Arduino IDE.
Example-2 – outputs 683kHz waveform on IO3:
void setup(){ pinMode(2, OUTPUT_FAST); } void loop() { register int x = 0; while(1){ fastGpioDigitalWrite(GPIO_FAST_IO2, x); x =!x; } }
Output – 705KHz:
The pulses generated seemed to alternate between 667KHz and 705KHz, I’m not sure if this is an inaccuracy with the Galileo or the Saleae, although this does average at 686KHz, so it looks to be an issue with the measurement.
Example-3 – outputs 2.93MHz waveform on IO3:
uint32_t latchValue; void setup(){ pinMode(3, OUTPUT_FAST); latchValue = fastGpioDigitalLatch(); } void loop() { while(1){ fastGpioDigitalWriteDestructive(latchValue); latchValue ^= GPIO_FAST_IO3; } }
Output:
Nice! 3MHz from a GPIO,
Although I’m a bit worried about the function name “fastGpioDigitalWriteDestructive“, so I’d like to know a bit more about this before using it in a dedicated sketch.
Example-4 – outputs 2.93MHz waveform on both IO2 and IO3:
uint32_t latchValue; void setup(){ pinMode(2, OUTPUT_FAST); pinMode(3, OUTPUT_FAST); latchValue = fastGpioDigitalLatch(); // latch initial state } void loop() { while(1){ fastGpioDigitalWriteDestructive(latchValue); if(latchValue & GPIO_FAST_IO3){ latchValue |= GPIO_FAST_IO2; latchValue &= ~ GPIO_FAST_IO3; }else{ latchValue |= GPIO_FAST_IO3; latchValue &= GPIO_FAST_IO2; } } }
Output:
I didn’t get this to work -_-
If I get a chance, I’ll go through the code again at a later stage and debug…
So there you go, depending on how you program IO2 or IO3, you can get:
- 226Hz by using the default setup.
- 477KHz by using pinMode(2, OUTPUT_FAST).
- 683KHz by using fastGpioDigitalWrite(GPIO_FAST_IO3, x);
- 2.93MHz by using fastGpioDigitalWriteDestructive – although I don’t like the sound of this command…
Nice work 🙂
I worry about the long term stability of this approach though, as it will suffer from jitter, flutter and even possible dropouts. The reason I suspect that is because the sketch on Galileo is simply a linux executable running with normal priority. The timing therefore is non-deterministic. Your code may not get scheduled to run at any specific regularity. If you were to take a deep memory log of the output, over several minutes and during that time do other things such as SSH connect to galileo, search for files, or whatever I’m sure you’d see timing discrepancies on the output.
Of course, that may be perfectly acceptable in your application!
How about using PWM to give any frequency and any duty cycle without any chance of jitter or dropout?
Hi SpiderKenny,
To be honest I’ve completed this more so as an exercise to understand the GPIO’s on the Galileo.
I’ve had a quick look around for more information on how to program the PWM to the correct – however I’ve only really found information on how to use the PWM with a servo motor, or how to program it via the Linux console.
I may have a go again programming it through the Linux console but right now I don’t have access to enough information to complete this project using the PWM in an Arduino Sketch (If you can find anymore info – feel free to forward it on to me!).
The project I’m hoping to complete is to create an IR remote control, connected to my SLR camera and do some cool night photography / timelapse photography, the GPIO’s will work for this (Spoiler alert: I’ve got the remote working, just need to clean up some code and I’ll create another post about it).
Thanks for visiting my blog and posting 🙂