Difference between revisions of "GPIO Driver"

From ArmadeusWiki
Jump to: navigation, search
(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 write (echo) pin direction
+
* 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 23:55, 9 September 2007

On this page, you will find all the informations needed to use the Armadeus GPIO driver.

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)

Links