Pull to refresh
0
Embox
Открытая и свободная ОС для встроенных систем

Существует ли отечественный процессор Мультиклет?

Reading time 8 min
Views 45K
В этом посте я хочу рассказать о наших усилиях по использованию российского процессора с оригинальной архитектурой Мультиклет. Нам интересен перенос нашей ОСРВ Embox на данную платформу, так как это даст возможность использовать довольно большое количество приложений, которые у нас имеются — например, SIP-телефон, о котором мы уже рассказывали.

Речь пойдёт о проблемах, с которыми мы столкнулись в процессе переноса, и о том, как мы эти проблемы устраняли. Возможно, это будет интересно не только тем, кто планирует использовать данный процессор, но и тем, кому по каким-то причинам будет необходимо перейти со стандарта c99 и gcc на стандарт c89 и какой-нибудь несовместимый с gcc компилятор. Также в заключении я позволю себе добавить личные ощущения от взаимодействия с данной платформой.

О российской действительности


Комплект, который мы купили, является топовым, и стоит довольно приличных денег. Конечно, он не такой дорогой, как Эльбрус, но и с той же малиной не сравним. Впрочем, если об этом забыть, то присланный комплект выглядел довольно прилично. Цену, по моему мнению, стоит списать на ограниченность партии, ведь это почти что ручная работа.

Фото модуля


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

Приступаем к портированию


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

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

Не очень обнадёживающая ситуация, но, по крайней мере, компилятор был! Хоть и c89, он компилировал сишный код и предоставленные примеры. Оптимизм внушал ещё и тот факт, что мы уже встречали статью о портировании на данную архитектуру FreeRTOS. Поэтому мы решили двигаться, пока не упрёмся в трудную задачу, которую не сможем обойти с помощью костылей.

Технические подробности компилятора


Компилятор С для Мультклета основан на lcc, который, к сожалению, не совместим с мэйнстримовыми gcc/llvm/icc во всём, в том числе — по интерфейсу командой строки. Первая же попытка скомпилировать хотя бы один файл выявила массу неподдерживаемых флагов. Самым неприятным было отсутствие опции компилятора -include x.h. Эта опция включает файл x.h для препроцессинга, как если бы первой строкой компилируемого файла было #include <x.h>.

В принципе, это не стандартный приём, но таким способом очень удобно передавать, к примеру, сгенерённые конфигурационные файлы (а их у нас много), или, как в нашем случае, параметры компилятора, о которых пойдет речь немного дальше.

Следующим отличием было предоставление компилятора публике. Дело в том, что lcc — это только компилятор, а gcc — это скорее набор утилит для компиляторов (ld, as, cc, ..). Сам же gcc служит своеобразной оберткой для всех этих утилит или проще говоря является драйвером компилятора. То есть правильно вызывать ассемблер или линкер через gcc, который пробросит все параметры соответствующей утилите с правильно установленным окружением. В общем, пришлось вводить отдельные переменные для сборки LD и AS, а утилиту AR брать с хостовой машины. Если раньше к названию кросстула, например mips-elf просто можно было приписать -ld, -as и -ar, а вызывались они вообще через СС c соответствующими флагами, то в данном случае пришлось в явном виде вызывать утилиты.

Линкер, естественно, тоже преподнёс свои сюрпризы.

Первым из них было отсутствие флага -r (--relocatable) для создания промежуточных объектных файлов. Мы используем эти объекты при генерации своей метаинформации — например, подсчитываем контрольные суммы для проверки целостности для каждого модуля системы. Ну и вообще, это довольно полезная штука, если речь заходит об использовании динамических модулей и библиотек.

Дальше — больше. Работа со статическими библиотеками оставляет желать лучшего. Мало того, что библиотеки могут передаваться только с помощью опции -l, так они ещё и не могут содержать полный путь. Из-за этого принципиально не получится линковать разные библиотеки с одинаковыми именами. Кроме того, неприятно отсутствие поддержки --start-group/--end-group.

Могу также добавить довольно интересный и неприятный факт, относящийся уже к компилятору: в нем переопределена опция -l. В lcc это синоним --lccdir.

Подводя промежуточные итоги, сформулирую хотелки к разработчикам компилятора-линкера по флагам
Опция компилятора -include x.h
Опция ликера -r, или --relocatable
Полный путь к библиотекам
Опции --start-group/--end-group
Опцию -l для компилятора зарезервировать под линкер, хотя это и мелочь


Модификация исходников


Теперь перейдем к самим исходникам. Напомню, что они у нас являются c99 или даже gnuc, а компилятор — c89. Понятно, что должны были возникнуть проблемы. Первые проблемы возникли даже не с компилятором, а с препроцессором. В данном компиляторе используется препроцессор mcpp. В общем, сходу выяснилось, что макросы с переменным количеством аргументов в нём обрабатываются иначе, чем в gcc: “хвост” не может быть пустым, т.е. макрос с одним обязательным аргументом нельзя вызывать меньше чем с двумя аргументами. Пришлось менять, например, такой макрос, как assert. Раньше он у нас мог принимать не только выражение для проверки, но и строку сообщения об ошибке, что порой очень удобно. В принципе, это не стандартное поведение макроса, поэтому мы просто сделали еще один макрос assertf() и не компилировали исходники, где он встречался.

Вернёмся к компилятору. Ключевое слово inline появилось в c90, и компилятором мультиклета оно не поддерживается. Мы широко используем static inline функции как замену макросов. Выходом стало введение файла compiler.h, в котором через ifdef’ы определяется отсутствие поддержки inline, и в таком случае inline объявляется пустым макросом (#define inline /* nothing */).

Компилятор не поддерживает назначенный инициализатор (designated Initializers). Эту проблему невозможно решить с помощью препроцессора, а ухудшать исходный код для поддержки старого стандарта нам очень не хотелось. На помощь пришел инструмент c99-to-c89, который на лету превращает c99 код в c89.

Кроме того, компилятор не поддерживает ключевое слово typeof, которое является расширением gnuc. Мы его используем, например, для описания макросов min и max:

/** @return the larger of @a a and @a b */
#define max(a, b) \
    ({                                          \
        typeof(a) __max_a = (a);               \
        typeof(b) __max_b = (b);               \
        __max_a > __max_b ? __max_a : __max_b; \
    })

/** @return the smaller of @a a and @a b */
#define min(a, b) \
    ({                                         \
        typeof(a) __min_a = (a);               \
        typeof(b) __min_b = (b);               \
        __min_a < __min_b ? __min_a : __min_b; \
    })

В общем, для целочисленных переменных можно записать просто:

#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))

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

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

Когда мы приступили к, собственно, поддержке архитектуры мультиклет, у нас сразу же возник ряд вопросов. На этот раз я решил схитрить и связался с сотрудниками мультиклета, которые что-то писали на Хабре. Огромное спасибо krufter. Он действительно быстро отвечал на мои вопросы и, благодаря ему, у нас появился stdarg.h для архитектуры мультиклет. Загрузочный код мы взяли из примеров, которые также были присланы им, но, в принципе, их можно было скачать и с сайта мультиклета. Возникали и некоторые недоразумения, о которых я не хочу распространяться. В итоге решили, что будет лучше, если вопросы будут задаваться на форуме мультиклета.

Заливка образа на плату


После компиляции мы распаковали наш комплект. Как я уже говорил, выглядел он вполне достойно.

Маленькая фотосессия распаковки







Ну и видео первого включения


Но когда мы собрались подключить jtag, выяснилось, что в документации на плату нет информации о том, как это сделать. Там были команды для прошивки, но там не было информации о том, как правильно воткнуть в разъем jtag. При этом, было два разъёма, к которым он прекрасно подходил. Опытным путём мы выяснили, что правильно это делать следующим образом:

Фото разъема


На самом деле, мы задавали вопросы мультиклету, и они, вроде бы, уже обновили руководство, добавив фотографию разъема.

Запуск образа


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

Суть в том, что готовые примеры работали, а образ Embox, по сути дела, с тем же кодом — нет. У меня сразу возникли подозрения о неправильном размещении в памяти объектов программы. Сначала мы грешили на стек, так как у нас образ был существенно жирнее, чем в примерах, и мы думали, что стек, указывающий на конец памяти в 256кБ, мог просто что-то затирать, такие прецеденты были. С помощью readelf выяснилось, что с размерами все в порядке, и мы стали грешить на стартовый адрес. То есть, мы хотели проверить, что программа правильно слинкована. Тут выяснилось, что в комплект разработки не входит дизассемблер. В итоге, после вывода линкером адресов меток предположение подтвердилось. Разница между Embox и примерами заключалась в том, что первым объектным файлов в примерах всегда был crt0.o.

Я попросил добавить поддержку директив .section в ассемблер и соответствующую поддержку в линкере, на что получил ответ на форуме “читайте документацию”. Прочитал, проверил и привел пример исходников, которые показывали, что это не работает. В общем, с помощью всё того же krufter -а проблема решилась.

И я, наконец, увидел долгожданную строчку:



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

Личные ощущения


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

Я не буду останавливаться на аппаратной составляющей, об этом довольно прилично написал barsmonster в своей статье. Я лучше посмотрю на проблему со своей колокольни с точки зрения системного программиста.

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

Все остальные производители тоже понимают, что таблички с производительностью не имеют никакого смысла, если нет возможности разрабатывать приложения и запускать уже написанный софт. На сегодняшний день статьи типа “Как я тестировал IDE компании «Мультиклет»” выглядят странно. То есть реально предполагается писать код на ассемблере? Нет, я, конечно, понимаю, что всё, что нужно современному программисту для встраиваемых систем — это IDE с возможностью залить свою программу прямо на плату. Я даже готов согласиться с выводом из этой статьи:
Таким образом, несмотря на простоту реализации, предлагаемого функционала вполне достаточно для полноценной отладки даже больших и сложных проектов. Обновленный функционал инструментального пакета позволяет значительно увеличить скорость разработки за счет предоставления интуитивно понятного и удобного интерфейса.

Но вот никак не пойму, как мне это поможет хотя бы повторить функционал Arduino, не говоря уже об STM?

Или расчёт на то, что “К Вам на предприятие придут специалисты уже обученные работать на отечественном процессоре”? Вот именно на отечественном! Нет, вы серьезно? Сейчас специалистов учат работать на каком-то конкретном процессоре?

В общем, мои личные впечатления двояки. С одной стороны, радуют люди, которые пытаются делать новое, а с другой — очень уж данный подход сквозит университетщиной. Сделали процессор, отчитались на тестах о проделанной работе, сказали: “Мы самые лучшие, причём всё делаем сами!”, — а продавать? Кому это нужно, кто захочет и сможет использовать этот продукт?

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

P.S. Эмоциональное заключение — это исключительно мои личные ощущения.
P.P.S. Код, описанный в статье, лежит в бранче нашего репозитория. Само собой, он может быть скачан и проверен на аналогичной плате.
Tags:
Hubs:
+72
Comments 95
Comments Comments 95

Articles

Information

Website
emboxing.ru
Registered
Founded
Employees
2–10 employees
Location
Россия