As mentioned above. Here is a summary of the issue and its resolution. I am 
posting it here so that anybody else that runs into this might be able to 
find it with a search.

BASIC PROBLEM: Using /dev/mem with a mmap() call to access the GPIOs in 
banks 2 and 3 fail with a bus error. Identical access to the GPIO's in 
banks 0 and 1 works just fine.

SOLUTION: Access to the GPIO banks 2 and 3 fails because the clocks 
CM_PER_GPIO2_CLKCTRL and CM_PER_GPIO3_CLKCTRL are not enabled. These can 
readily be enabled by accessing memory location 0x44e00000 (see the TRM) 
and turning them on. If you do that, access to the GPIO2 and 3 at locations 
0x481AC000 and 0x481AE000 will be successful.

EXPLANATION and EXAMPLES

Example C code for memory mapped access to the GPIOs is below – it assumes 
we wish to access GPIO_BANK_1

   int fd = open("/dev/mem", O_RDWR | O_SYNC); 
   if (fd < 0) 
   { 
      printf("Could not open GPIO memory fd\n"); 
      return 0; 
   } 
   
   volatile ulong *gpio; 
   int gpioBank = 0x4804C000;
   int sizeToFetch =0xfff;

   gpio = (ulong*) mmap(NULL, sizeToFetch, PROT_READ | PROT_WRITE, 
MAP_SHARED, fd, gpioBank); 
   if (gpio == MAP_FAILED) 
   { 
      printf ("GPIO Mapping failed\n"); 
      close(fd); 
      return 0; 
   } 
   //  offset 0 is the GPIO_REVISION field 
   //  expected value is 0x50600801 
   int gpioRevision = gpio[0]; 
   printf("bank %04x, gpioRevision = %04x\n", gpioBank, gpioRevision);

   munmap((void*)gpio,sizeToFetch); 
   close(fd); 


Accessing GPIO_BANK_2 or GPIO_BANK_2 will, in most circumstances, result in 
a failure with a “Bus error” message on the call to

int gpioRevision = gpio[0];

Everything else works fine, the /dev/mem file opens and the mmap() call is 
successful but access to any value in the mapped meory will fail. It seems 
that this is due to the clock which is used to shift the physical pin state 
into the GPIO_BANK bit is not enabled by default. 

One way to get around this is to note that using SYSFS to export any GPIO 
in that bank (echo 105 > /sys/class/gpio/export) will enable the clock on 
that BANK and all subsequent accesses via mmap() will succeed.

The other way is to enable the clock yourself. This is done by writing to a 
memory location and hence requires yet another mmap() on /dev/mem. The 
relevant memory location is 0x44e00000 and the offset of interest is 
entitled CM_PER_GPIO?_CLKCTRL (where the ? Is 1, 2, or 3 for GPIO_BANK_1,2 
or 3).  If you wish to look this up in the TRM, search for 
CM_PER_GPIO2_CLKCTRL – it is in Section 8 – which deals with the Power 
Clock and Reset Managment. Here is some sample code that will properly set 
the  CM_PER_GPIO2_CLKCTRL register.

   uint32_t *clock_gpio2; 
  clock_gpio2 = (uint32_t *) mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, 
MAP_SHARED, fd, 0x44E00000); 
  // 0xb0 is CM_PER_GPIO2_CLKCTRL as given in the TRM, use 0xb4 for GPIO_3 
(see the TRM)
  int offsetInMemory = 0xb0;
  // get the value, we divide by 4 because it is a byte offset
  int memValue = clock_gpio2[(offsetInMemory/4)]; 
  // print it – it will probably be 0x030000 if the clock has never been 
enabled
  printf("Value = %04x\n", memValue); 
  // now set it, this enables the memory
  clock_gpio2[(offsetInMemory/4)] = 0x02; 


Once the clock has been set as above, the previous C code will be able to 
access the  GPIO_BANK via a statement like.

int gpioRevision = gpio[0];

On my system  GPIO_BANK_1 was already enabled, but  GPIO_BANK_2 and  
GPIO_BANK_3 needed to be enabled. 
  

-- 
For more options, visit http://beagleboard.org/discuss
--- 
You received this message because you are subscribed to the Google Groups 
"BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to