Операции gpio в пользовательском пространстве ARM linux с использованием подхода mmap / dev / mem (возможность записи в регистры GPIO, но чтение из них не выполняется)

#c #linux #arm #mmap #gpio

#c #linux #arm #mmap #gpio

Вопрос:

Версия ядра 3.12.30-AM335x-PD15.1.1 от PHYTEC.

Если я использую способ /sys/ class/ gpio, я вижу, что значение ввода PIN-кода кнопки (gpio103 из AM3359) изменяется с 0 на 1.

После выполнения этого упражнения http://elinux.org/EBC_Exercise_11b_gpio_via_mmap и выполнение приведенной ниже команды для чтения gpio выводит usig / dev / mem подход:

 `devmem2 0x481ae13c` 
  

(база gpio bank 3, которая равна 0x481ae000 0x13c смещение вывода данных)

Я получаю приведенный ниже результат независимо от положения кнопки.

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

Также с помощью программы c, приведенной ниже, мне удалось переключить gpio с помощью /dev/mem; однако я не смог их успешно прочитать.

в заголовочном файле:

 #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, amp;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;
        }
    }
  

Комментарии:

1. Неудивительно, что регистры вывода данных предназначены для вывода . Если вы хотите прочитать входные значения, используйте регистры ввода данных. В названии есть подсказка…

2. Спасибо, что указали, я знал, что это должно быть что-то довольно глупое, но я был потерян.

Ответ №1:

Для чтения из вывода GPIO следует использовать регистр GPIO_DATAIN (смещение = 138h), а не GPIO_DATAOUT.