Difference between revisions of "GPIO Driver"
m (→Compilation) |
|||
Line 3: | Line 3: | ||
==Compilation== | ==Compilation== | ||
The first thing you have to do is to compile the driver. The only way to do that for the moment is to compile it as a module: | The first thing you have to do is to compile the driver. The only way to do that for the moment is to compile it as a module: | ||
+ | <pre> | ||
[host]$ cd armadeus/ | [host]$ cd armadeus/ | ||
[host]$ make linux26-menuconfig | [host]$ make linux26-menuconfig | ||
− | Then go in menu: | + | </pre> |
− | + | Then go in menu: | |
+ | <pre class="config"> | ||
+ | Device Drivers | ||
+ | --> Armadeus specific drivers | ||
+ | <M> Armadeus GPIO driver | ||
+ | <M> Armadeus Parallel Port driver | ||
+ | </pre> | ||
+ | |||
Exit and save your kernel configuration, then compile it: | Exit and save your kernel configuration, then compile it: | ||
+ | <pre> | ||
[host]$ make linux26 | [host]$ make linux26 | ||
+ | </pre> | ||
When compiled, you will obtain 2 modules in ''armadeus/target/linux/modules/gpio/'': | When compiled, you will obtain 2 modules in ''armadeus/target/linux/modules/gpio/'': | ||
Line 19: | Line 29: | ||
* copy loadgpio.sh script on your rootfs in /etc/ | * copy loadgpio.sh script on your rootfs in /etc/ | ||
After that you can launch: | After that you can launch: | ||
+ | <pre class="apf"> | ||
# sh /etc/loadgpio.sh | # sh /etc/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> | ||
Line 38: | Line 52: | ||
====Examples:==== | ====Examples:==== | ||
* 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 DevFull (pin 31 of portD): | * Blinks the LED on DevFull (pin 31 of portD): | ||
+ | <pre class="apf"> | ||
# 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> | ||
* 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: | * You can put it in a shell function: | ||
+ | <pre class="apf"> | ||
setbit() | setbit() | ||
{ | { | ||
Line 74: | Line 103: | ||
# setbit /proc/driver/gpio/portAdir 5 0 | # setbit /proc/driver/gpio/portAdir 5 0 | ||
+ | </pre> | ||
* Blocking read on the PortD pin 0: | * Blocking read on the PortD pin 0: | ||
+ | <pre class="apf"> | ||
# cat /dev/gpio/PD0 | # cat /dev/gpio/PD0 | ||
+ | </pre> | ||
=== Directly with C program ( /proc filesystem) === | === Directly with C program ( /proc filesystem) === |
Revision as of 09:58, 3 February 2009
On this page, you will find all the informations needed to use the Armadeus GPIO driver.
Contents
Compilation
The first thing you have to do is to compile the driver. The only way to do that for the moment is to compile it as a module:
[host]$ cd armadeus/ [host]$ make linux26-menuconfig
Then go in menu:
Device Drivers --> Armadeus specific drivers <M> Armadeus GPIO driver <M> Armadeus Parallel Port driver
Exit and save your kernel configuration, then compile it:
[host]$ make linux26
When compiled, you will obtain 2 modules in armadeus/target/linux/modules/gpio/:
- gpio.ko: this is the main driver. It should be loaded first and will allow you to easily control gpio pin from user space,
- ppdev.ko: 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).
Installation
You have to:
- reflash your rootfs or copy these modules on your target in /lib/modules/2.6.18.1/extra/gpio (don't forget modules.dep file),
- copy loadgpio.sh script on your rootfs in /etc/
After that you can launch:
# sh /etc/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,
If you don't know what these registers means, load the module without parameters !!
Driver usage
Directly with shell commands (through /proc & /dev filesystem)
GPIO driver is configurable through /proc interface:
- use /proc/drivers/gpio/portXdir to read (with cat) or set (with echo) pin direction (where X is your port name: A, B, C or D)
- then use /proc/drivers/gpio/portX to read (with cat) or write (with echo) pin status
- /proc/drivers/gpio/portXirq: configure if GPIO should be used as an interruptible one (ie blocking read)
- /proc/drivers/gpio/portXpullup: (de)activate i.MXL internal pull-up for that GPIO
Examples:
- 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 DevFull (pin 31 of portD):
# 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
- 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
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;
char buffer[32];
char * bufferDir="00000000011111111000000000000000";
char * buffer1= "00000000000000011000000000000000";
char * buffer2= "00000000000001100000000000000000";
char * buffer3= "00000000000110000000000000000000";
char * buffer4= "00000000011000000000000000000000";
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);
Directly from a C program with IOCTLs
There is another way to drive GPIO module: with IOCTLs on the right device node. ioctl() function is using flags to say what it must be done (read and write):
- GPIORDDIRECTION for reading direction of the concerned port
- GPIOWRDIRECTION for writing direction of the concerned port
- GPIORDDATA for reading data of the concerned port
- GPIOWRDATA for writing data of the concerned port
An example of code will give more explanation:
int fd;
int i;
int iomask,result;
unsigned char dev_buffer[BUF_SIZE+1];
if ((fd = open("/dev/gpio/portD", O_RDWR))<0) {
printf("Open error on /dev/gpio/portD\n");
exit(0);
}
printf("Opened on /dev/gpio/portD\n");
iomask=0xFFFFFF00;
ioctl(fd,GPIOWRDIRECTION,&iomask);
iomask=0x003F0000;
for (i=0;i<2;i++) {
printf("Led ON\n");
iomask=0x007F8000;
ioctl(fd,GPIOWRDATA,&iomask);
sleep(1);
ioctl(fd,GPIORDDATA,&iomask);
printf("read /dev/gpio/portD 0x%x\n",iomask);
printf("Led OFF\n");
iomask=0x00000000;
ioctl(fd,GPIOWRDATA,&iomask);
sleep(1);
}
close(fd);
exit(0);
Of course you'll need to declare in the include part, the following:
- sys/ioctl.h
- linux/ppdev.h
and define pragmas such as:
- GPIORDDIRECTION _IOR(PP_IOCTL, 0xF0, int)
- GPIOWRDIRECTION _IOW(PP_IOCTL, 0xF1, int)
- GPIORDDATA _IOR(PP_IOCTL, 0xF2, int)
- GPIOWRDATA _IOW(PP_IOCTL, 0xF3, int)