- basically it is trying to read the GPIO_REVISION at offset 0 at the start of each GPIO bank. The expected value returned should be 0x50600801 - but a "Bus Error" is returned for GPIO banks 2 and 3.// c code to test access to the /dev/mem file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#define GPIO_BANK_0 0x44E07000
#define GPIO_BANK_1 0x4804C000
#define GPIO_BANK_2 0x481AC000
#define GPIO_BANK_3 0x481AE000
int gpio_mmap_test(int gpioBank, int sizeToFetch);
int main()
{
gpio_mmap_test(GPIO_BANK_0, 0xfff);
gpio_mmap_test(GPIO_BANK_1, 0xfff);
gpio_mmap_test(GPIO_BANK_2, 0xfff);
gpio_mmap_test(GPIO_BANK_3, 0xfff);
return 0;
}
int gpio_mmap_test(int gpioBank, int sizeToFetch)
{
int gpio_fd2 = open("/dev/mem", O_RDWR | O_SYNC);
if (gpio_fd2 < 0)
{
printf("Could not open GPIO memory fd\n");
return 0;
}
volatile ulong *gpio;
gpio = (ulong*) mmap(NULL, sizeToFetch, PROT_READ | PROT_WRITE, MAP_SHARED, gpio_fd2, gpioBank);
if (gpio == MAP_FAILED)
{
printf ("GPIO Mapping failed\n");
close(gpio_fd2);
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);
close(gpio_fd2);
}
Check their functional clocks are enabled in the CPM_PER_GPIO(2/3)_CLKCTRL registers.
gpio0_dbclk_mux_ck {
#clock-cells = <0x0>;
compatible = "ti,mux-clock";
clocks = <0x14 0x15 0x12>;
reg = <0x53c>;
linux,phandle = <0x18>;
phandle = <0x18>;
};
gpio0_dbclk {
#clock-cells = <0x0>;
compatible = "ti,gate-clock";
clocks = <0x18>;
ti,bit-shift = <0x12>;
reg = <0x408>;
};
gpio1_dbclk {
#clock-cells = <0x0>;
compatible = "ti,gate-clock";
clocks = <0x12>;
ti,bit-shift = <0x12>;
reg = <0xac>;
};
gpio2_dbclk {
#clock-cells = <0x0>;
compatible = "ti,gate-clock";
clocks = <0x12>;
ti,bit-shift = <0x12>;
reg = <0xb0>;
};
gpio3_dbclk {
#clock-cells = <0x0>;
compatible = "ti,gate-clock";
clocks = <0x12>;
ti,bit-shift = <0x12>;
reg = <0xb4>;
};
Enter code here...
uint32_t *clock_gpio3;
clock_gpio3 = (uint32_t *) mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x44E00000);
clock_gpio3[0x2d] |= 0x40002; // 2d is b4 divide by 4 because it is a byte offset
I have found that accessing GPIOs via mmap() of /dev/mem works without accessing additional control register settings if you export one GPIO pin in each bank so that the GPIO kernel driver "unlocks" each bank and wakes it up. GPIO1 is awake by default, but you can get the other GPIO0, GPIO2, and GPIO3 working via the following commands:echo 5 > /sys/class/gpio/exportecho 65 > /sys/class/gpio/exportecho 105 > /sys/class/gpio/exportI do the same with Android in the init.{ro.hardware}.rc file:write /sys/class/gpio/export 5write /sys/class/gpio/export 65write /sys/class/gpio/export 105As for running those commands under Linux, I usually place the commands to export the pins into a shell script that also launches the application that uses the GPIOs. Since you have to be root to mmap() the pages with GPIO control registers, you can run the shell script via sudo and have the script export the pins and then launch your binary. You could also place the commands in the /etc/rc.local startup script or the like, if you want.
Andrew
On Wednesday, October 29, 2014 1:49:16 PM UTC-4, Nic Cyn wrote:Success!!! Thank you very much! - this works. I really appreciate your advice. I absolutely would not have got this sorted without it.
I am going to write up a summary and post it on this thread so that anybody else that runs into this issue can find it. However I do have a couple more questions - if you (or anybody) have the time to provide any insights you might have.
- The CM_PER_GPIO1_CLKCTRL at 0x44e00000[0xac] for Bank GPIO1 is already set, yet the equivalents for GPIO2 and GPIO3 are not. Any idea how CM_PER_GPIO1_CLKCTRL got set?
- Are there any Device Tree settings that you know of that can set the CLKCTRLs for GPIO2 and GPIO3 at boot up?
- There is no CM_PER_GPIO0_CLKCTRL for the GPIO0 bank. I gather GPIO0 is something of a special case due to the wakeup capabilities it contains. Is the GPIO0 bank always enabled? Any thoughts on why GPIO0 is not there?
- Your example OR'ed with 0x40002 - presumably to place it in standby - rather than fully active. I am curious - under what circumstances would you want to put a CLKCTRL in standby mode?
- Do you have any idea why /dev/mem would fail to access GPIO3 if the CLKCTRL was not set and yet SYSFS can read the GPIO states on GPIO3? Obviously SYSFS is a device driver and does not need to hit /dev/mem but even so it appears the CLKCTRL is used to transfer the state off the physical pin and into the GPIO bank so why would SYSFS work if the clock is disabled.
- You must have run into this issue yourself. How on earth did you figure out that it was the CLKCTRL registers? The reason I ask I I would like to know how to diagnose this sort of thing myself and it all seems such a mystery at the moment.
Once again.... many thanks.
On Tuesday, 28 October 2014 21:28:19 UTC, bris...@yahoo.com.au wrote:This is out of a program I use -
Enter code here...
uint32_t *clock_gpio3;
clock_gpio3 = (uint32_t *) mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x44E00000);
clock_gpio3[0x2d] |= 0x40002; // 2d is b4 divide by 4 because it is a byte offset
--
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 beagleboard...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Except that running those commands as root at startup( init scripts ) has no detrimental effect.
echo 5 > /sys/class/gpio/exportecho 65 > /sys/class/gpio/exportecho 105 > /sys/class/gpio/exportI do the same with Android in the init.{ro.hardware}.rc file:write /sys/class/gpio/export 5write /sys/class/gpio/export 65write /sys/class/gpio/export 105
As for running those commands under Linux, I usually place the commands to export the pins into a shell script that also launches the application that uses the GPIOs. Since you have to be root to mmap() the pages with GPIO control registers, you can run the shell script via sudo and have the script export the pins and then launch your binary. You could also place the commands in the /etc/rc.local startup script or the like, if you want.
echo 5 > /sys/class/gpio/exportecho 65 > /sys/class/gpio/exportecho 105 > /sys/class/gpio/exportI do the same with Android in the init.{ro.hardware}.rc file:write /sys/class/gpio/export 5write /sys/class/gpio/export 65write /sys/class/gpio/export 105As for running those commands under Linux, I usually place the commands to export the pins into a shell script that also launches the application that uses the GPIOs. Since you have to be root to mmap() the pages with GPIO control registers, you can run the shell script via sudo and have the script export the pins and then launch your binary. You could also place the commands in the /etc/rc.local startup script or the like, if you want.Read carefully.
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);
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;