Page 1 of 1

[SOLVED]GPIO issues

Posted: Tue Jul 02, 2013 5:53 am
by tonygrim
I'm running 3.6.11+ #474 (soft float) and I've written a c++ app (in Qt4.8.2) that listens for signals on one or more GPIO pins. My app was working just fine until I upgraded to the current release, but now it can't map the GPIO locations.

The code (somewhat abridged, but you get the idea):

Code: Select all

#define GPIO_BASE 0x22000000
#define BLOCK_SIZE (4 * 1024)
bool PiGPIO::setupio()
{
    if((mem_fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) return false; // this succeeds when run as root

    gpio_map = (char *) mmap(
                             NULL,
                             BLOCK_SIZE,
                             PROT_READ | PROT_WRITE,
                             mem_fd,
                             GPIO_BASE); // always fails with errno 11 (EAGAIN -- Resource temporarily unavailable)
 // etc
}
I've looked at all getrlimit() and ulimit have to offer, but can find no reason there why the mmap call is failing.

Any help would be gratefully received.

Tony

Re: GPIO issues

Posted: Tue Jul 02, 2013 6:07 am
by PiGraham
Does another process on your system access the GPIO memory?

I note you don't have MAP_SHARED. specified as it is here:
http://elinux.org/RPi_Low-level_periphe ... e_examples

EAGAIN The file to be mapped is already locked
using advisory or mandatory record locking.
See fcntl(2).
Is there another instance of your code running? (ps -all)

Re: GPIO issues

Posted: Tue Jul 02, 2013 9:04 pm
by tonygrim
PiGraham wrote:Does another process on your system access the GPIO memory?

I note you don't have MAP_SHARED. specified as it is here:
http://elinux.org/RPi_Low-level_periphe ... e_examples

EAGAIN The file to be mapped is already locked
using advisory or mandatory record locking.
See fcntl(2).
Is there another instance of your code running? (ps -all)
Sorry - MAP_SHARED is there in my app code. I inadvertently omitted it when I put the example code in my original post above.

There is no other instance of my code running, according to ps -all. That leaves me looking for something else that is locking me out, though I can't think what it might be. I'm using a largely unmodified "vanilla" OS, only having removed stuff I've no need of, such as web browsers, games, python and having installed wicd to get wireless networking happening.

Re: GPIO issues

Posted: Tue Jul 02, 2013 9:16 pm
by joan
Try

Code: Select all

#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>

#define GPIO_BASE 0x20200000
#define GPIO_LEN  0xB4

#define GPLEV0    13
#define GPLEV1    14

static volatile uint32_t  * gpioReg = MAP_FAILED;

int gpioSetMode(unsigned gpio, unsigned mode)
{
   int reg, shift;

   reg   =  gpio/10;
   shift = (gpio%10) * 3;

   gpioReg[reg] = (gpioReg[reg] & ~(7<<shift)) | (mode<<shift);

   return 0;
}

int gpioGetMode(unsigned gpio)
{
   int reg, shift;

   reg   =  gpio/10;
   shift = (gpio%10) * 3;

   return (*(gpioReg + reg) >> shift) & 7;
}

uint32_t gpioRead_Bits_0_31(void) { return (*(gpioReg + GPLEV0)); }
uint32_t gpioRead_Bits_32_53(void) { return (*(gpioReg + GPLEV1)); }

main()
{
   int fd;

   fd = open("/dev/mem", O_RDWR | O_SYNC) ;

   gpioReg = mmap(0,
                  GPIO_LEN,
                  PROT_READ|PROT_WRITE|PROT_EXEC,
                  MAP_SHARED|MAP_LOCKED,
                  fd,
                  GPIO_BASE);

   close(fd);

   if (gpioReg != MAP_FAILED)
   {
      gpioSetMode(0,  0); /* mode value for input */
      gpioSetMode(1,  0); /* mode value for input */
      gpioSetMode(28, 4); /* mode value for alt0 */
      gpioSetMode(29, 4); /* mode value for alt0 */
   }
   else fprintf(stderr, "map failed\n");
}
Just tried on soft float (3.6.11+ #484) and it works.

Re: [SOLVED]GPIO issues

Posted: Tue Jul 02, 2013 10:58 pm
by tonygrim
Yep, that got it going - thanks!! :)

It's odd that it worked under the older OS. All I've effectively done is change the type of the gpio_map pointer returned by mmap from char* to volatile uint32* (previously this was done after the fact via a cast: gpio = (volatile unsigned long *) gpio_map).

Tony