Difference between revisions of "GPIO Driver"
(→Module compilation & installation) |
(Add work from StephaneF) |
||
| Line 26: | Line 26: | ||
== Driver usage == | == Driver usage == | ||
| + | |||
| + | === Directly with shell commands (through /proc filesystem) === | ||
| + | |||
GPIO driver is usable through 2 interfaces: | GPIO driver is usable through 2 interfaces: | ||
| − | * use /proc/drivers/gpio/portXdir to read (cat) or | + | * use ''/proc/drivers/gpio/portXdir'' to read (cat) or set (echo) pin direction |
| − | * use /proc/drivers/gpio/portX to read (cat) or write (echo) pin status | + | * then use /proc/drivers/gpio/portX to read (cat) or write (echo) pin status |
Examples: | Examples: | ||
| − | See which IO-Pins of PortD are configured as inputs, and which are outputs ('1' = output, '0' = input): | + | See which IO-Pins of PortD are configured as inputs, and which are |
| + | outputs ('1' = output, '0' = input): | ||
# cat /proc/driver/gpio/portDdir## | # cat /proc/driver/gpio/portDdir## | ||
| − | Configure the IO-Pins 30, 28, 23, 22 and 21 of PortB as outputs, all others are inputs: | + | Configure the IO-Pins 30, 28, 23, 22 and 21 of PortB as outputs, all |
| − | # echo 01010000111000000000000000000000 >/proc/driver/gpio/portBdir | + | others are inputs: |
| + | # echo 01010000111000000000000000000000 > /proc/driver/gpio/portBdir | ||
| − | Read the status of the IOs of PortB: | + | Read the status/values of the IOs of PortB: |
# cat /proc/driver/gpio/portB | # cat /proc/driver/gpio/portB | ||
Set bits 30, 28 and 23 of PortB to '1', all other outputs to '0': | Set bits 30, 28 and 23 of PortB to '1', all other outputs to '0': | ||
# echo 01010000100000000000000000000000 > /proc/driver/gpio/portB | # echo 01010000100000000000000000000000 > /proc/driver/gpio/portB | ||
| + | |||
| + | === 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) | ||
== Links == | == Links == | ||
* http://soekris.hejl.de/ | * http://soekris.hejl.de/ | ||
* http://people.redhat.com/twaugh/parport/html/ppdev.html | * http://people.redhat.com/twaugh/parport/html/ppdev.html | ||
| + | * http://www.krugle.com/examples/p-yckfcEKjgfqvsNcB/drivertest.c | ||
Revision as of 22:55, 9 September 2007
On this page, you will find all the informations needed to use the Armadeus GPIO driver.
Contents
Module compilation & installation
The first thing you have to do is to compile the driver. The only way to do that actually is to compile it as a module:
[host]$ cd armadeus/ [host]$ make linux-menuconfig
Then Go in menu: Device Drivers ---> Armadeus specific drivers and choose <M> Armadeus GPIO driver + <M> Armadeus Parallel Port driver Exit and save your kernel configuration Compile it:
[host]$ make linux
When compiled, you will obtain 3 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. This way you will be able to emulate a standard parallel port on one GPIO port (and then for example connect a LCD)
- loadfpga.ko: this is an extension driver to add the possibility to load the fpga on APF boards from linux userspace -> fpga reprogrammation after linux boot.
Then, you have to:
- copy these modules on your rootfs in /lib/modules/2.6.18.1/extra/gpio (dont forget modules.dep) or reflash your rootfs
- 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,
Driver usage
Directly with shell commands (through /proc filesystem)
GPIO driver is usable through 2 interfaces:
- use /proc/drivers/gpio/portXdir to read (cat) or set (echo) pin direction
- then use /proc/drivers/gpio/portX to read (cat) or write (echo) pin status
Examples: See which IO-Pins of PortD are configured as inputs, and which are outputs ('1' = output, '0' = input):
# cat /proc/driver/gpio/portDdir##
Configure the IO-Pins 30, 28, 23, 22 and 21 of PortB as outputs, all others are inputs:
# echo 01010000111000000000000000000000 > /proc/driver/gpio/portBdir
Read the status/values of the IOs of PortB:
# cat /proc/driver/gpio/portB
Set bits 30, 28 and 23 of PortB to '1', all other outputs to '0':
# echo 01010000100000000000000000000000 > /proc/driver/gpio/portB
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)