Создание функции main специфичной для целевой платформы¶
В данном примере показано как использовать шаблоны генератора кода Engee для генерации функции main()
. Это позволяет сгенерировать функцию main
содержащую пользовательский код (например, платформозависимый код с настройками таймеров МК и т.д.). Так же этот подход позволяет встроить код модели в ОСРВ.
Пример - модель счетчика на конечном автомате¶
В качестве примера возьмем счетчик, реализованный с помощью конечных автоматов. Реализация содержится в модели Counter_PWM:
demoroot = @__DIR__
mdl = engee.load(joinpath(demoroot,"Counter_PWM.engee"); force = true)
engee.open(mdl)
Предположим, требуется вызывать этот счетчик с частотой 20 Гц и имплементировать его на разных аппаратных платформах: STM32F4 и Arduino.
Принцип работы счетчика¶
Принцип работы счетчика заключается в том, что аккумулятор инкрементируется на каждом шаге симуляции. Если значение аккумулятора достигает порога THRSHLD, задаваемого входной константой, то аккумулятор сбрасывается и поднимается флаг ISR. Для THRSHLD равного 4 результат работы выглядит следующим образом:
Что бы удостоверится, что система работает корректно, по флагу ISR будем включать или отключать светодиод.
Шаблоны для main¶
Мы уже знаем, что код для блоков можно настроить при помощи шаблонов генератора исходного кода. Тоже самое можно сделать и для main. Главное отличие - объем целевого кода в шаблонах main будет значительно больше, чем объем кода на хост-языке. Так же, применение шаблона main возможно только при использовании командного управления генерацией исходного кода.
В качестве примера рассмотрим простейший шаблон для Arduino:
run(`cat "arduino_main.jl"`)
Как видно, шаблон представляет собой почти чистый Си-код, с включениями специальных директив вида $model_<>
В отличии от обычных функций, применяемых в шаблонах, эти директивы раскрываются как вызовы соответствующих функций API модели. Например, вызов $model_step
для модели Counter_PWM раскроется как Counter_PWM_step();
Для генерации main для каждой из тестовых платформ воспользуйтесь переключателем:
и запустите кодовые ячейки ниже:
target = "Arduino" # @param ["STM","Arduino"]
hw = lowercase(target);
engee.generate_code(joinpath(demoroot,"Counter_PWM.engee"),
joinpath(demoroot,"$(hw)_code"),
target = "c",
template_path = "$demoroot/$(hw)_main.jl");
Посмотреть сгенерированный код можно с помощью команды ниже:
src = "$(hw)_code/main.c";
run(`cat $src`)
Сборка результирующего кода¶
Сборка для STM¶
Шаги для сборки описаны в примере Мигающий светодиод на STM32F4 в разделе Выполнение модели на STM32
Cборка для Arduino¶
Шаги для сборки описаны в примере Генерация кода для Arduino (генерация ШИМ сигнала) в разделе Перенос модели на Arduino. Единственное улучшение - мы сразу переименуем main.c в arduino_code.ino
mv("./arduino_code/main.c", "./arduino_code/arduino_code.ino";force=true)
Демонстрация работы (STM32)¶
Наконец, убедимся в том, что пример работает. Для этого воспользуемся платой STM32F4 Discovery. Соберем проект и загрузим его на плату. Видно, что светодиод начинает мигать:
Вывод¶
Шаблоны для функции main позволяют генерировать обвязку для кода модели, специфичную для аппаратной платформы. Таким образом обеспечивается полная переносимость алгоритмов.