Программирование выводов GPIO на чипсете FINTEK F81866A - PullRequest
0 голосов
/ 05 октября 2018

У меня есть промышленный ПК Cincoze DE-1000 с чипсетом Fintek F81866A .Мне нужно управлять выводами DIO, чтобы прочитать вход с физической кнопки и включить / выключить светодиод.У меня есть опыт программирования на C ++, но не на низком / аппаратном уровне.

В документации, прилагаемой к ПК, есть следующий код C:

#define AddrPort 0x4E
#define DataPort 0x4F

//<Enter the Extended Function Mode>
WriteByte(AddrPort, 0x87)
WriteByte(AddrPort, 0x87) //Must write twice to entering Extended mode

//<Select Logic Device>
WriteByte(AddrPort, 0x07)
WriteByte(DataPort, 0x06)
//Select logic device 06h

//<Input Mode Selection> //Set GP74 to GP77 input mode
WriteByte(AddrPort, 0x80) //Select configuration register 80h
WriteByte(DataPort, 0x0X)
//Set (bit 4~7) = 0 to select GP 74~77 as Input mode.

//<input Value>
WriteByte(AddrPort, 0x82) // Select configuration register 82h
ReadByte(DataPort, Value) // Read bit 4~7(0xFx)= GP74 ~77 as High.

//<Leave the Extended Function Mode>
WriteByte(AddrPort, 0xAA)

Насколько я понял,Приведенный выше код должен читать значение четырех входных ПИН-кодов (поэтому он должен читать 1 для каждого ПИН-кода), но я действительно изо всех сил пытаюсь понять, как он на самом деле работает.Я понял логику (выбор адреса и чтение / запись в него шестнадцатеричного значения), но я не могу понять, что это за инструкции C WriteByte() и ReadByte().Кроме того, я не понимаю, откуда взято Value в строке ReadByte(DataPort, Value).Он должен читать 4 PIN-кода все вместе, поэтому он должен быть своего рода «байтовым» типом, и он должен содержать 1 в его битах 4-7, но, опять же, я не могу действительно понять значение этой строки.

Я нашел ответ для аналогичного чипа , но он не помог мне понять.

Пожалуйста, посоветуйте мне или укажите какую-нибудь соответствующую документацию.

Ответы [ 2 ]

0 голосов
/ 06 октября 2018

Этот чип выглядит как довольно типичный Super I / O контроллер , который в основном является центром, где все «медленные» периферийные устройства объединены в один чипсет.

В Coreboot есть вики-страница, на которой рассказывается о том, как получить доступ к супер I / O .


В архитектуре ПК Port I / O выполняется с использованием специальных инструкций процессора, а именно in и out.Это привилегированные инструкции, которые можно использовать только из драйвера режима ядра (кольцо 0) или процесса пользовательского пространства, которому были предоставлены привилегии ввода / вывода.

К счастью, это легко сделать в Linux.Посетите справочную страницу для outb и друзей .

. Вы используете ioperm (2) или, альтернативно, iopl (2), чтобы сообщить ядру разрешить приложению пространства пользователяполучить доступ к портам ввода / вывода, о которых идет речь.Невыполнение этого условия приведет к тому, что приложение получит ошибку сегментации.

Таким образом, мы можем адаптировать вашу функцию в среде Linux, например:

/* Untested: Use at your own risk! */
#include <sys/io.h>
#include <stdio.h>

#define ReadByte(port)          inb(port)
#define WriteByte(port, val)    outb(val, port)

int main(void)
{
    if (iopl(3) < 0) {
        fprintf(stderr, "Failed to get I/O privileges (are you root?)\n");
        return 2;
    }


    /* Your code using ReadByte / WriteByte here */
}

Предупреждение

Вы должны быть очень осторожны при использовании этого метода для непосредственного общения с Super IO, потому что ваша операционная система почти наверняка имеет драйверы устройств, которые также общаются с чипом.

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

Ядро Linux предоставляет GPIO доступ по крайней мере к некоторому Super I /O устройства;должно быть просто перенести один из них на вашу платформу.См. этот запрос на выборку для чипсета IT87xx .

0 голосов
/ 06 октября 2018

WriteByte() и ReadByte() не являются частью языка C.Судя по всему, это функции, предназначенные для использования в качестве заполнителей для какой-либо формы системного вызова для порта ввода-вывода ядра ОС (а не для макросов, выполняющих ввод-вывод в память напрямую, как в предыдущей версии этого ответа).

прототипы для функций будут выглядеть примерно так:

#include <stdint.h>
void WriteByte(unsigned port, uint8_t value);
void ReadByte(unsigned port, uint8_t *value);

Таким образом, переменная Value будет указателем на 8-битное целое число без знака (unsigned char также может использоваться), что-то вроде:

uint8_t realValue;
uint8_t *Value = &realValue;

Конечно, было бы гораздо разумнее иметь Value просто быть uint8_t и иметь ReadByte(DataPort, &Value).Но тогда в примере кода также нет точек с запятой, поэтому, вероятно, никогда не было ничего, что действительно выполнялось.В любом случае, именно так Value будет содержать данные, которые вы ищете.

Я также нашел здесь больше документации о регистрах - https://www.electronicsdatasheets.com/download/534cf560e34e2406135f469d.pdf?format=pdf

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

...