I already blogged how to blink LED connected to OLinuXino GPIO through the shell script here https://olimex.wordpress.com/2012/04/23/blinking-led-with-linux-or-hello-world-with-imx233-olinuxino/
today I did experiement to see what is the fastest GPIO toggel I can achieve with this method and this code:
echo out > /sys/class/gpio/gpio0/direction
while [ 1 -eq 1 ]
do
echo 1 > /sys/class/gpio/gpio0/value
echo 0 > /sys/class/gpio/gpio0/value
done
makes nice 400Hz square wave on oscilloscope this means 1.25mS to set GPIO high and 1.25mS to set GPIO low.
Quite OK if you do some slow IO processes like switching ON OFF relays etc but slow if you want to do something faster, so I decided to see what will happend if I make same code in C.
For this purpose I decided to use the Green LED next to PWR jack which is connected to GPIO65:
#include <stdio.h>
#include <fcntl.h>
#include <string.h>int main()
{char s_out[] = “out”;
char s_0[] = “0”;
char s_1[] = “1”;
int fd;//define GPIO65 as output
if((fd=open(“/sys/class/gpio/gpio65/direction”,O_RDWR))<0)
return(1);
else {if(write(fd,s_out,strlen(s_out))<0)
return(1);printf(“GPIO65 set as output\r\n”);
if(close(fd)<0)
return(1);
}//toggle GPIO65
if((fd=open(“/sys/class/gpio/gpio65/value”,O_RDWR))<0)
return(1);
else {while(1) {
if(write(fd,s_1,strlen(s_1))<0)
return(1);if(write(fd,s_0,strlen(s_0))<0)
return(1);
};if(close(fd)<0)
return(1);
}}
This code improved the speed significant now I can see 140 kHz on GPIO65 with 3.5 uS high and 3.5 uS low time.
Although about 350 times faster than shell script this still seems slow to me, there is another approach to access the GPIOs under Linux and this is through “/dev/mem” writing directly in memory and iMX233 registers.
So what would be the speed if we write directly to the memory/registers? There is nice documentation with about 50 pages explaining how to set GPIOs 🙂 I may find a time during the weekend to read and try to implement it.
Sep 07, 2012 @ 18:11:49
Dear Olimex,
thanks for all your great work! My experience with gpio always stopped me from using for high speed serial communication e.g: configuration of fpga in slave serial mode, in this case, configuring a bigger fpga in less than 1 to 2 sec is a real challenge if you use gpio to generate data and clock.
For this we found a solution with SPI h/w block built inside the ARM cpu(ex: TI sitara AM335x) – with spi serial lines, we are able to configure 2megabyte of data to fpga in less than 1second.
I wish similar thing should be possible on your iMX233 board.
Br,
Albert.
Sep 07, 2012 @ 18:19:45
for serial link SPI is many times faster indeed, toggling GPIO is always bad idea running RTOS, small PIC or AVR would toggle their GPIOs faster as they work on bare metal, with the RTOS for instance I had LED blink running in background so I was seeing glitches with the oscilloscope every second when the script in the background was toggling the LED each second 🙂
Sep 08, 2012 @ 00:02:40
Olimex> I think you meant non-RTOS 😉 If you are indeed running a RTOS (or a standard OS with RTOS extensions), then the priority thread/task (in this case: blinking the LED) should *always* execute in the timeframe you requested.
Simple example from the real world: LinuxCNC uses the RTAI Linux kernel RTOS extensions. If you set the step rate too high, even X11 will begin to be sluggish but the actual pulse train out the parallel port will remain true to the given frequency. That’s the point about RTOS-es: to guarantee that some action (e.g. receiving a packet, resetting a watchdog, servicing an interrupt etc.) will happen in a definite timeframe no matter what else is going on in the system.
Now, about toggling GPIOs on the board in question, it’s always going to be dead slow from a shell script, faster from C and fastest via mmap(). It doesn’t have anything to do with the board or the CPU used, it’s simply “less layers is faster”. The same holds for Linux running on a PC, no matter how fast the CPU is, going through more layers will still be progressively slower.
The art of writing and running RTOS-using software on a conventional platform (i.e. that you expect to do something else apart from running your realtime stuff), is what you put in the realtime thread 🙂 You should, of course, put the minimum necessary stuff to meet your timing constraints and nothing else — and the good news is that this is not at all new stuff: people have been doing it for serial ports and sound cards for ages.
Hope this helps.