Загрузка конфигурации в ПЛИС через USB или разбираем FTDI MPSSE
Пишем загрузчик ПЛИС в LabVIEW. Часть 1




В первой статье мы обкатали алгоритм загрузки на старом добром Си, во второй статье разобрались, как в LabVIEW можно организовать программу и реализовать простой интерфейс пользователя. В этот раз мы познакомимся с новыми приемами работы в LabVIEW, разберем особенности обработки ошибок и завершим проект: реализуем протокол загрузки файла конфигурации в ПЛИС.

Обработка ошибок


Открываем сишный исходник, анализируем функцию MPSSE_open. Несмотря на алгоритмическую простоту (функции вызываются друг за дружкой) требуется импортировать довольно много элементов API D2XX: FT_OpenEx, FT_ResetDevice, FT_Purge, FT_SetUSBParameters, FT_SetChars, FT_SetTimeouts, FT_SetLatencyTimer, FT_SetFlowControl, FT_SetBitMode. Как было показано в предыдущей статье, импорт функций осуществляется с помощью узла Call library Function. Этот узел имеет выделенные терминалы для контроля ошибок. В LabVIEW есть одно простое правило: все ВП должны отслеживать ошибки и сообщать об ошибках, возвращаемых терминалами ошибок. Большинство встроенных ВП неукоснительно следует ему. Надеюсь всем понятно, насколько важно контролировать и обрабатывать ошибки особенно на этапе отладки, однако есть еще одна причина, почему это так важно, неочевидная "классическим" программистам. В LabVIEW нет строгой последовательности выполнения приборов на блок-диаграмме: прибор выполняется, когда на его входах будут готовы данные. Если с выхода одного ВП данные передаются на вход другого ВП, то понятно, что в начале отработает первый ВП, только после него второй. А как быть, если нет передачи данных, а ВП выполняют независимые действия? Конечно можно воспользоваться громоздкой "Flat Sequence Structure", но гораздо удобнее соединить приборы между собой потоком ошибок.


При импорте функций D2XX мы сталкиваемся с двумя типами ошибок. Первый — это ошибка непосредственно импорта — возвращает сам блок Call library Function. Второй — ошибка самой библиотеки, возвращается почти каждой функцией через FT_STATUS. Все возможные значения описаны в виде enum'а в заголовочном файле ftd2xx.h. Хотя достаточно знать, что значение FT_OK — отсутствие ошибки, а все остальные значения — коды ошибок, хотелось бы отследить не только сам факт ошибки, но и какая ошибка произошла и где именно она произошла.


В LabVIEW данные об ошибке распространяются через кластеры error. Это такой специальный выделенный тип данных, в LabVIEW есть множество ВП и функций для работы с ним. Кластер ошибок состоит из трех элементов: логическая переменная — отображает статус, целое знаковое число — код ошибки, строка — источник ошибки. Статус показывает, произошла ли ошибка, код ошибки определяет ее тип и используется специальными ВП для формирования отчета. Строка дает более развернутое представление о том, где именно произошла ошибка. В LabVIEW принято, если статус равен TRUE, то это ошибка, если статус равен FALSE, но код не равен нулю и строка описания не пустая, то это предупреждение, если же статус FALSE, код равен нулю и строка пустая — нет ошибки.




LabVIEW содержит внутреннюю базу данных, в которой код каждой ошибки связан с ее описанием. Для каждого типа ошибок выделен специальный диапазон значений кодов. Например, для ошибок связанных с работой сети выделено несколько диапазонов: от –2147467263 до –1967390460, от 61 до 65, от 116 до 118 и 122, 1101, 1114, 1115, 1132 до 1134, от 1139 до 1143 и от 1178 до 1185. Для ошибок, определяемых пользователем зарезервировано два диапазона от –8999 до –8000 и от 5000 до 9999. Из этих диапазонов мы можем выбрать значения для кодов ошибок библиотеки D2XX.


Создадим ВП, принимающий на вход статус функции D2XX и конвертирующий этот статус в кластер ошибки LabVIEW. Большинство функций и ВП в LabVIEW, получив на вход Error In статус TRUE, не выполняют свой код, а передают информацию об ошибке на терминал Error Out. Это позволяет эффективно передать информацию о источнике через всю цепочку до обработчика ошибок, исключив выполнение кода в аварийном режиме. Желательно, чтобы и наши ВП вели себя аналогично.


Оформим список статусов D2XX в виде enum и вынесем его в отдельный тип (в предыдущей статье мы так поступили с типами FTDI).


enum FT_Status

Новый ВП сохраняем под именем FT_error.vi. На переднюю панель добавляем два кластера Error In и Error Out, найти их можно в палитре "Array, Matrix & Cluster". Подсоединяем их к терминалам на панели соединений в нижнем левом и нижнем правом углах соответственно, как уже говорилось в прошлой статье, это принятое в LabVIEW расположение терминалов потока ошибок. На блок-диаграмму добавляем структуру Case, на вход Case selector подаем кластер Error In, после чего структура Case меняет цвет и делиться две поддиаграммы: "No Error" — зеленый цвет, и "Error" — красный цвет. Внутри случая Error передаем кластер ошибок от терминала селектора напрямую к выходному туннелю на правой границе. А в зеленом случае добавляем еще один Case, он в зависимости от статуса будет определять, следует ли создавать ошибку (статус не равен FT_OK), или оставить все как есть: пропустить входной кластер ошибки на выход без изменения.


Для того, чтобы технично преобразовать код ошибки в кластер, можно использовать ВП Error Cluster From Error Code VI. Этот SubVI в описание ошибки добавляет цепочку вызова, благодаря чему мы сможем определить не только что произошло, но еще и где это случилось.


Чтобы выделить текст, соответствующий входному статусу (FT_Status), используем блок свойств: выбираем "RingText.Text". Текст ошибки передаем на вход error message ВП Error Cluster From Error Code VI.
Не забываем нарисовать "говорящую" иконку.


FT_error.vi


Передняя (фронт) панель подприбора



Блок-диаграмма. На входе ошибка



Блок-диаграмма. На входе нет ошибки и статус равен FT_OK



Блок-диаграмма. На входе нет ошибки, но статус отличен от FT_OK



Для испытания FT_error можно создать пустой ВП, добавить туда созданный ВП и посмотреть, как будет меняться значение при запуске, если подавать различные статусы.


Тест FT_error.vi


Передняя (фронт) панель прибора



Блок-диаграмма


Теперь, после любого вызова функции из API D2XX, мы будем использовать SubVI FT_error.vi. А кластер ошибок будет проходить через все ВП по всей иерархии вызова.


В ВП верхнего уровня мы должны определиться, что делать с обнаруженной ошибкой: можно вывести сообщение в диалоговом окне, записать его в файл отчета, проигнорировать или просто "тихо" завершить приложение. Диалоговое окно — самый простой и наиболее популярный способ отчета об ошибках. А еще он удобен для начинающего программиста, так как делать ничего не надо. В каждом ВП по умолчанию активирован режим автоматической обработки ошибок (Enable automatic error handling, находится в категории Execution меню ВП Properties). Работает он так: если в каком-то узле выходной терминал Error Out никуда не подключен, и в этом узле происходит ошибка, то LabVIEW приостанавливает выполнение приложения и выдает диалоговое окно. Если терминал Error Out узла соединен, то поток ошибки распространяется, как запрограммировано, и никаких дополнительных действий не происходит. Однако окно сообщения можно вызвать программно, для этого нужно воспользоваться ВП General Error Handler и Simple Error Handler (находятся в палитре "Dialog&User Interface"). При этом информацию об ошибке мы можем использовать для завершения программы. На блок-диаграмме это выглядит примерно так:



Картинка кликабельная


Когда произойдет ошибка, программа будет приостановлена, появится окно с отчетом, после закрытия окна программа корректно завершиться.


Окно отчета


Открыть и закрыть FTDI


Итак, возвращаемся к функции MPSSE_open. Создаем новый VI. Первым делом, добавляем терминалы для потока ошибок. Добавляем структуру выбора и на селектор подаем вход Error In. В зеленом кейсе делаем импорт функций в порядке и с параметрами как в Сишном прототипе. Все узлы Call Library Function Node соединяем в цепочку потоком ошибок. В красном кейсе через тунель соединяем Error In с выходным терминалом ошибки.



Картинка кликабельная



ВП MPSSE_open.vi


На вход SubVI подается строка с описанием FTDI (Description), на выходе — Handle и инициализированный чип FTDI в режиме MPSSE.


Создадим ВП, завершающий работу с FTDI и можно уже проверить работоспособность на железе.


FT_Close.vi


Блок-диаграмма



Передняя панель


В предыдущей статье для отладки интерфейса мы сделали ВП заглушку SP_FT_MPSSE_FPGA.vi, сейчас настало время наполнить его. Добавляем на его блок-диаграмму MPSSE_open.vi и FT_Close.vi. На данном этапе достаточно сложно оценить, верно ли прошла инициализация, однако ненулевое значение Handle на выходе MPSSE_open.vi и отсутствие ошибки нам уже о многом скажет.



Блок-диаграмма SP_FT_MPSSE_FPGA.vi


Для того, чтобы посмотреть значение Handle можно воспользоваться окном "Probe Watch Window". Это удобный инструмент отладки, позволяющий вывести значение данных на любом (почти любом) проводе в процессе выполнения прибора. Для того чтобы установить пробу на линию, нужно в контекстном меню этой самой линии выбрать пункт "Probe". Откроется окно "Probe Watch Window", а на линии появится циферка с номером пробы. На рисунке выше это "3".


Probe Watch Window


На линии Handle значение 698389336


Отлично! Запускаем ВП верхнего уровня, подключаем к компьютеру отладочную плату. В списке "Выберите устройство" появляется описание подключенной микросхемы FTDI, нажимаем кнопку "Программировать" и… ничего не происходит. Только в окне "Probe Watch" появилось значение Handle. И это хорошо.


Отключаем плату, список устройств очищается. Нажимаем "Программировать". Вот тут-то выскакивает окно с отчетом об ошибке.


Окно отчета


После нажатия кнопки "Continue", ВП завершает свою работу.


Стоит запретить нажимать кнопку, если не найдено ни одного устройства. Модифицируем кейс "Timeout" обработчика событий. Напомню, два раза в секунду сканируются подключенные к ПК чипы FTDI, если таковые обнаружены и могут быть использованы для программирования ПЛИС, то через свойство Strings[] их дескрипторы добавляются в Devices list. Создаем для "Программировать" свойство Disabled, и, если годных устройств не обнаружено, то отключаем и затемняем кнопку.


Case Timeout


Картинка кликабельна


Осваиваем GPIO


После того, как MPSSE активирован, работа с ним осуществляется через так называемые "op-code", а из функций API D2XX используется только FT_Write, FT_Read и FT_Queue (чтобы узнать статус буфера приемника). По наторенной дорожке создаем соответствующие VI: FT_Write.vi, FT_Read.vi, FT_Queue.vi.


Немного рутины


FT_Write.vi



Блок-диаграмма. FT_Write.vi



FT_Read.vi



Блок-диаграмма. FT_Read.vi



FT_Queue.vi



Блок-диаграмма. FT_Queue.vi


Теперь из этих трех кирпичиков выкладываем ВП для чтения параллельного порта и записи в него. Значение удобно представить в виде массива булевых переменных.


MPSSE_Set_LByte.vi и MPSSE_Get_LByte.vi


MPSSE_Set_LByte.vi



Блок-диаграмма. MPSSE_Set_LByte.vi



MPSSE_Get_LByte.vi



Блок-диаграмма. MPSSE_Get_LByte.vi


Каюсь, мне было лениво создавать именованный список для всех op-code, поэтому оставил их в виде Magic Numbers.


Как говорилось в самой первой статье протокол загрузки ПЛИС "Passive Serial" есть ничто иное как SPI с дополнительной манипуляцией флагами. Всего используется пять ножек: линии DCLK, DATA[0], nCONFIG должны быть сконфигурированы как выхода, линии nSTATUS, CONF_DONE — как входы.


Распиновка схемы в виде таблицы
FPGA pin Pin Name Pin MPSSE Direction default
DCLK BDBUS0 38 TCK/SK Out 0
DATA[0] BDBUS1 39 TDI/DO Out 1
nCONFIG BDBUS2 40 TDO/DI Out 1
nSTATUS BDBUS3 41 TMS/CS In 1
CONF_DONE BDBUS4 43 GPIOL0 In 1

Нам понадобится ВП, который сможет менять значение на выбранной ножке не затрагивая все остальные. Первым делом создаем Enum с порядковыми номерами ножек в порту, сохраняем в виде "Strict Type Def" в файл SP_LBYTE_BITS.ctl. Создаем новый ВП, добавляем привычные терминалы потока ошибок. Считываем текущее значение параллельного порта с помощью MPSSE_Get_LByte.vi, с помощью функции Replace Array Subset модифицируем нужный бит и записываем значение обратно в порт (MPSSE_Set_LByte.vi).


SP_Set_Flag.vi


SP_Set_Flag.vi



Блок-диаграмма. SP_Set_Flag.vi



Enum SP_LBYTE_BITS.ctl


Для начала конфигурации контроллер MPSSE должен генерировать переход из низкого уровня в высокий на линии nCONFIG. Как только ПЛИС будет готова к приему данных, она сформирует высокий уровень на линии nSTATUS. На данном этапе у нас все готово для эксперимента в железе. На блок-диаграмму SP_FT_MPSSE_FPGA.v добавляем управление линией nCONFIG — после инициализации MPSSE подаем низкий уровень, а затем высокий. После каждой операции (для отладки) считываем состояние ножек порта.


SP_FT_MPSSE_FPGA.vi


Во время запуска



Блок-диаграмма


В целом, во время запуска VI видно, что ПЛИС реагирует на переход на линии nCONFIG — на ножке nSTATUS устанавливается ноль, а затем единица. Но не будет лишним проконтролировать это с помощью осциллографа. Годится почти любой двуканальный осциллограф с возможностью запуска по триггеру (ждущий режим). Канал А (синий трек) я ставлю в контрольную точку цепи nCONFIG, канал B (красный трек) — цепь nSTATUS. Триггер настроен на спадающий фронт канала A.



Картинка кликабельна. С подробностями!


Работа с файлом


ПЛИС готова принять файл конфигурации. А готовы ли мы передать файл в ПЛИС?


LabVIEW содержит обширный набор инструментов для работы с файлами. Не скажу, что функционала хватает на абсолютно весь спектр задач, однако базовые операции типа чтение и запись выполняются легко и приятно. Основной набор VI для работы с файлами можно найти в палитре "File I/O". Для решаемой задачи требуется открыть файл конфигурации, оценить его размер (нам нужно знать, сколько байт отправлять ПЛИС), прочесть его и закрыть. Все просто и друг за другом. Используем ВП Open/Create/Replace File, Get File Size, Read from Binary File, Close File, объединяем их цепочкой потока ошибок и refnum — число, типа файлового дескриптора, создается при открытии файла и должно быть передано на вход другим ВП, работающим с этим файлом.


Пока нам некуда утилизировать считанные данные, но если очень хочется проверить работоспособность цепочки, то можно создать индикатор типа String и немножко настроить его. В контекстном меню активируем опцию "Hex Display", включаем вертикальный скроллбар (Visible Items -> Vertical Scrollbar) и после запуска наблюдаем содержимое бинарного файла конфигурации.


SP_FT_MPSSE_FPGA.vi


Передняя панель. Смотрим на содержимое файла



Блок-диаграмма. Каринка кликабельная


На блок-диаграмме ВП образовалось две независимые параллельные линии кода, поэтому для них используются раздельные цепочки ошибок. Для того, чтобы свести параллельные потоки в один терминал Error Out, используется функция Merge Errors. Эта функция просматривает ошибки на входе сверху вниз (да, там может более двух входных терминалов, растягивается мышкой) и возвращает первую, которую найдет. Если ошибок нет, то возвращает первое попавшееся предупреждение. Если и предупреждений не обнаружено, то на выходе ошибка отсутствует. Важно отметить, что порядок подключения входов Merge Errors определяет приоритет ошибок, и если ошибка возникнет сразу в двух цепочках, то нижняя ошибка будет проигнорирована. К этому нужно относиться внимательно.


Если мы попытаемся в ВП верхнего уровня нажать кнопку "Программировать" не выбрав файл, то на вход SP_FT_MPSSE_FPGA.vi поступит пустой путь, что вызовет ошибку "Error 1430. LabVIEW: (Hex 0x596) The path is empty or relative. You must use an absolute path." Как говорит мой друг детства: "Пустяки, дело-то житейское!". И ошибка эта — вовсе не ошибка, а так, невнимательность пользователя. Останавливать программу и ругаться на него окном с красным крестиком мы не будем, просто удалим ошибку с этим кодом из потока и в диалоговом окне порекомендуем пользователю определиться с файлом. Для фильтрации ошибки используем ВП "Clear Errors" из палитры "Dialog&User Interface". Для вывода сообщения — "One Button Dialog".



Блок-диаграмма


Картинка кликабельна


Загрузка конфигурации


Для последовательной передачи данных процессору MPSSE нужно послать op-code 0x18, аргументами команды будет длина передаваемой последовательности (два байта, начиная с младшего), и сама последовательность данных. Длина кодируется за вычетом единицы. Отправку блока данных оформим в виде ВП MPSSE_send.


MPSSE_Send.vi


MPSSE_Send.vi



Блок-диаграмма


Размер входного буфера (Array Size) преобразовываем к двухбайтовому типу U16, отнимаем единицу, меняем местами младший и старший байт (Swap Bytes) — отправлять длину нужно начиная с младшего, и преобразовываем двухбайтовое число в однобайтный массив (Type Cast).


Функция Type Cast заслуживает отдельного внимания. Это такой универсальный преобразователь типов, сообразительность которого порою сильно удивляет. Если коротко, то:



Наглядно для програмиста


Однако это не просто приведение данных к другому типу, это еще и эвристическая интерпретация. Эта функция позволяет выполнять преобразование между несовместимыми типами данных, при этом функция не брезгует выравниванием входных данных и даже удалением "лишних" частей. Если запрошенный тип данных требует памяти больше, чем у входных данных, то функция выделит недостающий объем. Для начинающего разработчика LabVIEW Type Cast может стать палочкой-выручалочкой, но с взрослением, лучше от такого преобразователя отказаться — сильно много скрыто от глаз и может стать источником непредвиденных ошибок. Лучше использовать более явные методы преобразования, например, Coerce To Type.


При инициализации процессора MPSSE, мы задали максимально допустимый размер буфера для передачи данных в 65536 байт, следовательно файл конфигурации мы должны разделить на фрагменты, размер которых не превышает указанный размер. Воспользуемся функцией Array Subset, эта функция выделяет из массива подмассив начиная с элемента index и длинною length. Разбивать будем в цикле While, каждую итерацию индекс будем увеличивать на 65536, между итерациями значение передадим через сдвиговый регистр. Как только не удастся от основного массива отщипнуть 65536 байта, берем все, что осталось, отправляем и останавливаем цикл.


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


SP_FT_MPSSE_FPGA.vi


Картинка кликабельна


Для того, чтобы понять успех прошивки, считаем флаги, и, если CONF_DONE установлен в единицу, рапортуем ВП верхнему уровня, что все ОК.


Программа завершена. Осталось убедиться, что ПЛИС успешно прошивается, а плата счастливо мигает светодиодиками.


Про именование ВП


Ни для кого не секрет, что в классическом программировании всем пользовательским объектам и функциям нужно давать осмысленные имена, то же можно сказать и о LabVIEW, особенно, если в роли объектов выступает SubVI. Я привык имена файлам ВП давать на основе их места в иерархии разрабатываемого ПО. В текущем приложении можно выделить четыре уровня абстракции:


  • Самый низкий уровень — это ВП, выполняющие непосредственное взаимодействие с FTDI, в большинстве своем они сводятся к вызову соответствующей функции из API D2XX. В своем проекте имена ВП этого уровня я начинал с префикса "FT", например FT_Close.vi или FT_Read.vi.
  • Второй уровень — это взаимодействие с процессором MPSSE. Имена ВП этого уровня начинаются с префикса "MPSSE". Пример: MPSSE_open.vi, MPSSE_Set_LByte.vi, MPSSE_Get_LByte.vi.
  • Третий уровень — это реализация протокола "Passive Serial" поверх MPSSE. Все файлы имеют префикс "SР". Например, SP_FT_MPSSE_FPGA.vi (жуткое имя, состоящее из аббревиатур) и SP_LBYTE_BITS.ctl.
  • Уровень приложения. ВП верхнего уровня. Имя может быть произвольным, человекоориентированным.

Если проект достаточно большой (десятки ВП), то для каждого уровня файлы лучше хранить в отдельных директориях с соответствующим названием. В нашем проекте все ВП разместились в одной папке subVI.


Заключение


Может показаться, что описание процесса излишне подробно, но уж очень не хотелось создать очередное пособие по рисованию совы.


Рисуем сову


Я не пытался сделать справочник или учебник по языку, я хотел показать процесс создания приложения на LabVIEW, показать как строится логика разработки в этой среде. Человек со стороны поймет, нужно ли это ему вообще, начинающий разработчик несомненно почерпнет для себя много нового, профессионал снисходительно улыбнется и вспомнит себя в молодости (либо кинет в меня помидором). А мне будет куда направить моих студентов и дипломников.


Материалы по теме


  1. Блюм П. LabVIEW: стиль программирования. Пер. с англ. под ред. Михеева П.– М.:
    ДМК Пресс, 2008 – 400 с.: ил.
  2. labview_mpsse. Репозиторий с проектом.
  3. Учебный стенд для ЦОС. Железо для опыта
  4. Software Application Development D2XX Programmer's Guide. Руководство по API D2XX.

Комментарии (12)


  1. proton17
    12.11.2018 10:08

    А есть возможность все это не мышкой рисовать, а прописать кодом в блокноте и потом просто загрузить в LabView?


    1. Shamrel Автор
      12.11.2018 10:20

      К сожалению нет. Да и смысл? Можно открыть Qt Creator и прописать все, и загружать ничего никуда не потребуется.
      А если серьезно, иногда очень не хватает импорта некоторых форм из текстовых языков. Например, было бы здорово импортировать enum из сишного хедерника.
      Но если есть желание поиметь инструментарий LabVIEW и писать обычным кодом, то стоит взглянуть на продукт NI LabWindows.


      1. proton17
        12.11.2018 10:21

        Мы как-то общались с народом из NI на тему создания стенда для проверки нашего оборудования. Нашим программистам не очень понравилось. Задали три вопроса:
        — можно ли писать текстом
        — есть ли поддержка питона
        — есть ли поддержка linux
        На все вопросы ответ нет(((


        1. Shamrel Автор
          12.11.2018 10:49

          Для текста нужно использовать NI LabWindows. Поддержка линукс есть. Про питон не знаю, но сомневаюсь.


          1. proton17
            12.11.2018 11:09
            +1

            Тут как обычно дьявол в деталях. Если надо просто LabView на десктоп, то пожалуйста — linux есть. Но если нужна система с PXI-контроллером (встроенный комп NI) то тут только Windows и точка. Да и на практике оказывается что там куча проблем с дровами под линукс. Таже хрень и с питоном, вроде как поддержка есть, но делается она чуть ли не средствами комьюнити и опять же куча железа не окучена. Короче у ребят очень крутое железо, хороший софт, но все жутко проприетарное, как у Apple, ни шагу в сторону. Если нужна гибкая система это не всегда здорово.


        1. AndreyDmitriev
          12.11.2018 15:58
          +1

          поддержка питона появилась в 2018
          Python Resources for NI Hardware and Software
          Но вообще не стоит сранивать с текстовыми языками.
          Я много лет назад пересел с Дельфи на LabVIEW. Тошнотворный привкус изчез где-то через пару недель.
          Ну ещё от области применения довольно сильно зависит — если всё завязано на железки NI, то с текстовым языком возни будет сильно больше.
          Для тестовых стендов есть NI TestStand.


          1. Shamrel Автор
            12.11.2018 16:05

            Я так и не пересел на LabVIEW. Там где приходилось его использовать, выкручивался следующим образом: основной код делал на С/С++ в виде dll, а на LabVIEW только GUI. Такой подход меня спасал наверное только по тому, что я не работал с железяками NI — у нас были самопальные контроллеры.


            1. AndreyDmitriev
              12.11.2018 17:22
              +1

              Да, у нас тоже есть самопальные железки и я только через библиотеки их и подключаю. Но за много лет я таки нашёл несколько сильных сторон в этой среде разработки и в общем-то не всё так уж плохо. Я всё собираюсь несколько туториалов «с нуля» написать, в которых рассмотреть этот язык с точки зрения «языка общего назначения», да всё руки не доходят. Причём взять LabVIEW NXG для изучения — уже вышла третья версия. Эта версия ещё не доросла до того, чтобы делать что-то серьёзное, однако для обучения графическому программированию — самое то, как мне кажется. У меня, кстати, в основном проекте уже почти семь тысяч SubVI с контролами и ничего — полёт нормальный.


            1. Iryaz
              12.11.2018 19:29

              LabView для GUI по моему только и пригоден. Остальное делать на нем — это гемор


          1. proton17
            12.11.2018 16:10

            Да, питон вот-вот появился официально, до этого поддержка осуществлялась только самими пользователями. И даже сейчас часть интересующих нас железок не имела поддержки через питон. Возможно за пару лет допилят. А по поводу графического интерфейса — это конечно на любителя. Когда простые тестовые задачи, наверное, это удобно. Но когда нужны очень сложные проверки это становится как-то геморно. Нам показывали большие проекты, так вот там что-то оперативно поменять очень сложно. Нужно сделать 100500 кликов мышкой и переходов по всяким пунктам меню и спискам вместо изменения 10 строк питоновского кода. Да и хранить такие проекты в гите та еще задача. У нас повсеместно и для ПО и для Verilog используется GitLab. Он работает с текстовыми файлами. Всегда видно кто что и когда изменил. Тут же это отследить невозможно. Для любой модификации теста на месте нужен LabView, что не всегда возможно. TestStand нам тоже показывали — проблемы те же. В общем под наши задачи это все не подошло, хотя железо конечно шикарное, претензий нет)


  1. Iryaz
    12.11.2018 19:27

    У меня рука отнималась после долгой работы мышкой, когда пробовал программу накидывать на LabView. Лучше все-таки текстом