ARM linux 用户空间 gpio 操作使用 mmap /dev/mem 方法(能够写入 GPIO 寄存器,但无法从中读取)
ARM linux userspace gpio operations using mmap /dev/mem approach (able to write to GPIO registers, but fail to read from them)
PHYTEC 内核版本 3.12.30-AM335x-PD15.1.1。
如果我使用/sys/class/gpio方式,我可以看到按钮输入引脚(AM3359的gpio103)值从0变为1。
在这个练习之后 http://elinux.org/EBC_Exercise_11b_gpio_via_mmap
并执行以下命令以使用 /dev/mem 方法读取 gpio 引脚:
`devmem2 0x481ae13c`
(gpio bank 3 的基数,即 0x481ae000 + 0x13c 数据输出偏移量)
无论按钮位置如何,我都会得到以下输出。
/dev/mem opened
Memory mapped at address 0xb6fd1000.
Read at address 0x481AE13C (0xb6fd113c): 0x00000000
还有下面给出的 c 程序,我设法使用 /dev/mem 切换 gpios;但是我无法成功阅读它们。
头文件中:
#define GPIO0_START_ADDRESS (0x44E07000)
#define GPIO1_START_ADDRESS (0x4804C000)
#define GPIO2_START_ADDRESS (0x481AC000)
#define GPIO3_START_ADDRESS (0x481AE000)
#define GPIO0_END_ADDRESS (0x44e09000)
#define GPIO1_END_ADDRESS (0x4804E000)
#define GPIO2_END_ADDRESS (0x481AE000)
#define GPIO3_END_ADDRESS (0x481B0000)
#define GPIO0_SIZE (GPIO0_END_ADDRESS - GPIO0_START_ADDRESS)
#define GPIO1_SIZE (GPIO1_END_ADDRESS - GPIO1_START_ADDRESS)
#define GPIO2_SIZE (GPIO2_END_ADDRESS - GPIO2_START_ADDRESS)
#define GPIO3_SIZE (GPIO3_END_ADDRESS - GPIO3_START_ADDRESS)
#define GPIO_SETDATAOUT (0x194)
#define GPIO_CLEARDATAOUT (0x190)
#define GPIO_DATAOUT (0x13c)
程序中某处:
int fd = open("/dev/mem", O_RDWR);
//int fd = open("/dev/mem", O_RDWR|O_SYNC);
gpio0_address = mmap(0, GPIO0_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO0_START_ADDRESS);
gpio1_address = mmap(0, GPIO1_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO1_START_ADDRESS);
gpio2_address = mmap(0, GPIO2_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO2_START_ADDRESS);
gpio3_address = mmap(0, GPIO3_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO3_START_ADDRESS);
if(gpio0_address == MAP_FAILED){ printf("unable to map GPIO0 bank.\n"); }
if(gpio1_address == MAP_FAILED){ printf("unable to map GPIO1 bank.\n"); }
if(gpio2_address == MAP_FAILED){ printf("unable to map GPIO2 bank.\n"); }
if(gpio3_address == MAP_FAILED){ printf("unable to map GPIO3 bank.\n"); }
gpio0_dataout_address = gpio0_address + GPIO_DATAOUT;
gpio0_setdataout_address = gpio0_address + GPIO_SETDATAOUT;
gpio0_cleardataout_address = gpio0_address + GPIO_CLEARDATAOUT;
gpio1_dataout_address = gpio1_address + GPIO_DATAOUT;
gpio1_setdataout_address = gpio1_address + GPIO_SETDATAOUT;
gpio1_cleardataout_address = gpio1_address + GPIO_CLEARDATAOUT;
gpio2_dataout_address = gpio2_address + GPIO_DATAOUT;
gpio2_setdataout_address = gpio2_address + GPIO_SETDATAOUT;
gpio2_cleardataout_address = gpio2_address + GPIO_CLEARDATAOUT;
gpio3_dataout_address = gpio3_address + GPIO_DATAOUT;
gpio3_setdataout_address = gpio3_address + GPIO_SETDATAOUT;
gpio3_cleardataout_address = gpio3_address + GPIO_CLEARDATAOUT;
read_GPIO_bank_memory(3, &GPIO3_bank_memory);
读取函数:
void read_GPIO_bank_memory(int bank, four_bytes* gpio_bank_dataout)
{
switch(bank)
{
case 0:
gpio_bank_dataout->ALL = *gpio0_dataout_address;
break;
case 1:
gpio_bank_dataout->ALL = *gpio1_dataout_address;
break;
case 2:
gpio_bank_dataout->ALL = *gpio2_dataout_address;
break;
case 3:
gpio_bank_dataout->ALL = *gpio3_dataout_address;
break;
}
}
您应该使用 GPIO_DATAIN 寄存器(偏移量 = 138h)从 GPIO 引脚读取,而不是 GPIO_DATAOUT。
PHYTEC 内核版本 3.12.30-AM335x-PD15.1.1。
如果我使用/sys/class/gpio方式,我可以看到按钮输入引脚(AM3359的gpio103)值从0变为1。
在这个练习之后 http://elinux.org/EBC_Exercise_11b_gpio_via_mmap 并执行以下命令以使用 /dev/mem 方法读取 gpio 引脚:
`devmem2 0x481ae13c`
(gpio bank 3 的基数,即 0x481ae000 + 0x13c 数据输出偏移量)
无论按钮位置如何,我都会得到以下输出。
/dev/mem opened
Memory mapped at address 0xb6fd1000.
Read at address 0x481AE13C (0xb6fd113c): 0x00000000
还有下面给出的 c 程序,我设法使用 /dev/mem 切换 gpios;但是我无法成功阅读它们。
头文件中:
#define GPIO0_START_ADDRESS (0x44E07000)
#define GPIO1_START_ADDRESS (0x4804C000)
#define GPIO2_START_ADDRESS (0x481AC000)
#define GPIO3_START_ADDRESS (0x481AE000)
#define GPIO0_END_ADDRESS (0x44e09000)
#define GPIO1_END_ADDRESS (0x4804E000)
#define GPIO2_END_ADDRESS (0x481AE000)
#define GPIO3_END_ADDRESS (0x481B0000)
#define GPIO0_SIZE (GPIO0_END_ADDRESS - GPIO0_START_ADDRESS)
#define GPIO1_SIZE (GPIO1_END_ADDRESS - GPIO1_START_ADDRESS)
#define GPIO2_SIZE (GPIO2_END_ADDRESS - GPIO2_START_ADDRESS)
#define GPIO3_SIZE (GPIO3_END_ADDRESS - GPIO3_START_ADDRESS)
#define GPIO_SETDATAOUT (0x194)
#define GPIO_CLEARDATAOUT (0x190)
#define GPIO_DATAOUT (0x13c)
程序中某处:
int fd = open("/dev/mem", O_RDWR);
//int fd = open("/dev/mem", O_RDWR|O_SYNC);
gpio0_address = mmap(0, GPIO0_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO0_START_ADDRESS);
gpio1_address = mmap(0, GPIO1_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO1_START_ADDRESS);
gpio2_address = mmap(0, GPIO2_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO2_START_ADDRESS);
gpio3_address = mmap(0, GPIO3_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO3_START_ADDRESS);
if(gpio0_address == MAP_FAILED){ printf("unable to map GPIO0 bank.\n"); }
if(gpio1_address == MAP_FAILED){ printf("unable to map GPIO1 bank.\n"); }
if(gpio2_address == MAP_FAILED){ printf("unable to map GPIO2 bank.\n"); }
if(gpio3_address == MAP_FAILED){ printf("unable to map GPIO3 bank.\n"); }
gpio0_dataout_address = gpio0_address + GPIO_DATAOUT;
gpio0_setdataout_address = gpio0_address + GPIO_SETDATAOUT;
gpio0_cleardataout_address = gpio0_address + GPIO_CLEARDATAOUT;
gpio1_dataout_address = gpio1_address + GPIO_DATAOUT;
gpio1_setdataout_address = gpio1_address + GPIO_SETDATAOUT;
gpio1_cleardataout_address = gpio1_address + GPIO_CLEARDATAOUT;
gpio2_dataout_address = gpio2_address + GPIO_DATAOUT;
gpio2_setdataout_address = gpio2_address + GPIO_SETDATAOUT;
gpio2_cleardataout_address = gpio2_address + GPIO_CLEARDATAOUT;
gpio3_dataout_address = gpio3_address + GPIO_DATAOUT;
gpio3_setdataout_address = gpio3_address + GPIO_SETDATAOUT;
gpio3_cleardataout_address = gpio3_address + GPIO_CLEARDATAOUT;
read_GPIO_bank_memory(3, &GPIO3_bank_memory);
读取函数:
void read_GPIO_bank_memory(int bank, four_bytes* gpio_bank_dataout)
{
switch(bank)
{
case 0:
gpio_bank_dataout->ALL = *gpio0_dataout_address;
break;
case 1:
gpio_bank_dataout->ALL = *gpio1_dataout_address;
break;
case 2:
gpio_bank_dataout->ALL = *gpio2_dataout_address;
break;
case 3:
gpio_bank_dataout->ALL = *gpio3_dataout_address;
break;
}
}
您应该使用 GPIO_DATAIN 寄存器(偏移量 = 138h)从 GPIO 引脚读取,而不是 GPIO_DATAOUT。