К встраиваемым относятся программные системам исполняемые на устройствах с ограниченной мощьностью. Часто к таким системам выдвигаются особые требования надежности, работы в реальном времени, ограниченное потребление и пр.
Ada отлично подходит для реализации таких систем в силу свойственных языку возможностей. Поскольку Ada это компилируемый язык, программы на нем очень энерго эффективны. Изначальная ориентация языка на надежность и безопасность гармонирует с целями разработки встраиваемых систем. Гибкие возможности спецификации представления позволяют легко взаимодействовать с железом на низком уровне. В то же время, мощная система типов позволяет естественно выражать понятия понятия прикладной области. Наконец, в стандарте языка есть отдельный раздел посвященный поддержке встраиваемых систем и систем реального времени. Реализуя требования стандарта, Ada позволяет программировать устройства без необходимости использования универсальных операционных систем, в тоже время предлагая эффективную поддержку многозадачного окружения на устройствах с ограниченными возможностями.
Целью этой статьи является помочь начинающим разобраться с существующим инструментарием программирования встраиваемых систем на Ada на примере создания простой программы. Мы рассмотрим установку и настройку ПО на примере платы разработчика STM32F40x.
Для разработки встраиваемых систем нам нужны следующие инструменты
- Кросс-компилятор
- Библиотека времени исполнения (Runtime Library)
- Библиотеки драйверов (например Ada Drivers Library)
Кросс-компилятор позволяет собирать исполняемые модули для процессора отличного от текущего. Например, построить код для ARM используя рабочую станцию на AMD64. Пакетный менеджер Alire имеет несколько готовых к использованию кросс-компиляторов для следующих архитектур процессоров:
- ARM
- AVR
- RISC-V
- xtensa_esp32 (экспериментальный, не рекомендуется для начинающих)
Для поддержки нетривиальных конструкций языка нужна библиотека времени исполнения. Обнаружив такую конструкцию в коде пользователя компилятор ищет в библиотеке времени исполнения соответствующие типы и подпрограммы и использует их. Таким образом, RTL тесно связана с кросс-компилятором и выход новой версии компилятора требует библиотеки времени исполнения соответствующей версии.
Не все конструкции языка Ada востребованы во встраиваемых системах. Например, обработка исключений считается слищком наклажной, чтобы реализовать ее в полном объеме. В зависимости от реализуемых конструкций языка библиотеки времени исполнения делятся на несколько типов. В данный момент с GNAT доступны три типа RTL
- light - минимальная версия библиотеки, без поддержки многозадачности и других конструкций
- light-tasking - с ограниченной поддержкой многозадачности, так называемые Ravenscar, jorvik профили
- embedded - еще более жирная библиотека времени исполнения
Библиотеки времени исполнения расчитаны на использования расчитаны на конкретное железо, поскольку включают в себя код инициализации и распределение ресурсов. Кросс-компиляторы для ARM и RISC-V идут с набором библиотек RTL для наиболее популярных устройств разработки. Поддержка других устройств может распространятся, как отдельные Alire crates.
Для микропроцессоров встраиваемых систем свойственно иметь богатый ассортимент вспомогательных устройств таких как порты ввода-вывода общего назначения, таймеры, UART, SPI, I2C и пр. Для работы с этими устройствами нужны соответствующие драйвера. Наверное, наиболее полной поддержкой драйверов может похвалится Ada Drivers Library (ADL). ADL распространяется под BSD лицензией и включает в себя код драйверов устройств микропроцессоров, а также драйвера внешних стройств, таких как датчики, дисплеи, камеры и пр. Также репозиторий ADL предоставляет примеры использования драйверов для некоторых плат разработки.
Поскольку ADL был создан до появления Alire, эти два инструмента плохо совместимы. Часть кода ADL была скопирована в Alire как отдельные crates, чтобы еще больше всех запутать.
Давайте рассотрим создания минимального приложения на примере микроконтроллера
STM32F407. На рынке есть несколько плат разработчика на основе этого недорогого
процессора, начиная от Discovery Board и заканчивая китайскими STM32 F4VE.
Библиотека времени исполнения для этого чипа носит название light-tasking-stm32f4
.
Мы начнем с создания приложения в терминале без использования среды разработки, чтобы осветить, как все устроено внутри, а затем отдельно остановимся на поддержке таких проектов в GNAT Studio.
Alire помогает нам создать подходящую заготовку для проекта:
alr init --bin test
cd test
Следующий шаг - указать кросс-компилятор в зависимостях проекта:
alr with gnat_arm_elf
Чтобы проектный менеджер gprbuild
знал, что нужно использовать
кросс-компилятор необходимо указать Target
. Проще всего это сделать
в проектном файле. За одно укажем какая библиотека времени исполнения
нам нужна. Отредактируем test.gpr
добавив следующие строки:
for Target use "arm-eabi";
for Runtime ("Ada") use "light-tasking-stm32f4";
Код программы (test.adb
) сделаем максимально простым:
with Ada.Text_IO;
procedure Test is
begin
loop
Ada.Text_IO.Put_Line ("Hello");
delay 1.0;
end loop;
end Test;
Все готово, чтобы собрать исполняемый файл:
alr build
Преобразуем получившийся ELF в бинарный файл подходящий для прошивки
alr exec -- arm-eabi-objcopy -Obinary bin/test bin/test.bin
Для прошивки процессоров STM32 обычно используется аппаратный отладчик ST Link v2.
Discovery board имеет его интегрированным прямо на плате. (Подойдет также и
DAPLINK.) Для управления аппаратным отладчиком можно использовать программное
обеспечение st-util
, либо пакет с открытым исходным кодом OpenOCD (который
умеет также управлять DAPLINK).
Команда для прошивки:
st-flash --connect-under-reset write bin/test.bin 0x08000000
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg -c 'program bin/test.bin verify reset exit 0x08000000'
Давайте воспользуемся отладчиком, чтобы посмотреть, как исполняется наша программа. В одном окне консоли активируем аппаратный отладчик:
stutil --semihosting # или
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg
А в другом запустим GDB:
alr exec arm-eabi-gdb ./bin/test
target extended-remote :4242
target extended-remote :3333
monitor arm semihosting enable # только для OpenOCD
Чтобы заставить GNAT Studio запускать st-util
для прошивки и отладки достаточно в
файл проекта добавить следующий код:
package Ide is
for Program_Host use "localhost:4242";
for Communication_Protocol use "remote";
for Connection_Tool use "st-util";
end Ide;
Теперь запустим студию:
alr exec gnatstudio
Студия распознает что этот проект для встраиваемых систем и позволит вам собирать, прошивать и отлаживать его с помощью GUI.