как очистить запись на пины raspberry pi gpio

#raspberry-pi3 #gpio

#малина-pi3 #gpio

Вопрос:

У меня есть программа, написанная на C на Raspberry Pi 3. Я mmap /dev/gpiomem для доступа к регистрам GPIO непосредственно в пользовательском режиме. Вот моя функция для записи на выходные контакты:

 static uint32_t volatile *gpiopage; // initialized by mmap() of /dev/gpiomem  static uint32_t lastretries = 0;   void PhysLib::writegpio (uint32_t value)  {  uint32_t mask = 0xFFF000; // [11:00] input pins  // [23:12] output pins   // all the pins go through an inverter converting the 3.3V to 5V  gpiopage[GPIO_CLR0] = value;  gpiopage[GPIO_SET0] = ~ value;   // sometimes takes 1 or 2 retries to make sure signal gets out  uint32_t retries = 0;  while (true) {  uint32_t readback = ~ gpiopage[GPIO_LEV0];  uint32_t diff = (readback ^ value) amp; mask;  if (diff == 0) break;  if (   retries gt; 1000) {  fprintf (stderr, "PhysLib::writegpio: wrote X mask X, readback X diff Xn",  value, mask, readback, diff);  abort ();  }  }  if (lastretries lt; retries) {  lastretries = retries;  printf ("PhysLib::writegpio: retries %un", retries);  }  }  

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

Я совершенно уверен, что это происходит, потому что этот код является частью цикла:

 while (true) {  writegpio (0x800000); // set gpio pin 23  software timing loop for 1uS  writegpio (0); // clear gpio pin 23  software timing loop for 1uS  }  

Иногда временные интервалы Linux во время циклов синхронизации программного обеспечения на мне, и я получаю задержку более 1 МС, что нормально для этого проекта. Прежде чем я введу код, который зацикливается до тех пор, пока он не прочитает обновленный бит, иногда напряжение на выводе остается высоким дольше 1uS, а затем становится низким соответственно менее 1uS или наоборот, подразумевая, что для двух временных циклов в общей сложности задержка составляет 2uS, но обновление фактического вывода задерживается аппаратным обеспечением. После вставки корректирующего кода я всегда получаю по крайней мере 1 ед. высокого напряжения и 1 ед. низкого напряжения каждый раз через контур.

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

1. Вы пытаетесь выполнить задачу RT на не-RTO. Кроме того, вы делаете это в пользовательском пространстве. Несмотря на то, что /dev/gpiomem-один из самых уродливых интерфейсов, который вызывает проблемы. Для выполнения такого рода задач вам идеально нужен Zephyr RTOS. Но если вы хотите больше изучить Linux, сделайте его RT и переместите свой код в пространство ядра, используя таймеры с высоким разрешением вместо задержек.

2. Ну, я не думаю, что проблема в операционной системе. Поскольку я использую gpiomem для прямого доступа к регистрам GPIO, изменение операционной системы не изменит происходящее. Теперь я знаю, что на X86 есть MTRR, которые отключают кэширование в регистрах ввода-вывода с отображением памяти, я полагаю, что Linux с ARM не отключает или не может отключить кэширование для рейгстеров GPIO, вы знаете об этой возможности? Кстати, что уродливо в gpiomem, похоже, это именно то, что мне здесь нужно.