Как читать и записывать значения GPIO с помощью inb() и outb()

У меня есть атомная плата с Fintek F75111 GPIO. У меня есть информация от производителя, что адрес SMbus для доступа к чипу 06EH.

Я пытаюсь читать и записывать значения в GPIO в Linux. У меня есть образец программы от производителя, написанный для Windows, который выглядит так.

#include “math.h”
#include “stdio.h”
#include “dos.h”
void main(void){
    int SMB_PORT_AD = 0x400;
    int SMB_DEVICE_ADD = 0x6E;
    /*75111R’s Add=6eh */
    //programming DIO as output //0:input 1:Output
    /* Index 10, GPIO1x Output pin control */
    SMB_Byte_WRITE(SMB_PORT_AD,SMB_DEVICE_ADD,0x10,0xff); delay(10);
    //programming DIO default LOW
    /* Index 11, GPIO1x Output Data value */
    SMB_Byte_WRITE(SMB_PORT_AD,SMB_DEVICE_ADD,0x11,0x00); delay(10);
}


unsigned char SMB_Byte_READ (int SMPORT, int DeviceID, int REG_INDEX)
{
    unsigned char SMB_R;
    outportb(SMPORT+02, 0x00); /* clear */ 
    outportb(SMPORT+00, 0xff); /* clear */ 
    delay(10);
    outportb(SMPORT+04, DeviceID+1); /* clear */ 
    outportb(SMPORT+03, REG_INDEX); /* clear */ 
    outportb(SMPORT+02, 0x48); /* read_byte */ 
    delay(10);
    SMB_R= inportb(SMPORT+05);
    return SMB_R;
}

void SMB_Byte_WRITE(int SMPORT, int DeviceID, int REG_INDEX, int REG_DATA)
{
    outportb(SMPORT+02, 0x00); /* clear */ 
    outportb(SMPORT+00, 0xff); /* clear */
    delay(10);
    outportb(SMPORT+04, DeviceID); /* clear */ 
    outportb(SMPORT+03, REG_INDEX); /* clear */
    outportb(SMPORT+05, REG_DATA); /* read_byte */
    outportb(SMPORT+02, 0x48); /* read_byte */
    delay(10);
}

Я попытался перевести это в совместимые с Linux функции inb() и outb(), и вот что у меня получилось.

#include <stdio.h>
#include <sys/io.h>

unsigned int gpio_read(int PORT, int DEVICE, int REG_INDEX){
    unsigned int RESPONSE;

    outb(0x00, PORT+02);
    outb(0xff, PORT+00);
    usleep(100);
    outb(DEVICE+1, PORT+04);
    outb(REG_INDEX, PORT+03);
    outb(0x48, PORT+02);
    usleep(100);
    RESPONSE = inb(PORT+05);
    return RESPONSE;
}

unsigned int gpio_write(int PORT, int DEVICE, int REG_INDEX, int REG_DATA){
    outb(0x00, PORT+02);
    outb(0xff, PORT+00);
    usleep(100);
    outb(DEVICE, PORT+04);
    outb(REG_INDEX, PORT+03);
    outb(DATA, PORT+05);
    outb(0x48, PORT+02);
    usleep(100);

}

void main() {
    int PORT = 0x400;
    int DEVICE = 0x6E;
    unsigned int RESPONSE;

    // Ask access to port from kernel
    ioperm(0x400, 100, 1);

    // GPIO1x set to input (0xff is output)
    gpio_write(PORT, DEVICE, 0x10, 0x00);

        RESPONSE = gpio_read(PORT, DEVICE, 1);
        printf("\n %u \n", RESPONSE);
}

Индекс GPIO1X 0x10 используется для установки того, являются ли 8 портов GPIO, подключенных к GPIO1x, выходными или входными портами.

Выходные значения для GPIO устанавливаются с использованием индекса 0x11, и если порты работают как входные порты, то для чтения входных значений используется индекс 0x12.

Проблема в том, что я не знаю, правильно ли это и как читать значения (почему функция чтения что-то выводит перед чтением?!?)

Когда я бегу:

RESPONSE = gpio_read(PORT, DEVICE, X);

Изменяя X со значениями от 1 до 9, я получаю это как вывод: 0 8 8 0 0 0 0 0 0

Меня смущает цифра 8...


person Goran Jurić    schedule 11.09.2012    source источник
comment
У вас в итоге получилось? Я работаю над аналогичным проектом, используя плату Aaeon Gene-CVO5. К сожалению, их поддержка Linux не так сильна. Плата использует Intel 82801G в качестве мастера i2c. Используя программу обнаружения датчиков lm-sensors, я не вижу F75111 в списке.   -  person user2058980    schedule 10.02.2013


Ответы (1)


Вместо того, чтобы писать напрямую в порт SMBus, я бы предпочел использовать библиотеки i2c. I2C (и SMBUS) используют два вывода порта, один для часов и один для данных. Данные передаются и принимаются по краям часов (синхронно). Читая код, я не могу ясно видеть, к каким из них (часам или данным) осуществляется доступ и когда.

Для начала я бы использовал i2ctools в качестве отправной точки (проверьте этот сайт: http://elinux.org/Interfacing_with_I2C_Devices). Этот инструмент поможет вам найти устройства, подключенные к шине I2C вашего микропроцессора, а также выполнить базовую коммуникацию.

Надеюсь, поможет...

person Javier Uria    schedule 12.10.2012