使用 mmap/dev/mem 方法的 ARM linux 用户空间 gpio 操作(能够写入 GPIO 寄存器,但无法从中读取) [英] ARM linux userspace gpio operations using mmap /dev/mem approach (able to write to GPIO registers, but fail to read from them)

查看:33
本文介绍了使用 mmap/dev/mem 方法的 ARM linux 用户空间 gpio 操作(能够写入 GPIO 寄存器,但无法从中读取)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

PHYTEC 的内核版本 3.12.30-AM335x-PD15.1.1.

Kernel version 3.12.30-AM335x-PD15.1.1 by PHYTEC.

如果我使用/sys/class/gpio方式,可以看到按键输入引脚(AM3359的gpio103)的值从0变为1.

If I use the /sys/class/gpio way, I can see that the button input pin (gpio103 of AM3359) value changes from 0 to 1.

按照本练习http://elinux.org/EBC_Exercise_11b_gpio_via_mmap并执行以下命令来读取 gpio 引脚 usig/dev/mem 方法:

Following the this exercise http://elinux.org/EBC_Exercise_11b_gpio_via_mmap and executing the below command for reading gpio pins usig /dev/mem approach:

`devmem2 0x481ae13c` 

(gpio bank 3 的基址,即 0x481ae000 + 0x13c 数据输出偏移)

(base of gpio bank 3 which is 0x481ae000 + 0x13c dataout offset)

无论按钮位置如何,我都会得到以下输出.

I get the below output regardless of button position.

/dev/mem opened
Memory mapped at address 0xb6fd1000.
Read at address  0x481AE13C (0xb6fd113c): 0x00000000

还有下面给出的 c 程序,我设法使用/dev/mem 切换 gpios;但是我无法成功阅读它们.

Also with the c program given below I managed to toggle gpios using /dev/mem; however I could not read them succesfuly.

在头文件中:

#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 Register (offset = 138h) 从 GPIO pin 读取数据,而不是 GPIO_DATAOUT.

You should use GPIO_DATAIN Register (offset = 138h) to read from GPIO pin, not GPIO_DATAOUT.

这篇关于使用 mmap/dev/mem 方法的 ARM linux 用户空间 gpio 操作(能够写入 GPIO 寄存器,但无法从中读取)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆