
В разные периоды я тестировал свою среду разработки, компилятор и рантайм на разных МК — от STM32G030 до FPGA Altera Cyclone 4. Минимальные требования к рантайму — это 5 КБ ОЗУ и не менее 32 КБ Flash, либо 3000 LUT, если это FPGA. Мой основной тестовый стенд — это системы с относительно ограниченными ресурсами. Не 8-битные микроконтроллеры, но и не обязательно ESP32. ОЗУ от 12–20 КБ — это уровень, на базе которого можно создать настоящий ПЛК с вытесняющей многозадачностью, заменой кода на лету, RS-485 и онлайн-отладкой.
Классически я тестировал все МК на Ladder-программе, так как различные бренды — производители ПЛК часто публикуют данные выполнения дискретной логики в документации, что очень удобно для сравнения.
Методика тестирования.

Дискретная логика оценивается по среднему времени выполнения контактов и катушек в сложном ранге. Под сложным понимается ранг со множеством ветвлений: здесь, помимо обработки самих контактов, компилятор неявно вставляет дополнительные инструкции для сохранения промежуточных результатов вычисления цепей.
При разработке среды я ориентировался на Allen-Bradley, поэтому те, кто знаком с их ПО, сразу узнают знакомый дизайн — неограниченные сложные ветвления в рангах и характерный функционал.
Однако есть и отличия. Поскольку я ориентировался на языки высокого уровня (такие как ST), то создавал полноценный собственный компилятор, и встроенной поддержке сложных типов данных. Прямо в цепях Ладдера можно использовать следующие конструкции (можно делать короткие псевдонимы, аналоги #define на СИ):

Второй тип тестов - наиболее часто используемые функциональные блоки: таймеры, триггеры, счетчики.

Сам рантайм представляет собой софт-процессор (виртуальное ядро с программными регистрами R0–R32). Это обеспечивает полную абстракцию от железа и позволяет мне всего за два часа развернуть ПЛК на любом микроконтроллере. Из минусов — производительность в 3–5 раз ниже, чем у нативной программы, однако в 5–10 раз выше, чем у Lua или MicroPython (а самое главное — выполнение строго детерминировано по времени).
С точки зрения нативной части внутри МК, в которой содержатся программа ПЛК, данные, стек и прочее, представляет собой единый массив:
__attribute__((aligned(512))) uint8_t memory[SIZE_MEMORY];
SIZE_MEMORY - размер который можно выделить под программу для ПЛК. В данный момент, у меня единая область, нет разделения на память инструкций или данных: больше программа/меньше данных, меньше данных тогда влезет больше программа. Сам мк тестировался давно, код может не соответствовать местами, но принцип тот же, глобальный массив и указатели на обработчики.
Из IDE прошивка попадает в МК по UART. После сверки хешей, начинается выполнение. В цикле идет чтение программы:
dec.ui = __builtin_bswap32(*(uint32_t*)&memory[PC]); void (*instruction_handler)(void) = (void (*)(void))cpu.instruction[dec.b[3]]; instruction_handler();
cpu.instruction - это массив указателей на обработчики.
PC - это один из 32 софт-регистров, является адресом инструкции.
Производительность
Один ранг с 40 булевыми инструкциями и шестью ветвлениями (как на скриншоте выше) выполняется за 0,5 миллисекунды. Здесь важно иметь в виду, что, помимо этих 40 инструкций, компилятор(вернее транслятор Ladder) неявно добавляет около 25 инструкций для сохранения промежуточных результатов вычислений в ветках( 3-4 инструкции на ветку ).
Время выполнения функциональных блоков:
Таймер: 80–320 мкс.
Счётчик: 80–390 мкс.
Триггер: 20–120 мкс.
Максимальное значение соответствует полному циклу работы функционального блока, когда сработали все условия. Если, к примеру, таймер не активирован, то его выполнение занимает всего 20–25 мкс.
Таким образом, за цикл в 10 миллисекунд будет отработано около 10 таких сложных рангов с учётом накладных расходов на чтение/запись портов. Отправку 128 байт данных в кадре, на хост по 4400 bod\sec может добавить в несколько сотен мсек, если блокирующий режим. Тут зависит от реализации выполнения и скорости передачи.
Процесс онлайн мониторинга в среде, на момент работы с MIK32 еще не был готов, но сейчас это выглядит так:
Зная точное время выполнения таймеров, счётчиков и триггеров, можно легко рассчитать общее время обработки программы, если добавить в эти ранги необходимое количество указанных функциональных блоков. Так же можно рисовать, и создавать собственные функциональные блоки, добавлять их в библиотеку. Детальнее можно посмотреть в моих прошлых постах, или в этом видео чтоб не искать:
Это не коммерческая разработка, я не провожу каких то оптимизаций под конкретный микроконтроллер для производительности. Мне важнее пока легкая переносимость на разные чипы и быстрые изменения. Для этого создавал собственный компилятор - иметь завершенный полный стек, от IDE до рантайма на железе, который позволяет устанавливать и отлаживать все несколькими кликами мышки , без всяких настроек путей, каких то портов, ввода консольных команд, и прочее.
Slym99
Вот объясните мне: как версионировать, мерж/diffить код написанный картинками?
есть ли выгрузка/загрузка в текст который потом глазками diffить...
zoshytlogic Автор
Не все слова понимаю из вопроса.
Если перевод картинку - в команду, то в моих прошлых двух постах есть несколько больше информации:
1) https://habr.com/ru/articles/1103196/
2)https://habr.com/ru/articles/1103386/
Коротко, то картинок (типа jpeg) и подобного нет. Есть векторная графика : список фигур и линий, из которых получается рисунок, а вместе с рисунком есть набор инструкций которые понимает мой компилятор. В конце, каждый получает свое, человек картинку, компилятор - текстовую команду.
Когда пользователь нажимает на вставку картинки/функционального блока, то в конце при компиляции, вместо картинки вставляется - код, который описывает что делать в этом участке кода.
Например, на рисунке есть контакт , на вид как --| |-- , а при компиляции картинка заменяется инструкцией ANDM R0 Variable0; , еще чуть дальше в обработке ANDM R0 Variable0; превращается в ANDM R0 Port12; Где Port12 это уже ваша переменная в том месте программы.
max_dark
Речь о системах контроля версий (
gitкак пример, https://git-scm.com/book/ru/v2)Помнится огромная боль с переносом изменений между версиями проекта в TIA Portal и подобных…
zoshytlogic Автор
А, спасибо! Есть .xml файл проекта, который содержит все : построение веток, инструкций, переменные и т.п. там на видео, с отладкой в реальном времени, и есть открытые проекта, файл .xml
Ветки, ladder программа хранится в этом фале проекта в скрипте текстовом, выглядит как последовательность строк типа @LOD(...); @ LDN(...); их можно как текст копировать/вмтавить и схема перерисуется.
Библиотека функциональных блоков, так же но отдельный файл .xml, он в интерфейсе программы сверху, вкладки типа binary, timers ...Если что то свое нарисовали, пид регулятор какой, то онихранится как модель ПЛК. Но думаю если б я выходил на рынок, то организовал бы эти .xml под международный открытый стандарт, который позволяет переносить проекты между производителями ПЛК
max_dark
Как по мне,
xmlне самый удобный для слияния формат - весь файл можно оформить одной строкой.В добавок в случае
xmlпредполагается, что программист знает устройство его внутренностей(которое не стандартизировано)ИМХО, тут бы бы удобнее
IL(Instruction list) либоST(Structured Text)zoshytlogic Автор
Программа, сама, на низком уровне (для рантайма) это и есть ассемблерные инструкции:
ADDI R28 @SymbolAddress(Thread.Stack.R);SDR R28 CNXT @SymbolAddress(PC);SDR R28 CNXT @SymbolAddress(CNXT);Но это уже скомпилированный файл, это не ветки, это как открыть через блокнот .exe программу, АСУ ТПшник с этим кодом встречаться не будет если не хочет.
Ladder программа/вернее скрипт который внутри .xml выглядит как:
Начало ветки:
@LOD(TimerOff.Dn); // контакт
@TON(TimerOn,500,0);// таймер
конец ветки
...
Это аналог XIC XIO BST BND у Allen Bradley - вставляете этот скрипт, и лестница нарисовалась. Этот скрипт, и находится в .xml. Версии проекта, это история изменения именно этого скрипта который внутри .xml
zoshytlogic Автор
внутри .xml это выглядит так
SRG - это начало ранга. INF - это типа цветной комментарий и.тд
Среда IDE читает эту последовательность, и рисует схему.
IL вроде как признали устаревшим, не знаю есть ли смысл его внедрять, только для совместимости