Может ли малина Pi надежно бить бит 9600 бод-сериала и есть ли пример кода?

Мне интересно, насколько возможно использовать битбинг, чтобы управлять серийным номером 9600 бод через контакты GPIO на Малиновой Пи.

Очевидно, что Linux не очень хорошая платформа для битбинга, так как существует большое количество драйверов и других прерываний, которые могут блокировать процессор в течение длительных периодов времени (1-10 мс). Однако в последнее время ситуация улучшилась, и в ядрах теперь разрешено некоторое предварительное упреждение. Я также подозреваю, что исправленное ядро ​​в реальном времени можно легко использовать на малине Pi, и подключенное оборудование и драйверы могут быть выбраны тщательно.

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

Итак, мои вопросы:

  • Может ли пользовательское программное обеспечение надежно бить скорость 9600 бод?
  • Требуется ли исправление ядра в реальном времени?
  • Сколько ошибок я должен ожидать в целом?

Кроме того, есть ли какой-либо пример кода, выполняющий серийный номер через битбинг GPIO? Я знаю Arduino SoftSerial, но это все.

На всякий случай, чтобы ограничить вопрос: это не стандартный последовательный интерфейс, а UART из Raspberry Pi уже используется для другой последовательной связи. Я не желаю ответов, которые предлагают внешние аппаратные средства (такие как Gertboard или Arduino), и ответы, которые зависят от UART.

27 голосов | спросил Nakedible 24 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowMon, 24 Sep 2012 20:52:25 +0400 2012, 20:52:25

3 ответа


13

Я, наконец, решил это, но довольно неортодоксальным способом. Я отказался от бит-стука как слишком ненадежный и попытался найти другие решения, которые позволили бы мне одно и то же, не добавляя больше аппаратного обеспечения. Я рассматривал возможность написания драйвера ядра, который вызвал бы прерывание в GPIO, а затем перенастроил бы штырь для SPI и использовал SPI для чтения всего байта данных, но потом я получил более полную идею.

Я использую SPI для отбора строк в 20 раз по скорости передачи. Я полностью игнорирую выводы SCLK и SS, подключаю линию RX к линии MISO и TX в MOSI. Это дает мне (1-битовое) осциллоскопическое представление в линии RX и четко видит биты, передаваемые в последовательной линии:

00 00 00 00 00 00 
00 00 00 00 01 FF 
FF FF FF FF 00 00 
01 FF FF FF FF FF 
FF FF E0 00 00 00 
00 00 07 FF FF FF 
FF FF 

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

Причина, по которой это работает лучше, чем бит-биение, заключается в том, что SPI имеет свои собственные часы, которые не замерзают с ядром, а строки отправки и получения SPI имеют 16-байтовый FIFO для передачи, которые также не зависят от зависания ядра. Для 9600 бод я использую часы SPI 250 кГц, а это значит, что я могу спать даже миллисекунду между заполнением и истощением FIFO без ошибок передачи. Однако, чтобы ошибиться в безопасности, я использую 300 мкс спать. Я кратко протестировал, как далеко я могу продвигать это, и по крайней мере 2MHz SPI-часы все еще пригодны для использования, поэтому это решение масштабируется и с более высокими скоростями передачи.

Одна уродливая часть этого решения заключается в том, что драйвер SPI ядра не поддерживает такую ​​передачу потокового бита. Это означает, что я не могу этого сделать, написав свой собственный модуль ядра с помощью драйвера SPI ядра, и я также не могу этого сделать, используя /dev/sdidev0.0 на земле пользователя. Однако на Raspberry Pi SPI и другие периферийные устройства доступны непосредственно из userland с помощью mmap (): n /dev /mem, полностью обходя контроль ядра. Я не очень доволен этим, но он отлично работает, и это дает дополнительную выгоду, что ошибки сегментации в пользовательском пространстве не могут привести к крушению ядра (если случайно не возиться с другими периферийными устройствами). Что касается использования ЦП, то сон на 300 мкс кажутся мне примерно 7% использования ЦП, но мой код очень неоптимальный. Увеличение продолжительности сна, очевидно, снижает потребление ЦП.

Изменить: Забыл отметить, я использовал красивую библиотеку bcm2835 для управления SPI из пользовательского пространства, расширяя при необходимости.

Итак, подведем итог: Я могу надежно передавать и получать по серийному каналу 9600 бод целиком из пользовательской сети, напрямую используя чип SPI через /dev /mem на частоте 250 кГц на малиновом Pi.

ответил Nakedible 29 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowSat, 29 Sep 2012 12:40:17 +0400 2012, 12:40:17
8

Казалось бы, по крайней мере, без патчей реального времени (CONFIG_PREEMPT_RT), Raspberry Pi не может надежно бить 9600 бод-серий.

Я использовал простой тестер задержки, который оптимально оптимизировал все операции со стороны Linux (sched_fifo, приоритет 99, cpu_dma_latench 0us, mlockall). Я пробовал спать за 100 мкс (примерно 9600 бод) и проверял перерасход латентности на спокойной системе в течение 2 минут. Результаты:

Мин: 12 мкс Среднее: 24 мкс Макс.: 282 мкс

Это казалось общим результатом. Максимум варьировался в более медленных измерениях между 100 мкс и 300 мкс. Я также проверил распределение, и кажется, что подавляющее большинство находится в диапазоне 24 мкс. Там всего несколько, которые выше 50 мкс, но почти всегда есть некоторые. Есть также иногда огромные задержки, например 4000 мкс, но они достаточно необычны, чтобы их можно было игнорировать, по крайней мере пока.

Я предполагаю, что максимальные задержки должны быть ниже 50 мкс для 9600 бод, чтобы не получить ошибок, и любая латентность более 100 мкс приводит к полному отсутствию бит в передаче или приеме.

Это все, даже не касаясь контактов GPIO. Так как я не мог получить чистый ход даже всего за 2 секунды, можно с уверенностью сказать, что без патчей в реальном времени Raspberry Pi не может бить серийный номер 9600 бод, не генерируя ошибок за какое-то серьезное время.

Я буду тестировать исправления в реальном времени позже, если я получу время.

(Используемый инструмент: http: //git. kernel.org/?p=linux/kernel/git/clrkwllms/rt-tests.git;a=summary )

Обновление. Ядро RPi зависает при загрузке без обнаружения SD-карты, если скомпилировано с набором исправлений CONFIG_PREEMPT_RT. Это может быть просто исправлять, но, видя беспорядочные различия в источнике RPi, я думаю, что я хочу подождать, пока больше в ядре mainline.

Итак, тестирование слишком сложно, и я отказываюсь от него.

ответил Nakedible 25 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 25 Sep 2012 13:55:19 +0400 2012, 13:55:19
1

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

ответил Lalo UY 9 J000000Thursday15 2015, 21:49:06

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132