Difference between revisions of "GPIO Driver"

From ArmadeusWiki
Jump to: navigation, search
m (Examples:)
(IOCTL prog is now included in SDK)
Line 154: Line 154:
 
* GPIORDDATA for reading data on the corresponding port
 
* GPIORDDATA for reading data on the corresponding port
 
* GPIOWRDATA for writing data
 
* GPIOWRDATA for writing data
 +
* Etc...
  
An example of code will give more explanation (APF9328 DevFull LED blinking):  
+
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]
<source lang="C">
+
 
+
  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);
+
</source>
+
 
+
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 ==

Revision as of 14:56, 26 August 2009

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

Compilation

Done by default starting from Armadeus-3.0 release. See Talk:GPIO_Driver to know how.

Installation

When compiled, you will 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 Note: The parallel port driver (ppdev) will only work on APF9328 based systems !


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,

Warning Warning: 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/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: 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:

  • Configure IO-Pin 31 of port A (LCD_OE_ACD on the APF27) as gpio
 # 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
 # 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
  • 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, *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);

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

Links