Difference between revisions of "GPIO Driver"
m (→Directly with C program ( /proc filesystem)) |
|||
(28 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
+ | {{Warning| This article describe the method to use gpio with armadeus '''version < 4.0'''. To use gpio on armadeus '''version 4.0''' or more see [[GPIOlib]]}} | ||
+ | |||
+ | |||
On this page, you will find all the informations needed to use the Armadeus GPIO driver. | On this page, you will find all the informations needed to use the Armadeus GPIO driver. | ||
+ | ==Installation== | ||
==Compilation== | ==Compilation== | ||
− | + | Since Armadeus-3.0 release, gpio driver is compiled and installed by default in rootfs. See [[Talk:GPIO_Driver]] to know how. | |
− | + | ||
− | + | ||
− | + | ||
− | [[ | + | |
− | + | ||
− | + | ||
− | + | You have 2 modules: | |
− | * gpio | + | * gpio: this is the main driver. It should be loaded first and will allow you to easily control GPIO pins from user space, |
− | * ppdev | + | * ppdev: this is an extension driver to add PPDEV emulation to gpio.ko. This way you will be able to emulate a standard parallel port on one GPIO port (to connect a textual LCD, for example). |
+ | {{Note|The parallel port driver (ppdev) will only work on [[APF9328]] based systems for now !}} | ||
− | == | + | ===Loading driver=== |
− | + | <pre class="apf"> | |
− | + | # /usr/bin/loadgpio.sh | |
− | + | </pre> | |
− | + | ||
− | + | ||
or look inside this script if you want to manually enter the module parameters: | or look inside this script if you want to manually enter the module parameters: | ||
+ | <pre class="apf"> | ||
# modprobe gpio portB_init=0,0,0x00FFFF00,0,0,0,0,0,0x0FF00000,0,0,0,0,0,0,0x0FF00000 | # modprobe gpio portB_init=0,0,0x00FFFF00,0,0,0,0,0,0x0FF00000,0,0,0,0,0,0,0x0FF00000 | ||
+ | </pre> | ||
gpio module parameters are values for PORTA, PORTB, PORTC, PORTD configuration registers in following order: | gpio module parameters are values for PORTA, PORTB, PORTC, PORTD configuration registers in following order: | ||
DDIR, OCR1, OCR2, ICONFA1, ICONFA2, ICONFB1, ICONFB2, DR, GIUS, SSR, ICR1, ICR2, IMR, GPR, SWR, PUEN,<br> | DDIR, OCR1, OCR2, ICONFA1, ICONFA2, ICONFB1, ICONFB2, DR, GIUS, SSR, ICR1, ICR2, IMR, GPR, SWR, PUEN,<br> | ||
− | + | {{Warning|If you don't know what these registers means, load the module without parameters !!}} | |
== Driver usage == | == Driver usage == | ||
+ | |||
+ | === As_devices === | ||
+ | |||
+ | GPIO can be use with library [[AsDevices]]. | ||
=== Directly with shell commands (through /proc & /dev filesystem) === | === Directly with shell commands (through /proc & /dev filesystem) === | ||
− | GPIO driver is | + | GPIO driver is usable through its /proc interface: |
− | + | # use ''/proc/drivers/gpio/portXmode'' to configure a pin as a gpio (with ''echo'') and where X is your port name: A, B, C or D (E,F for apf27) | |
− | + | # use ''/proc/drivers/gpio/portXdir'' to read (with ''cat'') or set (with ''echo'') pin direction (where X is your port name) | |
− | + | # then use ''/proc/drivers/gpio/portX'' to read (with ''cat'') or write (with ''echo'') pin status | |
− | + | # ''/proc/drivers/gpio/portXirq'': to configure GPIO as an interrupt (blocking read); 0-> no interrupt, 1-> rising edge, 2-> falling edge, 3-> both edges | |
+ | # ''/proc/drivers/gpio/portXpullup'': (de)activate i.MX internal pull-up for that GPIO | ||
+ | |||
+ | ====Examples==== | ||
+ | * Configure IO-Pin 31 of port A (LCD_OE_ACD on the APF27) as GPIO (not reversible): | ||
+ | <pre class="apf"> | ||
+ | # echo -n 10000000000000000000000000000000 > /proc/driver/gpio/portAmode | ||
+ | </pre> | ||
− | |||
* See which IO-Pins of PortD are configured as inputs, and which one are outputs ('1' = output, '0' = input): | * See which IO-Pins of PortD are configured as inputs, and which one are outputs ('1' = output, '0' = input): | ||
+ | <pre class="apf"> | ||
# cat /proc/driver/gpio/portDdir | # cat /proc/driver/gpio/portDdir | ||
01101100111100000110110011110000 pins order: [31...0] | 01101100111100000110110011110000 pins order: [31...0] | ||
# | # | ||
+ | </pre> | ||
* Configure the IO-Pins 30, 28, 23, 22 and 21 of PortB as outputs ('1'), all others as inputs ('0'): | * Configure the IO-Pins 30, 28, 23, 22 and 21 of PortB as outputs ('1'), all others as inputs ('0'): | ||
+ | <pre class="apf"> | ||
# echo -n 01010000111000000000000000000000 > /proc/driver/gpio/portBdir | # echo -n 01010000111000000000000000000000 > /proc/driver/gpio/portBdir | ||
+ | </pre> | ||
* Read the status/values of the IOs of PortB: | * Read the status/values of the IOs of PortB: | ||
+ | <pre class="apf"> | ||
# cat /proc/driver/gpio/portB | # cat /proc/driver/gpio/portB | ||
00000000000011111111000000000000 | 00000000000011111111000000000000 | ||
# | # | ||
+ | </pre> | ||
* Set bits 30, 28 and 23 of PortB to '1', all other outputs to '0': '''<-- DEPRECATED, use /dev/gpio/ instead !''' | * Set bits 30, 28 and 23 of PortB to '1', all other outputs to '0': '''<-- DEPRECATED, use /dev/gpio/ instead !''' | ||
+ | <pre class="apf"> | ||
# echo -n 01010000100000000000000000000000 > /proc/driver/gpio/portB | # echo -n 01010000100000000000000000000000 > /proc/driver/gpio/portB | ||
+ | </pre> | ||
− | * Blinks the LED on | + | * Blinks the LED on [[APF9328DevFull]] (pin 31 of portD): |
+ | <pre class="apf"> | ||
+ | # cat /proc/driver/gpio/portDmode | sed "s/[0-1]\([0-1]\{31\}\)$/1\1/" > /proc/driver/gpio/portDmode | ||
# cat /proc/driver/gpio/portDdir | sed "s/[0-1]\([0-1]\{31\}\)$/1\1/" > /proc/driver/gpio/portDdir | # cat /proc/driver/gpio/portDdir | sed "s/[0-1]\([0-1]\{31\}\)$/1\1/" > /proc/driver/gpio/portDdir | ||
# echo -ne "\x00" > /dev/gpio/PD31 | # echo -ne "\x00" > /dev/gpio/PD31 | ||
# echo -ne "\x01" > /dev/gpio/PD31 | # echo -ne "\x01" > /dev/gpio/PD31 | ||
+ | </pre> | ||
+ | |||
+ | * Blinks the LED on [[APF27Dev]] (pin 14 of portF): | ||
+ | <pre class="apf"> | ||
+ | # cat /proc/driver/gpio/portFmode | sed "s/[0-1]\([0-1]\{14\}\)$/1\1/" > /proc/driver/gpio/portFmode | ||
+ | # cat /proc/driver/gpio/portFdir | sed "s/[0-1]\([0-1]\{14\}\)$/1\1/" > /proc/driver/gpio/portFdir | ||
+ | # echo -ne "\x01" > /dev/gpio/PF14 | ||
+ | # echo -ne "\x00" > /dev/gpio/PF14 | ||
+ | </pre> | ||
* Sets only bit 5 of portADir to 1: | * Sets only bit 5 of portADir to 1: | ||
+ | <pre class="apf"> | ||
# cat /proc/driver/gpio/portAdir | sed "s/[0-1]\([0-1]\{'''5'''\}\)$/'''1'''\1/" > /proc/driver/gpio/portAdir | # cat /proc/driver/gpio/portAdir | sed "s/[0-1]\([0-1]\{'''5'''\}\)$/'''1'''\1/" > /proc/driver/gpio/portAdir | ||
+ | </pre> | ||
* Sets only bit 5 of portADir to 0: | * Sets only bit 5 of portADir to 0: | ||
+ | <pre class="apf"> | ||
# cat /proc/driver/gpio/portAdir | sed "s/[0-1]\([0-1]\{'''5'''\}\)$/'''0'''\1/" > /proc/driver/gpio/portAdir | # cat /proc/driver/gpio/portAdir | sed "s/[0-1]\([0-1]\{'''5'''\}\)$/'''0'''\1/" > /proc/driver/gpio/portAdir | ||
+ | </pre> | ||
+ | |||
+ | * You can put it in a shell function: | ||
+ | <pre class="apf"> | ||
+ | setbit() | ||
+ | { | ||
+ | PORT=$1 | ||
+ | NB=$2 | ||
+ | VAL=$3 | ||
+ | cat $PORT | sed "s/[0-1]\([0-1]\{$NB\}\)$/$VAL\1/" > $PORT | ||
+ | } | ||
+ | |||
+ | # setbit /proc/driver/gpio/portAdir 5 0 | ||
+ | </pre> | ||
* Blocking read on the PortD pin 0: | * Blocking read on the PortD pin 0: | ||
− | # cat /dev/gpio/PD0 | + | <pre class="apf"> |
+ | # cat /dev/gpio/PD0 | less | ||
+ | </pre> | ||
− | === Directly | + | * A test script is available in ''target/test/'' : [http://armadeus.git.sourceforge.net/git/gitweb.cgi?p=armadeus/armadeus;a=blob;f=target/test/test_gpio.sh;h=e2e54e855aeb25b0f0cbae5915930e9f904861dc;hb=HEAD test_gpio.sh] |
+ | |||
+ | === Directly from a C program with IOCTLs === | ||
+ | |||
+ | There is another way to drive GPIO module: with IOCTLs on the right device node (full port).<br> | ||
+ | ioctl() function is using flags to say what must be done: | ||
+ | * GPIORDDIRECTION for reading direction settings of the corresponding port | ||
+ | * GPIOWRDIRECTION for writing direction settings | ||
+ | * GPIORDDATA for reading data on the corresponding port | ||
+ | * GPIOWRDATA for writing data | ||
+ | * Etc... | ||
+ | |||
+ | There is a small C example in ''target/demos/gpio/'' that will give you more explanation: [http://armadeus.git.sourceforge.net/git/gitweb.cgi?p=armadeus/armadeus;a=blob_plain;f=target/demos/gpio/blink_led.c;hb=HEAD blink_led.c] | ||
+ | |||
+ | === Directly with C program: /proc filesystem=== | ||
+ | {{Note|For performance please use IOCTL instead (see above)}} | ||
After inserting the GPIO module, /proc entries are created in the | After inserting the GPIO module, /proc entries are created in the | ||
Line 81: | Line 143: | ||
int i; | int i; | ||
unsigned char dummy; | unsigned char dummy; | ||
− | FILE *GPIO,*GPIODIR; | + | FILE *GPIO,*GPIODIR, *GPIOMODE; |
char buffer[32]; | char buffer[32]; | ||
− | char * bufferDir="00000000011111111000000000000000"; | + | char * bufferMode="00000000011111111000000000000000"; |
− | char * buffer1= | + | char * bufferDir= "00000000011111111000000000000000"; |
− | char * buffer2= | + | char * buffer1= "00000000000000011000000000000000"; |
− | char * buffer3= | + | char * buffer2= "00000000000001100000000000000000"; |
− | char * buffer4= | + | char * buffer3= "00000000000110000000000000000000"; |
+ | char * buffer4= "00000000011000000000000000000000"; | ||
+ | GPIOMODE = fopen("/proc/driver/gpio/portDmode","w"); | ||
+ | setvbuf(GPIOMODE,buffer,_IONBF,32); | ||
+ | fwrite(bufferMode, sizeof(char), strlen(bufferMode), GPIOMODE); | ||
+ | fclose(GPIOMODE); | ||
GPIODIR = fopen("/proc/driver/gpio/portDdir","w"); | GPIODIR = fopen("/proc/driver/gpio/portDdir","w"); | ||
setvbuf(GPIODIR,buffer,_IONBF,32); | setvbuf(GPIODIR,buffer,_IONBF,32); | ||
Line 108: | Line 175: | ||
return (0); | return (0); | ||
</source> | </source> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
== Links == | == Links == | ||
Line 166: | Line 182: | ||
* [http://www.ipbx.ru/rm9200/gpio-RM9200.tar.gz AT91 way of doing it] | * [http://www.ipbx.ru/rm9200/gpio-RM9200.tar.gz AT91 way of doing it] | ||
* [http://www.avr32linux.org/twiki/bin/view/Main/GpioDevInterface AVR32 way of doing it] | * [http://www.avr32linux.org/twiki/bin/view/Main/GpioDevInterface AVR32 way of doing it] | ||
− | * [http:// | + | * [http://www.jibee.com/view.pl/OpenRobotik/GpioRoutingDriver JiBee's way of doing it] |
[[Category:UserInput]] | [[Category:UserInput]] | ||
[[Category:Linux drivers]] | [[Category:Linux drivers]] |
Latest revision as of 16:41, 12 December 2011
Warning: This article describe the method to use gpio with armadeus version < 4.0. To use gpio on armadeus version 4.0 or more see GPIOlib |
On this page, you will find all the informations needed to use the Armadeus GPIO driver.
Contents
Installation
Compilation
Since Armadeus-3.0 release, gpio driver is compiled and installed by default in rootfs. See Talk:GPIO_Driver to know how.
You have 2 modules:
- gpio: this is the main driver. It should be loaded first and will allow you to easily control GPIO pins from user space,
- ppdev: this is an extension driver to add PPDEV emulation to gpio.ko. This way you will be able to emulate a standard parallel port on one GPIO port (to connect a textual LCD, for example).
Note: The parallel port driver (ppdev) will only work on APF9328 based systems for now ! |
Loading driver
# /usr/bin/loadgpio.sh
or look inside this script if you want to manually enter the module parameters:
# modprobe gpio portB_init=0,0,0x00FFFF00,0,0,0,0,0,0x0FF00000,0,0,0,0,0,0,0x0FF00000
gpio module parameters are values for PORTA, PORTB, PORTC, PORTD configuration registers in following order:
DDIR, OCR1, OCR2, ICONFA1, ICONFA2, ICONFB1, ICONFB2, DR, GIUS, SSR, ICR1, ICR2, IMR, GPR, SWR, PUEN,
Driver usage
As_devices
GPIO can be use with library AsDevices.
Directly with shell commands (through /proc & /dev filesystem)
GPIO driver is usable through its /proc interface:
- use /proc/drivers/gpio/portXmode to configure a pin as a gpio (with echo) and where X is your port name: A, B, C or D (E,F for apf27)
- use /proc/drivers/gpio/portXdir to read (with cat) or set (with echo) pin direction (where X is your port name)
- then use /proc/drivers/gpio/portX to read (with cat) or write (with echo) pin status
- /proc/drivers/gpio/portXirq: to configure GPIO as an interrupt (blocking read); 0-> no interrupt, 1-> rising edge, 2-> falling edge, 3-> both edges
- /proc/drivers/gpio/portXpullup: (de)activate i.MX internal pull-up for that GPIO
Examples
- Configure IO-Pin 31 of port A (LCD_OE_ACD on the APF27) as GPIO (not reversible):
# echo -n 10000000000000000000000000000000 > /proc/driver/gpio/portAmode
- See which IO-Pins of PortD are configured as inputs, and which one are outputs ('1' = output, '0' = input):
# cat /proc/driver/gpio/portDdir 01101100111100000110110011110000 pins order: [31...0] #
- Configure the IO-Pins 30, 28, 23, 22 and 21 of PortB as outputs ('1'), all others as inputs ('0'):
# echo -n 01010000111000000000000000000000 > /proc/driver/gpio/portBdir
- Read the status/values of the IOs of PortB:
# cat /proc/driver/gpio/portB 00000000000011111111000000000000 #
- Set bits 30, 28 and 23 of PortB to '1', all other outputs to '0': <-- DEPRECATED, use /dev/gpio/ instead !
# echo -n 01010000100000000000000000000000 > /proc/driver/gpio/portB
- Blinks the LED on APF9328DevFull (pin 31 of portD):
# cat /proc/driver/gpio/portDmode | sed "s/[0-1]\([0-1]\{31\}\)$/1\1/" > /proc/driver/gpio/portDmode # cat /proc/driver/gpio/portDdir | sed "s/[0-1]\([0-1]\{31\}\)$/1\1/" > /proc/driver/gpio/portDdir # echo -ne "\x00" > /dev/gpio/PD31 # echo -ne "\x01" > /dev/gpio/PD31
- Blinks the LED on APF27Dev (pin 14 of portF):
# cat /proc/driver/gpio/portFmode | sed "s/[0-1]\([0-1]\{14\}\)$/1\1/" > /proc/driver/gpio/portFmode # cat /proc/driver/gpio/portFdir | sed "s/[0-1]\([0-1]\{14\}\)$/1\1/" > /proc/driver/gpio/portFdir # echo -ne "\x01" > /dev/gpio/PF14 # echo -ne "\x00" > /dev/gpio/PF14
- Sets only bit 5 of portADir to 1:
# cat /proc/driver/gpio/portAdir | sed "s/[0-1]\([0-1]\{'''5'''\}\)$/'''1'''\1/" > /proc/driver/gpio/portAdir
- Sets only bit 5 of portADir to 0:
# cat /proc/driver/gpio/portAdir | sed "s/[0-1]\([0-1]\{'''5'''\}\)$/'''0'''\1/" > /proc/driver/gpio/portAdir
- You can put it in a shell function:
setbit() { PORT=$1 NB=$2 VAL=$3 cat $PORT | sed "s/[0-1]\([0-1]\{$NB\}\)$/$VAL\1/" > $PORT } # setbit /proc/driver/gpio/portAdir 5 0
- Blocking read on the PortD pin 0:
# cat /dev/gpio/PD0 | less
- A test script is available in target/test/ : test_gpio.sh
Directly from a C program with IOCTLs
There is another way to drive GPIO module: with IOCTLs on the right device node (full port).
ioctl() function is using flags to say what must be done:
- GPIORDDIRECTION for reading direction settings of the corresponding port
- GPIOWRDIRECTION for writing direction settings
- GPIORDDATA for reading data on the corresponding port
- GPIOWRDATA for writing data
- Etc...
There is a small C example in target/demos/gpio/ that will give you more explanation: blink_led.c
Directly with C program: /proc filesystem
After inserting the GPIO module, /proc entries are created in the
filesystem, and so it's possible to directly use some Linux standard functions
inside a C program, such as:
- fopen
- fwrite
- fread
- fclose
A little piece of code is the best way to understand quickly:
int i;
unsigned char dummy;
FILE *GPIO,*GPIODIR, *GPIOMODE;
char buffer[32];
char * bufferMode="00000000011111111000000000000000";
char * bufferDir= "00000000011111111000000000000000";
char * buffer1= "00000000000000011000000000000000";
char * buffer2= "00000000000001100000000000000000";
char * buffer3= "00000000000110000000000000000000";
char * buffer4= "00000000011000000000000000000000";
GPIOMODE = fopen("/proc/driver/gpio/portDmode","w");
setvbuf(GPIOMODE,buffer,_IONBF,32);
fwrite(bufferMode, sizeof(char), strlen(bufferMode), GPIOMODE);
fclose(GPIOMODE);
GPIODIR = fopen("/proc/driver/gpio/portDdir","w");
setvbuf(GPIODIR,buffer,_IONBF,32);
fwrite(bufferDir, sizeof(char), strlen(bufferDir), GPIODIR);
fclose(GPIODIR);
GPIO = fopen("/proc/driver/gpio/portD","w");
setvbuf(GPIO,buffer,_IONBF,32);
while(1) {
fwrite(buffer1, sizeof(char), strlen(buffer1), GPIO);
sleep(1);
fwrite(buffer2, sizeof(char), strlen(buffer2), GPIO);
sleep(1);
fwrite(buffer3, sizeof(char), strlen(buffer3), GPIO);
sleep(1);
fwrite(buffer4, sizeof(char), strlen(buffer4), GPIO);
sleep(1);
}
fclose(GPIO);
return (0);