Как обрабатывать GPIO-подобные прерывания в пользовательском пространстве Linux - PullRequest
0 голосов
/ 16 мая 2019

Не уверен, должен ли я публиковать это здесь или нет, но я должен спросить.

Контекст:

  • Linux на встроенной платформе (процессор @ ~ 500 МГц)
  • Одна команда работает над программным обеспечением для одного пользователя
  • Одна команда работает над Linux + драйвер + uboot и т. Д.

Программное обеспечение должно обрабатывать GPIO, некоторые выводятся (пишут при необходимости), некоторые вводятся (читаются при необходимости для одних, предпочтительно как прерывания для других).

Это многопоточное приложение с ~ 10-15 потоками в политике планирования SCHED_FIFO.

Допустим, у меня есть модуль под названием WGPIO, который является оболочкой, обрабатывающей GPIO. (это разработано командой Linux между прочим. WGPIO все еще находится в пользовательском пространстве, но они могут разработать драйвер при необходимости)

Вот некоторый псевдо-код того, что разработано, как мы говорим.

gpio_state state = ON;
// IO_O is output. Set to ON, don't care if it's active_high or active_low btw
WGPIO_WriteOutput(IO_O,state);

// IO_I is input, read when needed
WGPIO_ReadInput(IO_I,&state);

// register callback when rising edge occurs on IO named IO_IT
WGPIO_SetCallback(IO_IT,EDGE_RISING,my_callback);
// Unmask to enable further IT-like processing
WGPIO_UnmaskIRQ(IO_IT);

Я должен быть в состоянии справиться с некоторыми изменениями GPIO за 5-10 мс.

Достаточно ли опроса какого-либо пользовательского пространства (тогда WGPIO будет иметь поток SCHED_FIFO) на нескольких FD, чтобы имитировать обработку, подобную прерыванию, в моем приложении? Это выглядит как самая простая идея.

Если вам нужна дополнительная информация, не стесняйтесь спрашивать. Заранее спасибо.

1 Ответ

2 голосов
/ 16 мая 2019

Из ядра gpio / sysgs.txt :

"value" ... reads as either 0 (low) or 1 (high). If the GPIO
  is configured as an output, this value may be written;
  any nonzero value is treated as high.

  If the pin can be configured as interrupt-generating interrupt
  and if it has been configured to generate interrupts (see the
  description of "edge"), you can poll(2) on that file and
  poll(2) will return whenever the interrupt was triggered. If
  you use poll(2), set the events POLLPRI and POLLERR. If you
  use select(2), set the file descriptor in exceptfds. After
  poll(2) returns, either lseek(2) to the beginning of the sysfs
  file and read the new value or close the file and re-open it
  to read the value.

"edge" ... reads as either "none", "rising", "falling", or
  "both". Write these strings to select the signal edge(s)
  that will make poll(2) on the "value" file return.

  This file exists only if the pin can be configured as an
  interrupt generating input pin.

Обычно предпочтительным способом настройки прерывания является /sys/class/gpio/gpioN/edge и poll(2) дляPOLLPRI | POLLERR (важно, что не ПОЛЛИН!) На /sys/class/gpio/gpioN/value.Если ваш процесс представляет собой некий процесс «в реальном времени», который должен обрабатывать события в режиме реального времени, подумайте об уменьшении его полезности.

Вы даже можете найти пример кода на github, который использует poll, напр. это репо .

...