В прошлой статье мы начали знакомиться с тем, как можно работать со стандартными, общеизвестными шинами силами комплекса Redd, после чего я обещал перейти к тому, как в нём можно получить доступ к шинам более экзотическим. Но побеседовав с парой знакомых, я вдруг понял, что не все читали статью, которая была написана про комплекс Redd вне этого цикла. И, соответственно, не все знают, зачем эти шины в комплекс добавлены вообще. Можно, конечно, просто сослаться на ту статью, но мне кажется, что будет правильнее пересказать соответствующую её часть с привязкой к теме именно этого цикла. Поэтому сегодня мы рассмотрим не только практические, но и теоретические вопросы, касающиеся шин, реализуемых комплексом Redd.
Занудная теоретическая часть
Что мы будем рассматривать
Давайте коротко (насколько это возможно) пробежимся по некоторым теоретическим вопросам, чтобы чётко понимать, зачем в комплексе Redd всё сделано так или иначе. В первую очередь, основная задача комплекса… Как ни странно, в рамках этого цикла статей я ещё ни разу не писал про неё. Да и не планирую писать. Дело в том, что основная задача — это совместный удалённый доступ к отладке тех или иных аппаратных средств (от микроконтроллеров до огромных многоядерных процессорных систем). Резервирование рабочего времени, обеспечение физического доступа по каналам средней паршивости (а не только идеальным) и прочие прелести. Отладка может быть через JTAG или через иные средства, предоставляемые средами разработки. Над этим работает большая команда, там у них всё очень интересно, но я не люблю всякую бюрократию, поэтому не хочу писать на те темы. Возможно, в будущем кто-то другой восполнит этот пробел… А пока я пишу о вспомогательных средствах комплекса.
Зачем в комплексе Redd реализованы стандартные шины
Очень часто приходится вести разработку оборудования, не имея доступа к нему самому. Давайте рассмотрим какой-либо конкретный пример проекта, на который есть красивые ссылки. Вот, например, мои любимые вертолёты. Мы здесь, а вертолёты — в Швеции. Причём разработку нам заказывали зимой, когда вертолёты физически не могли выполнять функции, которые мы для них реализовывали (а именно удобрение почвы в лесах: почва же в это время была под сугробами). Получается, что устройства, установленные в вертолёте, при отладке надо эмулировать, а летать — виртуально.
Но то отладка. При тестировании же проекта эмуляция является единственно возможным вариантом. Тестер должен всё проверить в максимальном количестве режимов, перебирая различные комбинации. Плюс он должен создать ситуации с критическими и аварийными условиями (такая у тестеров деструктивная работа). Как это сделаешь на реальном оборудовании? Только на эмуляторах.
Как идёт общение с современными устройствами? Обычно — через типовые шины, ведь разработчики устройств стремятся подключаться через что-то, уже известное потребителям. Вот как раз Redd и будет выступать в роли эмулятора многих устройств. Его шины подключаются к разрабатываемому блоку. И блок будет уверен, что он работает с реальной аппаратурой, не зная, что на том конце шин стоит не куча железа, а комплекс Redd, на котором крутится некоторое количество эмуляторов.
При работе же с реальным оборудованием, шины могут выступить в роли анализаторов, протоколируя работу с реальным железом для разбора полётов при проблемах.
В общем, шин должно быть как можно больше, а их набор как можно более разнообразным. Хотя, во всём надо знать меру. Ну хотя бы потому, что каждая шина стоит каких-то денег и занимает место в корпусе, да и на разъёме тоже. Теперь рассмотрим, по каким стратегиям этими шинами лучше управлять программно.
Кто будет вести разработку кода под Redd
В современных компаниях во главе угла стоит его величество человеко-час. Дело в том, что это весьма дорогой ресурс по многим параметрам (деньги, сроки разработки, доступность специалиста в данный конкретный момент для этой и иных задач компании и т. п.), поэтому если руководство может сэкономить на часах, оно это сделает. Если будет возможность не добавлять разработчиков к команде, они не будут добавлены. Если будет возможность сделать всё за меньший срок, из разработчиков будут выбивать, чтобы они сделали за меньший срок.
Из этого следует, что вряд ли для написания эмуляторов дадут отдельных специалистов. А если и дадут, то это будут обычные программисты, трудящиеся в той же компании.
К чему я это пишу. В некоторых статьях считается шиком, когда для задач обслуживания нестандартных шин используются какие-то специализированные языки. Мне довелось поработать с чем-то таким. Давайте я опишу свои впечатления на примере вещей, которые когда-либо публиковались. Вот, например, https://www.astrosoft.ru/about/clients/bvg-group/case-959/. Причём на язык ЯСТЕК не так давно вышел даже ГОСТ. Моё мнение таково: что было необходимо в конце 70-х — начале 80-х, то совершенно не нужно на исходе первой четверти XXI века. Вот замечательная статья Константина Чижова, в которой самая главная вещь того языка (группы контактов) прекрасно и почти бесплатно реализуются через метапрограммирование на С++ http://easyelectronics.ru/rabota-s-portami-vvoda-vyvoda-mikrokontrollerov-na-si.html. В этой статье проверяется всё для AVR. Я провёл большую проверку варианта библиотеки для Cortex M, результаты тоже поражают. Оптимизаторы упаковывают всё так, что прямая разработка на ассемблере не даст никакого выигрыша. И это касается не только групп контактов, а вообще всех драйверов из mcucpp. Жаль только, что начальство не пустило эту идеологию в ОСРВ МАКС, поэтому в публикацию результаты исследований не пошли. Но дома я пользуюсь только этой библиотекой.
Все прочие вещи, которые реализованы на ЯСТЕКе, также прекрасно упаковываются в конструкции С++. А вот интерактивности для оператора на стыке семидесятых и восьмидесятых не было. Правда, не было её и в тогдашних компиляторах Паскаля, Си и прочих языков. Компиляторы тех времён в большинстве своём были пакетными и просто генерили ассемблерный текст, не особо располагая средствами отладки. Мы при изготовлении ремейка ЯСТЕКа добавили операторы вывода данных на экран и даже интерактивный отладчик, но всё равно, это полумеры на фоне того, что сейчас творится в готовых средах разработки обычных языков программирования. Короче, времена, когда были технические причины делать особый язык ЯСТЕК, давно минули. Сегодня на обычном языке программирования можно достичь и того же, и гораздо большего.
Кто-то может сказать, что там код писали не специалисты по С++, а обычные настройщики… Так-то оно так, но я уже отметил, что для Redd код будут писать обычные программисты. Нет смысла руководству держать ради эпизодических задач узкого специалиста. И нет смысла обычному специалисту учить ещё один язык.
Да и какие у этого ещё одного языка будут выразительные возможности? При разработке эмуляторов могут понадобиться совершенно экзотические вещи. Например, для эмулятора GPS в интерактивном режиме мы управляем при помощи джойстика. Какой проблемно-ориентированный язык его поддерживает? И гибкость у этих языков та ещё. Наконец, повторное использование кода в обсуждаемом ЯСТЕКе не на высоте, а поиск готовых решений в сети… Даже на распространённых-то языках не просто найти хороший пример, а на экзотике — и подавно.
То же касается и вот такого случая, плавно перешедшего в такой. В рамках автоматизации предприятия SIMATIC с его развитой системой настройки и программирования — хорош, но для небольшого проекта он больше проблем создавал, чем решал, поэтому был заменён на более универсальное решение.
Итого, мы делаем вывод, что работа обычных программистов на привычных им языках нормальна для Redd. Для других задач — обсуждаемо, а конкретно для вспомогательных задач, решаемых комплексом Redd, нормально.
Как реализовать шины
Но если мы говорим о том, что шинами будут пользоваться обычные программисты на привычных им языках, то и библиотеки для работы с этими шинами должны быть как можно более типовыми. В частности, сразу было отметено предложение: «А давайте мы поставим в комплекс микроконтроллеры, а программисты всё будут писать на них». Этот вариант снова требует специалистов по этим контроллерам. Плюс он требует серьёзной синхронизации между подсистемами. Было решено, что по возможности, программист должен работать на привычном ему центральном процессоре PC. «А как же ПЛИС?» — спросите вы. Ну-у-у-у, наверное, все заметили, что и для ПЛИС я выбрал идеологию «минимум разработки на Verilog, максимум привычного для программистов». Там пока что более удобно не сделаешь. Но мы прикладываем все усилия.
Итак, типовые реализации шин. С UART всё понятно. С SPI/I2C рассматривались разные варианты, так как устоявшегося стандарта де-факто для PC нет. Но было желание обойтись без варианта написания полного комплекта: «прошивки» контроллера, драйвера и библиотек. Хотелось взять что-то готовое. Тем не менее, мы до последнего рассматривали вариант с микроконтроллерами, реализующими на уровне USB протокол а-ля отладчик от Cypress. Точку в этом поставили находки, изложенные в статье про DMA. Невозможно гарантировать пропускную способность, запрошенную в ТЗ, если одновременно работают все шины с заранее неизвестными потоками данных. А если разносить на несколько контроллеров — упираемся в пропускную способность USB 2.0 FS. Поэтому только мосты FTDI. Один мост — одна функция, а пропускную способность обеспечивает шина USB 2.0 HS.
К слову, в прошлом разделе я всё время ссылался на распространённый язык C++. Дело в том, что на данном этапе жизненного пути это мой основной язык программирования (хоть так было и не всегда). Но стандартные решения, они на то и стандартные, чтобы прекрасно работать и на других распространённых сегодня языках, будь то Питон, Ява или что ещё. Поэтому если в бой бросят специалиста по тем языкам, он, применяя эти языки, не менее легко всё сделает. Именно в этом прелесть универсальных решений.
Но есть несколько шин, на которые глупо закладывать дорогие чипы FTDI. Вот о том, как они реализованы в комплексе, мы сейчас и поговорим.
Тысяча мелочей
Ряд разрабатываемых устройств обновляет свою «прошивку» с помощью SD карты. Чаще всего «прошивка» заливается на карту в виде файла, после чего устройство выключается, а при включении обнаруживает файл с обновлением и применяет его. Я недавно баловался с новой платой для одного из своих 3D принтеров. Там «прошивка» Marlin 2.0 после какой-то из M-команд (точный код не помню) открывала содержимое SDшки через шину USB, поэтому я мог вливать обновления без каких-либо ухищрений. Подключился по USB, после чего знай себе выключил/включил питание (как это сделать силами комплекса Redd, мы рассматривали в прошлой статье), подал команду подключения SDшки к USB, дождался появления диска, залил «прошивку», снова выключил/включил питание, подождал. «Прошивка» обновилась. Но не всегда всё так красиво. Иногда SD карточка должна быть подготовлена заранее. Кстати, если в 3D принтер влить кривую «прошивку», описанный выше идеальный вариант тоже не сработает, и карту тоже придётся готовить заранее. А при разработке сделать нерабочую «прошивку» — пара пустяков.
Для этого случая в комплексе Redd имеется коммутируемая SDшка. На схеме электрической принципиальной она включена следующим образом:
Сначала мы пытались найти типовое решение, которое бы позволяло коммутировать шину SDIO (не SPI, а именно SDIO, устройства же могут работать и через данный интерфейс) через ПЛИС. Оказалось, что красивого решения не существует. Даже решения от производителей ПЛИС сложны и не очень внушают доверие. Поэтому были поставлены аналоговые ключи, которые физически подключают карту или на внешний разъём, или к считывателю в составе Redd. Поэтому алгоритм работы такой: подключили к считывателю, подготовили файлы средствами ОС Linux, подключили к целевому устройству. Используем там.
Так как работа с файловой системой не относится к критическим вещам (мы же всего лишь готовим данные, так что особого быстродействия не требуется), было решено сделать считыватель на базе микроконтроллера STM32F103. Поддержка полноценного SDIO есть только у максимальной версии данного кристалла. А так как у этого контроллера имеется много свободных контактов, было решено вынести на них прочие низкоскоростные функции. Рассмотрим фрагмент схемы электрической принципиальной, из которого станет виден их перечень.
Собственно, красным подсвечены сигналы, относящиеся к SDIO, и коммутации SD карты. Переходим к рассмотрению остальных цветов подсветки.
SPI флэшка
Второй распространённый приём обновления «прошивок» целевых устройств — с SPI флэшки. В наше время это всё чаще не SPI, а Quad-SPI. Принцип тот же самый. Залили данные, затем подключили флэшку к устройству и включили его. Механизм Bootstrap «засосёт» прошивку в ОЗУ при старте.
Здесь применена та же самая схема — с аналоговыми коммутаторами:
Ну, а линии, относящиеся к работе с флэшкой, были подсвечены зелёным.
Слаботочные твердотельные реле
Периодически возникает задача имитировать нажатие кнопок на устройстве. Типичная ситуация: тестерам надо проверить работу меню целевого устройства. Нет, один раз можно по всем пунктам пробежаться, но если разработчики вносят изменения? Чтобы автоматизировать процесс, лучше, если кнопки прохода по меню будет делать автоматика (скриншоты же снимать можно или силами ОС на целевом устройстве, или сканируя шину, идущую к дисплею, при помощи сниффера на ПЛИС). Ну, и есть масса других задач, где требуется программно имитировать нажатие кнопок. Для этого в схему добавлены твердотельные реле:
… а линии управления ими были подсвечены синим.
Конфигурирование мостов USB-SPI/I2C
В прошлой статье я отмечал, что мосты FTDI, на которых реализованы шины SPI и I2C имеют управляющие ножки CFG0 и CFG1. В целом, скорее всего, никому не понадобится изменять их значения по умолчанию (все нули), но если потребуется — линии, управляющие данными сигналами, также выходят из рассматриваемого контроллера STM32 и были подсвечены фиолетовым цветом.
Сброс USB устройств
При разработке системы было решено, что чисто теоретически устройства могут «зависнуть». Например, мосты FTDI первых серий имели свойство «зависать» при нестабильной «земле». Да, это было более десяти лет назад. Да, внутри комплекса земля крайне стабильная, так как мост находится в том же корпусе, что и ЭВМ. Но вдруг. В общем, в ТЗ была заложена возможность сброса любого из устройств. Соответствующие запросы вырабатываются всё тем же контроллером STM32 и подсвечены жёлтым цветом.
Программный доступ к контроллеру STM32
Как видим, большинство устройств, описанных выше, не являются стандартными. Если точнее, то большинство из них можно отнести к разряду GPIO, но стандарта де-факто для него нет. Самое сложное из устройств — это считыватель SD карт. Поэтому было решено реализовать на контроллере STM32 именно функциональность SD Reader (благо среда STM Cube MX позволяет сделать это, вписав буквально несколько строчек собственного кода), а остальные функции реализовать в виде Vendor-запросов к устройству Mass Storage Device, лежащему в основе считывателя. Но как было решено несколько статей назад, огромные повествования неудобны для чтения. Поэтому принципы посылки команд к Mass Storage Device из ОС Linux и примеры программного доступа к получившемуся устройству мы рассмотрим в следующий раз.