Язык Ada на Atmel SAM4 (Cortex-M) - быстрый старт

Введение

Недавно мне в руки попал оценочный комплект Atmel® SAM4S Xplained Pro evaluation kit производства компании Atmel. Ядром этого комплекта является мощный микроконтроллер на базе современной архитектуры Cortex-M. AVR-контроллеры фирмы Atmel весьма популярны в России ввиду невысокой цены и хорошей функциональности. Было тем более интересно познакомиться с их более мощным и современным собратом.

Имея опыт, на предыдущих местах работы, программирования встроенных устройств на Си и Ассемблере, в том числе AVR-контроллеров и некоторых других процессоров RISC-архитектуры с одной стороны, и, опыт в совсем другой области - программировании сетевых приложений на языке Ada, мне было также интересно попробовать совместить то и другое - программировать микроконтроллер на Ada.

Тем более, что одной из главных сфер применения Ada как раз и является создание встроенных приложений, систем реального времени повышенной надёжности.

Вероятно, самой известной реализацией компилятора языка Ada является реализация компании AdaCore, выпускаемая под маркой GNAT. Существует как профессиональная платная версия - GNAT Pro, так бесплатная версия - GNAT GPL, предоставляемая в целях обучения и для разработки приложений под лицензией GPL и имеющая ту же функциональность, но без поддержки.

Различные версии компилятора, для различных хост- и целевых платформ, графическую среду разработчика, другие инструменты, исходные коды, а также множество библиотек, можно бесплатно загрузить с сайта компании.

Язык Ada используется много десятилетий прежде всего для построения больших систем, работающих на серьёзном оборудовании, в том числе, в авиации, железнодорожном транспорте и телекоммуникациях (www.adacore.com/customers). Однако, в последние годы, разработчики AdaCore повернулись лицом к младшим братьям - микроконтроллерам, и компания выпустила ряд продуктов для разработки программного обеспечения для микроконтроллеров AVR и ARM.

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

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

Поэтому, в первую очередь, цель данной статьи - обеспечить быстрый старт желающим опробовать разработку на языке Ada для платформы Cortex-M. Это ни в коем случае не учебник по языку Ada, ни руководство по применению микроконтроллера SAM4, то и другое даже в отдельности слишком объёмный предмет. Все примеры носят характер экспериментов, и могут лишь служить исходным пунктом для написания "настоящих" приложений.

Статья может быть полезна и начинающим разработку для аналогичной платформы STM32F на базе Cortex-M c помощью компилятора GNAT или для AVR тем же компилятором. И, в какой-то степени, на языке Си для SAM4S (или близкого контроллера от Atmel).

Все файлы примеров и утилит можно взять здесь.

1. Оценочный комплект

Использование демонстрационной (оценочной) платы микропроцессора (microprocessor development board, evaluation board) несомненно самый простой путь для разработчика оборудования ознакомиться с архитектурой, и оценить возможность её применения для решения собственных задач. Во-первых, в этом случае ему нет необходимости нечто подобное проектировать и изготавливать (принципиальная схема, разводка платы, фотошаблоны, травление, пайка элементов) прежде, чем решит, что данный микропроцессор ему подходит. А во-вторых, с такой платой обычно поставляются (выкладывается в открытый доступ) файлы заголовков, библиотеки функций, примеры приложений, которые избавляют программиста от тривиальной, но нудной работы и ускоряют старт. В данном случае мы имеем не только плату микропроцессора, но целый kit с некоторыми дополнительными устройствами, которые могут быть также полезны для встроенного применения.

Плата SAM4S

Это плата процессора, на которой установлена дополнительная микросхема FLASH-памяти (NAND) на 2 Гб, кварц, переменный резистор для подстройки эталонного напряжения АЦП, кнопка RESET, кнопка общего назначения SW0, светодиод общего назначения LED0, светодиод RESET, светодиод POWER, светодиод STATUS (моргание которого показывает интенсивность обмена по DEBUG USB). Разъём USB для питания и отладки - DEBUG USB, разъём USB общего назначения SAM4S USB, разъём для внешнего LCD - LCD CONNECTOR, три разъёма для плат расширения.

На обратной стороне платы размещён также разъём кардридера SD-Card и чип отладчика EDBG.

Плата может быть запитана подключением USB-кабеля к разъёму DEBUG USB и с другой стороны к источнику питания USB или компьютеру. Также есть отдельный четырёхштырьковый разъём питания. После включения и сброса процессор запускает программу из флэш, если там что-то прошито.

Немаловажной деталью устройства является чип "The Atmel Embedded Debugger (EDBG)" установленный на обратной стороне платы и подключенный к разъёму DEBUG USB. Будучи соединённым через последовательные каналы TWI, SPI, UART с процессором, он позволяет выполнять отладку приложения используя протокол OpenOCD (Open On-Chip Debugger).

Кроме того, EDBG создаёт на хост-компьютере виртуальный ком-порт Virtual COM Port, который может служить приложению в качестве стандартного ввода вывода.

Подробнее см.

SAM4S Datasheet

SAM4S Xplained Pro User Guide

Atmel Embedded Debugger User Guide

SAM4S ARM Cortex-M4 Microcontrollers

Плата Oled1

Содержит LCD-дисплей, размером 128х32 пикселя, три кнопки (BUTTON 1 .. BUTTON 3) и три светодиода (LED1 .. LED3). В примерах подключается к разъёму расширения EXT3.

OLED1 Xplained Pro User Guide

Плата IO1

Содержит фотодиод, датчик температуры и кардридер MicroSD.

IO1 Xplained Pro User Guide

Плата PROTO1

Небольшая макетная плата расширения для сборки своего устройства.

Также в комплект входят два USB-кабеля.

2. Организация среды разработки

Много лет я являюсь пользователем ОС Linux, как для профессиональной работы, так и в домашних целях. Поэтому все дальнейшее также проделывалось в Linux (Fedora Core 21).

В качестве среды разработки я использую редактор emacs, для которого существует модуль ada-mode поддерживающий редактирование исходного кода Ada, навигацию по коду, вызов компилятора, переход на ошибки, и др. что обычно требуется разработчику. Поэтому все проекты содержат файлы proj.adp, которые служат в качестве простенького файла проекта для библиотеки ada-mode.

Необходимые пакеты

С сайта компании AdaCore скачиваем бинарную версию компилятора: gnat-gpl-2015-arm-elf-linux-bin

исходные коды GNAT:

gnat-gpl-2015-src

исходные коды компилятора gcc:

gcc-4.9-gpl-2015-src

и исходные файлы для сборки runtime-библиотек (для "голого железа" - Bare Boards - устройств без ОС):

bb-runtimes-gpl-2015-src

Компилятор устанавливаем в каталог /usr/gnat (там же у меня установлен и native-компилятор для x86 - gnat-gpl-2015-x86_64-linux-bin), для этого достаточно запустить в его каталоге скрипт ./doinstall.

Сборка ZFP

Далее собираем runtime-библиотеку для нашей платформы.

Здесь необходимо пояснить, что для GNAT существует понятие "профиля компилятора", которое описывает совокупность доступных средств языка, функциональность и объём runtime-библиотеки.

По степени увеличения функциональности существуют предопределённые профили Zero Footprint Profile (ZFP), Cert Profile, Ravenscar Profiles (два варианта профиля - sfp и full), Full Ada Language Support.

Основной мотивацией существования профилей AdaCore называет лёгкость и снижение цены сертификации приложения на соответствие требованиям надёжности и безопасности при использовании ограниченного профиля. Подробнее здесь.

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

Для процессора sam4s официально поддерживается только один профиль - Zero Footprint Profile (ZFP). Это наиболее ограниченная версия языка, из которой исключено всё, что касается динамической семантики.

В частности исключены все средства поддержки многозадачности, как task и protected objects. Поэтому этот рантайм позволяет разрабатывать только однозадачные приложение. Но, даже в случае однозадачной программы, обмен с устройствами по прерыванием создаёт подобие многозадачной среды.

Кроме, того есть ограничения на обработку исключений (допустимы только локальные обработчики), отсутствуют контролируемые типы, полный список можно узнать заглянув в system.ads.

Подробнее о предопределённых профилях здесь

Приступаем к сборке ZFP.

Распаковываем gnat-gpl-2015-src, bb-runtimes-gpl-2015-src, gcc-4.9-gpl-2015-src в один каталог, допустим он указан у нас в переменной окружения $SOURCES.

bash$ export SOURCES=... # путь к бинарной версии компилятора bash$ export PATH=/usr/gnat/bin:$PATH bash$ export GNAT_SRC_DIR=$SOURCES/gnat-gpl-2015-src/src/ada/ bash$ export GCC_SRC_DIR=$SOURCES/gcc-4.9-gpl-2015-src bash$ cd $SOURCES/bb-runtimes-gpl-2015-src bash$ ./build-all.sh -g -v --no-link --target=sam4s zfp # --no-link - указывает, что все файлы нужно копировать, а не делать ссылки bash$ cp -R install /usr/gnat/arm-eabi/lib/gnat/zfp-sam4s # копирую в традиционное для рантайма место

На этом со сборкой библиотеки рантайма всё.

Отладчик и терминал

Помимо этого, нам понадобится openocd с помощью которого мы будем выполнять загрузку и отладку приложения и терминальная программа minicom, которую мы подключим на стандартный ввод-вывод приложения. И то и другое есть, вероятно, в любом дистрибутиве Linux.

Руководство openocd можно найти на сайте проекта.

Общие модули

Предположим, что все наши проекты будут находиться в каталоге $PROJ.

Условимся складывать вспомогательные файлы для запуска openocd, скрипт с общими функциями GDB, скрипт для запуска консоли и т.п. в $PROJ/utils.

Ещё один каталог $PROJ/xstk-common создадим для хранения общих модулей, пригодных для использования в любом приложении.

В первую очередь туда поместим файл sam4s.ads с описанием аппаратуры процессора. Он позволит для доступа к регистрам различных подсистем MCU пользоваться именами переменных и символическими константами, а не адресами регистров и числовыми значениями.

Этот файл я скопировал из ZFP и дополнил всем, что мне понадобилось. Хотя в реальном приложении его размер должен быть минимально необходимым, для наших экспериментов тем лучше, чем полнее будет описана аппаратура. Это позволит реже перелистывать 1300-страничное руководство по процессору.

В случае языка C такой файл обычно состоит из макросов препроцессора, со всеми вытекающими отсюда возможными неожиданностями при их разворачивании посредством простой текстовой подстановки.

В Ada вместо этого мы определяем полноценные переменные с указанием их размещения в памяти по физическому адресу регистра и добавлением аспектов Volatile, Import.

Откуда следует, что вся работа с регистрами будет выполняться с обычном для языка строгим контролем типов. При этом, типичные для С в подобных случаях приведения типов указателей, не требуются.

Пример:

type PIO_Registers is record PER : Word; PDR : Word; PSR : Word; Pad0 : Word; ... end record; PIOA : PIO_Registers with Volatile, Import, Address => System'To_Address (PIOA_Base);

Одни из самых востребованных операций при работе с MCU - работа с портами ввода-вывода, поэтому следующая полезная вещь - модуль IO_Ports io_ports.ads, io_ports.adb.

И, на базе пакета IO_Ports ещё два тривиальных пакета для работы с кнопками и светодиодами платы процессора и платы расширения Oled1.

Итого в $PROJ/xstk-common у нас:

io_ports.adb io_ports.ads sam4s.ads xstk_board.adb xstk_board.ads xstk_oled1_board.adb xstk_oled1_board.ads