eddy_em: (Default)
В возне с прототипом спектрографа ESPriF, наткнулся на то, что все мои три железяки (контроллер восьми шаговиков, контроллер объектива Canon и контроллер узла калибровки) абсолютно никак в системе не различаются: те же самые VID/PID/Manufacturer (собственно, эмулирую PL2303). Подсказали мне, что можно завести текстовое поле Interface, которое поможет в дальнейшей идентификации. И вот на "заполнялке азотом" я решил поиграться. Заодно лишний раз оптимизировал USB, выкинув ненужные флаги. Все индексы текстовых дескрипторов задаются в дескрипторе устройства и конфигурационном дескрипторе. Скажем: iManufacturer, iProduct, iSerialNumber и тот самый iInterface. Чтобы не запутаться, проще завести enum, его поля и использовать как индексы. Если мы не хотим отдавать дескрипторы, задаем вместо индекса нуль. Ну, а дальше компьютер запрашивает нужный индекс и получает текстовую строку, которую и можно использовать в правиле udev, чтобы вместо кучи /dev/ttyUSBx создать более понятные (например, /dev/nitrogen_flooding0 или /dev/canusb0).
Вот с правилами UDEV пришлось повозиться подольше: благо, есть udevadm test, так что не пришлось постоянно шнурок туда-сюда втыкать/вытыкать. Сложность вызвало то, что поле Interface лежит в одном "устройстве", а поля VID/PID — в "родительских". Как обычно, SO помог в решении этой проблемы (что бы мы без Stack Overflow делали вообще? Я, например, по латеху там кучу проблем решил, ну и сам немного людям помог; да и по C, линуксу, башу…).
Одним словом, чтобы различить устройства с одинаковым VID/PID, нам нужно это правило:
ACTION=="add", DRIVERS=="usb", ENV{USB_IDS}="%s{idVendor}:%s{idProduct}"
ACTION=="add", ENV{USB_IDS}=="067b:2303", ATTRS{interface}=="?*", SYMLINK+="$attr{interface}%n"

Т.е. когда udev будет пробегаться по всем "родительским устройствам", на стадии добавления в систему USB он заведет переменную USB_IDS, а когда пройдется по "дочернему" устройству, проверит, соответствует ли эта переменная нужному VID:PID. Если соответствует — проверит, есть ли поле iInterface (нам не нужно "настоящие" PL2303 там именовать, да и у них все равно нет этого поля), и если оно есть — создаст нужную ссылочку.
В простейшем же случае (в данном) наше устройство отличается от всех остальных полем "DRIVERS" (которое как раз является свойством "подустройства" с полем interface), поэтому можно упростить правило:
DRIVERS=="pl2303", ACTION=="add", ATTRS{interface}=="?*", SYMLINK+="$attr{interface}%n"

Все, как только добавили устройство с нужным полем DRIVERS и существующим атрибутом interface, создастся нужная символическая ссылка.
Теперь достаточно для каждого USB-устройства только лишь менять название этого поля. И в системе теперь не придется перебирать из кучи /dev/ttyUSBx, чтобы найти свое устройство — на него будет удобный симлинк. Да и все демоны будут элементарно стартовать (не нужно будет перебирать устройства и запрашивать "ТЫ ХТО, Э?").
eddy_em: (Default)
Зашел на одном из форумов спор, что невозможно поднять (N-1) устройство CDC-ACM на микроконтроллере с N концевыми точками (N<=8). ОК, держите СЕМЬ CDC на одном устройстве.
Правда, я стал реализовывать это на STM32F103, подзабыв, какое он Г по сравнению с нулевой серией. А ведь там буфер под USB — всего-то 512 байт! Из них 64 уже занято описанием конечных точек плюс минимум 16 байт надо выделить на EP0. Получается 61 с небольшим байт на каждое устройство. Ближайшее круглое число — 32, так что пришлось буферы Rx/Tx каждого CDC урезать до 16 байт. Дескриптор конфигурации — просто ад! В полпервого ночи я его с первой попытки правильно заполнить не осилил (хоть и выделил те места, в которые нужно вносить изменения). Таки нужно такие вещи автоматом генерировать. Как же это работает без INTERRUPT IN? Да очень просто: я еще когда лепил эмуляцию PL2303, обратил внимание на то, что вообще никогда хост не работает с этой конечной точкой. И ее можно даже не инициализировать! Но, однако, она должна быть указана в дескрипторе. Как победить ситуацию? Ответ увидел где-то на SO или забугорном форуме: нужно просто указывать "виртуальную" конечную точку. На STM32F103/0x2 всего 8 конечных точек, а стандарт USB допускает использование шестнадцати. Следовательно, т.к. у нас EP0 занята, остается еще 7 конечных точек. Каждую настраиваем как INOUT (и в обработчике не забываем, что и на IN, и на OUT необходимо выставлять Tx valid — я с этим уже немного потупить успел), а вот для INTERRUPT IN указываем несуществующие точки, начиная с номера восемь!
Понятно, что всякие обработчики вроде SET_CONTROL_LINE_STATE использовать для выставления флага установленного соединения нельзя: ведь теперь аж 7 независимых каналов! И каждый работает с этой EP0. Поэтому писать приходится постоянно в каждый канал (разве что можно поставить флажок, что канал пока что не активен; а потом не писать в этот канал, пока не получим прерывание IN, в нем флажок и сбросим; но мне такой вариант городить лень было).
Пока могу лишь одно применение этой штуке придумать: когда я делал хронометр, меня просили сделать возможным подключение "малинки" для проксирования на нее данных с GPS. Либо этот UART можно было использовать как отладку. С таким диким устройством можно все в один USB запихать ☺ Только перейти на более вменяемый микроконтроллер (может, на 303?).
eddy_em: (Default)
На основе рабочего кода того же самого эмулятора клавомыши под STM32F0x2 и свежего USB CDC сделал
USB-HID для STM32F103. На "склеивание" двух монстров ушло почти 2 часа.
Теперь можно с чистой совестью забросить STM32F103 в самый дальний ящик и забыть о нем надолго.
eddy_em: (Default)
Все-таки, вымучил я CDC для этого МК. Конечно, если сравнить с STM32F042, вообще непонятно, для чего нынче люди используют F103: периферия никакущая, уйма багов, в общем, через одно место его создавали, похоже. Получился эдакий первый блин комом. Похоже, из-за того, что он такой дерьмовый получился, ST не вставляет китайцам палки в колеса и позволяет их клепать в бешеных масштабах и чуть ли не за полбакса продавать!

Read more... )
eddy_em: (Default)
Сегодня вымучил-таки эмулятор. Пришлось запускать виртуалбокс с прошивкой для игровых приставок, устанавливать там wireshark с "драйвером" PL2303 и сравнивать, чем отличаются данные, которые передаю я, от данных, передаваемых "настоящей китайской" микросхемой. В линуксе такого не сделать, т.к. модуль сильно урезан (все ненужное выкошено бритвой Оккама, а под прошивкой проверяют, не является ли этот чип поддельным).
Теперь еще сделать эмулятор ch340 (а можно и cp2102), разобраться с USB на STM32F103, портировать туда все эти варианты CDC, и эпопею с USB можно считать оконченной!
eddy_em: (Default)
Сегодня победил-таки (правда, по большей части "методом тыка") проблему с отправкой данных по USB CDC, о которой писал ранее. Но вот непонятно, как реагировать на SET_LINE_CODING: я пробовал читать следующую посылку на EP0, но там пусто (зато пропала ругань в dmesg).
Придется, похоже, читать стандарт USB CDC и/или ковыряться в ST'шных или opencm'овских исходниках, чтобы понять, что же там надо делать...

Да, вечером погоняли с Тимуром "недоробо"-телескоп, попадает очень хреново: с полем зрения 1.5° он местами промазывает почти на полкадра! Надо делать привязку, но для этого сначала требуется съюстировать оптику.
С RTS2 пока сражаюсь, надо довести ее до минимально компилируемого состояния и начать уже внедрять...
eddy_em: (Default)
Сегодня у меня последний день отпуска, завтра и послезавтра буду экскурсоводить на горе, так что уже не отдохнешь перед работой. А еще и выдался на редкость солнечный и теплый денек (до этого стояла хмарь по 6-7°C днем!), и я после обеда решил на работу не возвращаться, а добавить еще 4 USB-розетки в машину.
Дальше )
eddy_em: (Костерок)
Итак, вчера я написал базовый функционал для управления турелью "High Speed Filter Wheel" от Edmund Optics, сегодня добавил функцию смены имен колес/фильтров и более-менее дополировал. Код лежит на гитхабе (т.к. утилитка мелкая, я ее в сниппеты запихал, чтобы отдельную репу не делать), а также в одноименных репах на сосфорже, гитлабе и битбакете. Функционал сброса имен в "умолчательные" значения пока не добавлял (не думаю, что нужно).
Дальше )
Видео:


UPD


Сегодня взял вторую турель и доработал утилиту: избавился от вышеназванных багов, добавил возможность сброса имен в значения по умолчанию, добавил возможность установки в позицию "дом" той турели, в которой есть указанный фильтр. Да и вообще, оказалось, что все купленные колеса промаркированы как 'A', т.е. обращаться надо будет либо по идентификатору (что не очень удобно), либо по именам (что удобней). Хотя, конечно, плохо, что колеса одноименные: если колесо воткнуть в "чужую" турель, понять об этом можно будет лишь после пробных снимков (и то, возможно, не сразу)...

Систему управления фотометром планируем только под линукс писать (Тимур говорит, что "родной" линуксовый SDK для быстрой камеры присутствует и есть истории успеха работы с ним), архитектура будет клиент-серверная. А вот клиенты уже будут кроссплатформенными (для себя, наверное, консольную сделаю, а для народа тимур на Qt нарисует). Самой интересной и сложной будет методическая работа: как обрабатывать "кубы данных" с быстрой камеры, чтобы реализовать работу Lucky imaging. Заодно думали про фокусировку: если у цейсса нет каких-нибудь характерных асимметричных дефектов изображения (скажем, комы) с амплитудой выше полуширины первого максимума функции Эйри (но, понятное дело, меньше сиинга, иначе эти дефекты давно заметили бы), то определить знак изменения фокуса без перефокусировки (или установки в сходящемся пучке асимметричной маски) будет невозможно!
eddy_em: (Костерок)
Появилось у нашей лаборатории желание создать фотометр для Zeiss-1000 с минимумом разработок железа/софта и т.п. Одной из частей фотометра будут две турели High Speed Filter Wheel. Как обычно, железо огороженное. В отличие от предшественника Intelligent Filter Wheel (у которого вполне нормальный последовательный интерфейс с описанным в документации протоколе), у этой железяки только мастдайнутый установщик и никакой документации о протоколах!

При подключении к компьютеру железяка создает устройство /dev/hidrawX. На основе примера работы с этими устройствами из ядра я попытался определить, как же им управлять. И, в принципе, основные вещи реализовал (установка в "дом", установка на заданную позицию), но без понятия, как реализовать сброс (в отличие от usbdevfs эмуляторов последовательных портов здесь простым ioctl'ом перезапустить соединение не вышло). А сброс очень важно реализовать, т.к. любая проблема в протоколе вызывает "глухоту" контроллера: он перестает реагировать на управляющие команды.

Кстати, в опытах выяснил интересную вещь: если в первую десятку регистров hidraw под ведром 3.12 писать ненулевые данные, ядро (случайным образом, кстати: можно десяток раз так сделать без последствий, а можно с первого раза попасть) уходит в глубокий kernel panic, перезагрузка после которого чревата десятиминутным fsck'ом (это еще хорошо, что у меня один винт и небольшой)!

Протокол )

Вот таким жутким велосипедостроением приходится порой заниматься, потому как разработчики железяки закрысили описать протокол (заодно передаю привет Canon'овцам)! То ли еще будет с ПЗС…

UPD


Пока вендокомпьютер был свободен, я поставил софт управления турелью и попытался проанализировать трафик сниффером.
Регистры изменения положения турели )

UPD-2


Я вспомнил, что у меня есть вендокомпьютер для работы с Шаком-Гартманном (да, каюсь: я уже 6 лет не могу собраться, и написать нормальное ПО без огораживания). С его помощью была проделана оставшаяся работа.
Регистры работы с EEPROM и сброса )
Все, как только напишу полноценную управлялку, создам новую тему.
eddy_em: (Костерок)
Итак, поскребя по сусекам посмотрев примеры с easyelectronics.ru, я таки собрал все воедино и у меня получился рабочий эмулятор USB→COM (его, кстати, можно и как реальный использовать при небольшой доработке).
Вот — исходники. Пока что в них полным-полно мусора, но наконец-то после выполнения
make && make load

и переподключении USB (почему-то сразу после заливки железяка не определяется, наверное, нужно при запуске сначала отключить USB, подержать его немного так, а потом уже включать - ХЗ, будет моим домашним заданием) появляется устройство /dev/ttyACM0!!!
more )

eddy_em: (Костерок)
Сегодня наконец-то у меня что-то небольшое получилось. Отсюда я скачал проект-заготовку (если точнее, то скачал отсюда, в оригинальной статье версия нерабочая).
После некоторых изменений и отключении USART и printf (первый мне не нужен, т.к. некуда подключать, а второй вешал систему, т.к. некуда выводить), получил это.

После сборки и прошивки (make && make load) светодиод замигал, а dmesg выдал
[181351.201294] usb 1-1: new full-speed USB device number 69 using xhci_hcd

В /dev/ появилось устройство /dev/bus/usb/001/069. Конечно, с ним пока ничего не поделаешь: использовать libusb я не хочу, т.к. есть вроде бы возможность "оформить" железяку как посредник USB→RS232, чтобы появилось устройство /dev/ttyUSBx, с которым уже можно было бы работать, как с обычным последовательным портом, безо всяких libusb. А это будет намного лучше: все равно для работы эта плата будет использовать USART, но для тестовых подключений — как раз USB (т.к. я не собираюсь таскать туда-сюда "железный" переходник USB→RS232, не для того дорогущий ARM покупался).

Итак, остается почитать спецификации: как должно себя идентифицировать устройство, чтобы система решила, что это — USB→RS232, а не какое-то "левое" устройство.
А потом — дело за малым: подрихтовать исходники (выбросить все ненужное и заменить жирную printf на самописную) и добавить своих функций.
P.S )
eddy_em: (Костерок)
Внеся минимальные правки в скачанный отсюда код (который по идее должен работать), получил вот это. Но фигвамушки ☹, не работает, собака!

Что-то уже крыша съезжает, так что, наверное, сегодня до конца рабочего дня пропинаю, а завтра с новыми силами возьмусь за внимательное вчитывание в код. А то непонятно, где что и в какой последовательности выполняется. Может, где-то забыта функция инициализации порта. А может, я где-то пропустил определение пинов, к которым USB подключены.

P.S. )

October 2025

S M T W T F S
   1234
567 89 1011
121314 15161718
19202122232425
2627 28293031 

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Feb. 24th, 2026 01:36 pm
Powered by Dreamwidth Studios