Как стать автором
Обновить

Затолкаем, братцы!!! UART Lite через PCIe прямиком в Linux: драйвер за вечер (почти)

Уровень сложностиСредний
Время на прочтение20 мин
Количество просмотров9.4K
Всего голосов 83: ↑81 и ↓2+101
Комментарии29

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

Я сегодня сладкого больше не ем. Мне достался огромный кусок торта в этой отличной статье!

Спасибо автору!

Наконец-то хоть что-то интересное, а не корпоративная копирайтерская вода (но зато написанная без отвлечения внимания разработчиков: https://habr.com/ru/articles/858258/)

Давно хочется этот PCIe пощупать, и даже KC705 есть, времени только нехватает.

Но после этой статьи мотивации прибавилось.

О, круто! KC705 — отличная плата, а с PCIe можно много всего интересного сделать.
Понимаю насчёт времени — у самого вечно дилемма между хотелками и дедлайнами 😅
Рад, что статья добавила мотивации!

Хм. То есть в этой железяке квадратурные компоненты для отладки можно писать в файл почти неограниченно. Круто. Интересно как организована демодуляция на artix

Да, это вполне рабочая схема — можно стримить I/Q через PCIe, USB или Ethernet и обрабатывать всё на CPU/GPU (например, в GNU Radio , Python или C). Но если важна минимальная задержка или требуется real-time, лучше выполнять обработку прямо в FPGA: NCO, микшер, фильтрация, демодуляция — всё это реализуемо как в виде одного пайплайна, так и через набор сопроцессорных ядер.

У меня оба подхода реализованы в разных проектах:
Один — SDR с обработкой на хосте.
Второй — полноценный трансивер с OFDM и MIMO, где все расчёты идут внутри FPGA.

Для передачи данных используются каналы C2H и H2C через XDMA:
Потоки разделяются по направлениям: RX → C2H, TX ← H2C

Пример скорости передачи данных:
В одну сторону (2 канала, 61.44 MSps, 16-бит I/Q): ~3.93 Гбит/с
В обе стороны: ~7.86 Гбит/с

PCIe Gen1 x4 (4 × 2.0 Гбит/с) справляется с такой нагрузкой, но на практике узким местом чаще становится RAM или CPU хоста, особенно при непрерывной high-rate передаче.

А можно я понаглею и про работу NCO спрошу? Относительные PSK у меня работают как часы хоть на -105, а с NCO засада, работает разве что при некогерентности частот передатчика/приемника до 1 кГц

Странно использовать dma для uart 9600, имхо. Fifo есть, прерывание и блокирующее чтение/запись, нагрузки на cpu сравнимы с 0. Да даже пулинг по таймеру несильно загрузит систему, имхо.

Да нет тут ни DMA ни прерываний, ими только пугают. По сути всё взаимодействие с железом тут в 3 строчках:

ioread32(priv->base + UARTLITE_STATUS);

iowrite32(val, priv->base + UARTLITE_TX_FIFO);

ioread32(priv->base + UARTLITE_RX_FIFO);

Т.е. просто побайтово пишут/читают через регистр, предварительно проверяя статус - самый примитивный метод. А остальное нужно чтобы оно виделось и работало в системе как COM порт.

Только непонятно, что можно сделать с SDR на скорости 9600 - просто какая-то настройка, а основной поток данных идет по другому каналу?

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

У меня немного другой случай — UART IP реализован в FPGA и доступен (его адресное пространство, регистры) через PCIe как AXI memory-mapped устройство. Использую AXI Lite, подключённый к PCIe BAR. На хосте доступ идёт через XDMA IP от Xilinx (или свой драйвер), но только memory-mapped интерфейс — DMA здесь не используется, он просто не нужен для UART.
UART используется для получения сообщений от GPS приемника. Поэтому достаточно обычного доступа к регистрам через mmap, как к памяти. Основной поток данных (например, для SDR) передаётся через другие интерфейсы с DMA.

Аа, понял - я просто решил, что xdma это именно dma)

Торт так торт, спасибо вам!
Ещё бы вот о разработке железа почитать, но тогда совсем слипнется 😁

Моя SDR-плата

А что за плата?

Это моя собственная SDR-плата, полностью разработанная мной с нуля.
Использую её вместе с LattePanda Sigma (x86) и Nano PC T6 (ARM) — основная идея: компактный, полностью автономный SDR-модуль с 2×RX и 2×TX до 6 ГГц, на котором можно поднять полноценную связь, включая собственный проприетарный baseband.

Что на борту:

  • FPGA Xilinx Artix-7 (опции: 35T / 75T / 100T / 200T)

  • RF-трансивер: AD9361 / AD9364 / AD9363

  • DDR3-память

  • GPS-модуль SIM68

  • MPU9250 (акселерометр, гироскоп, магнитометр)

  • Датчик давления

Плата подключается через PCIe x4 (формат M.2 2280).

Я так понимаю в заголовке в скобочках заключено основное время работы, а про вечер упомянуто, как раз про тот, в который статья на публикацию ушла)

Проект весь на модульном дизайне построен? Я как-то от текстовых модулей топ-уровня отвыкнуть так и не смог.

Формфактор sdr приёмника под м2 слот тупо топ.

Тот момент когда ощущаешь себя героем мема "Ничего не понятно, но жутко интересно", но по окончанию чтения понимаешь что статья, это торт в кубе!

Круто, но без огонька. :)

Какое-то крупно-панельное домостроение получается - потыкали мышью в разные окошечки и кнопочки, выбрали опции и вуоля - гигантский кусок проприетарного кода на Verilog, об устройстве котрого мы ничего не знаем и даже не имеем шанса узнать. Но зато работает, байтики пересылаются, через DMA. Только зачем тут DMA ?

Автор в любом случае молодец, что смог разобраться. PCIe это самая сложная цифровая технология на сегодняшний день.

PS: Хотелось бы теперь увидеть аппаратную сторону. Та, что со стороны ПЛИС.

Так он же не писал ядро PCIe с нуля - оно готовое от производителя, воткнул в проект, назначил пины и готово. И никакого DMA тут нет, по крайней мере UART работает через примитивное PIO. DMA если и используется, то для чего-то, не описанного в статье.

Как справедливо было замечено — зачем изобретать велосипед зачем писать PCIe с нуля, когда есть отличные ядра от вендоров и целый набор достойных open-source решений, в которые уже кто-то выложился по полной.

Моя цель была не в том, чтобы изобрести новое ядро, а чтобы поднять всю систему целиком — от SDR-модуля до работающего baseband-процессора со связью, навигацией, сенсорами, и, конечно, общением с хостом через PCIe. Дел — непочатый край: HDL, драйверы, пламенные костыли, память, DMA, управление потоками.

🔥 Огонёк — есть. В сердце, в душе, ну и иногда на плате — там с этим строго: светодиодов достаточно 😄

Аппаратную часть обязательно покажу — layout, трассировка, разводка, схемотехника. Будет жарко (и аккуратно).

зачем писать PCIe с нуля, когда есть отличные ядра от вендоров

Совершенно незачем - вполне логично использовать готовое и отлаженное. Тем более в ПЛИС оно скорее всего хардварное, т.к. на плисовой логике просто нереально добиться нужного быстродействия. Комментарий был в ответ на фразу:

PCIe это самая сложная цифровая технология на сегодняшний день.

Очевидно, что сроектировать своё или использовать готовое - отличаются по сложности на несколько порядков. В случае использования готового ничего сверхсложного нет.

Кстати неплохо бы описать общими словами что за устройство проектируете и с какиой целью. А то вообще непонятно - толи это самодельный GPS модуль, который с внешним миром общается только через NMEA, толи комбайн всё в одном, но пока что описали только UART для GPSa.

Статья супер. Расскажите, как передаете квадратуры через PCIe? Лучше в виде статьи )

Предполагаю, что Q/I не передаются в хост-машину. Вся обработка DSP идет внутри ПЛИС, а хоcт только управляет процессом. Или передается какой-то минимум FFT коэф. для отображения "водопада".

Вся обработка DSP идет внутри SIM68, ПЛИС только принимает по UART результат

Интересно, рассматривали ли вы возможность использования UIO-драйвера вместо написания полноценного TTY-драйвера? Это могло бы упростить доступ к регистрам из пользовательского пространства без необходимости внедрения в ядро. Также, как насчет использования более высоких скоростей передачи данных через UARTLite? 9600 бод может быть узким местом в некоторых приложениях. В целом, статья вдохновляет на эксперименты с FPGA и Linux.

Да, идея с UIO действительно хорошая — особенно когда нужен простой и быстрый доступ к регистрам через AXI Lite (BAR).
Но в моём случае я использую DMA-каналы (H2C / C2H), так что UIO не подойдёт. Для потоковых данных нужно полноценное взаимодействие с буферами, прерываниями и адресным пространством — поэтому задействован драйвер xdma от Xilinx и свой.
Параллельно собираю "свой танк" — с полным контролем над PCIe, SDR-цепочкой и всей архитектурой.
UART у меня подключён только к GPS-модулю, и никаких ограничений по скорости нет — при желании вы легко можете менять параметры (скорость, формат, режим работы) под свои задачи.

Вроде нормально все работает с UIO, там держатся только регистры управления и прерывание. SG DMA master пишет все в зарезервированную от линукса область физ. памяти. User land аппликация вытаскивает пакеты через mmap

Блин, я за вечер (почти) даже прочитать статью не осилил :)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации