15.03.2012

ArduinoIDE в Ubuntu 11.10

К сожалению, дистрибутив ArduinoIDE для Linux не включает в себя сам компилятор gcc (или, если быть более точным, его порт для AVR, avr-gcc). С одной стороны - это хорошо, поскольку дистрибутив становится меньше. С другой стороны - плохо, потому что произвольные сочетания версий компонентов компилятора могут давать существенные "вывихи" и генерить  неверный код.

Например, после апдейта своей Ubuntu до 11.10, я обнаружил у себя такие версии:
  • binutils-avr: 2.20.1
  • gcc-avr: 4.5.3
  • avr-libc: 1.7.1
В то время как в комплекте с ArduinoIDE 1.0 для Windows, который и поныне можно скачать на сайте arduino.cc, версии выглядят более консервативно:
  • binutils-avr: 2.19
  • gcc-avr: 4.3.2
  • avr-libc: 1.6.4
Что с этим делать и как бороться?...


Самый радикальный способ - скомпилировать собственный avr-toolchain. Если вы никогда этого не делали - советую поставить g++ и попробовать ;) Тем более, что ничего сложного нет, все подробно описано туттут и для любителей великого и могучего - здесь.

Горькая правда состоит в том, что даже с учетом прочтения вышеуказанных материалов - дьявол, как всегда, кроется в мелочах. 

Допустим, мы задались задачей получения toolchain-а, аналогичного Windows-версии ArduinoIDE 1.0. Там используется последняя (на момент написания статьи и, похоже, вообще последняя - см. об этом ниже) версия WinAVR с тегом 'WinAVR-20081205'. Соответственно - надо заполучить указанные в файле WinAVR-user-manual.txt версии исходных кодов binutils, gcc-avr и avr-libc, а затем скомпилировать и наслаждаться результатом. 

Это выглядит почти правдой. "Почти" - потому что в итоге мы лишимся поддержки Mega2560, ADK и Leonardo - компилятор не будет ничего знать про ATmega2560 и ATmega32u4. Поэтому, чтобы получить по-настоящему аутентичный toolchain, на исходные тексты потребуется наложить некоторое количество патчей от WinAVR, которые "включат"  поддержку новых устройств и пофиксят некоторое количество ошибок. Если это еще не запугало вас окончательно, то приступим (пошагово).

Переменные окружения

Ставить результат компиляции следует в отдельный каталог - например, создав его в домашнем:

$ cd && mkdir avr432 && cd avr432
$ export PREFIX=/home/user/avr432

По умолчанию, команда make install копирует результат компиляции в корень файловой системы, безжалостно перетирая существующие файлы. Переменная окружения PREFIX служит для того, чтобы изменить этот путь, еще на стадии запуска скрипта configure (см. ниже). 

$ export CXXFLAGS=-w 
$ export LDFLAGS=-w
$ export CFLAGS=-w

Может случиться так, что текущая версия вашего компилятора gcc настолько критично относится к предупреждениям, что трактует даже неиспользованные переменные как ошибки.  Однако в наши планы не входит правка кода, поэтому с помощью опции -w объясняем компилятору, что надо закрыть глаза на все эти "безобразия".

$ export PATH=$PREFIX/bin:$PATH

Модификация PATH нужна для того, чтобы собирать последующие компоненты с помощью собранных на предыдущих шагах. Обратите внимание, что мы добавляем путь слева (в некоторых руководствах он добавлен справа!) - это важно, если у вас уже установлен компилятор avr-gcc и нет планов его удалять из системы. Поскольку поиск исполняемой программы в каталогах PATH происходит слева направо, то, например, в нашем случае  будет найден и запущен именно /home/user/avr432/bin/avr-gcc, а не существующий /usr/bin/avr-gcc

Патчи

Технология применения патча - крайне проста. Для нее нужен исходный файл, файл с описанием изменений (обычно с расширением .patch) и сама утилита patch. В нашем случае каждый патч надо применять так:

$ patch -p0 < patchfile.patch

Но сначала потребуется скачать и распаковать патчи с сайта WinAVR, можно прямо в PREFIX:
$ tar -zxf winavr-2.19.tar.gz
$ tar -xzf winavr-4.3.2.tar.gz  
$ tar -xzf winavr-1.6.4.tar.gz

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

Binutils

Сначала придется собрать binutils - низкоуровневые утилиты для манипуляции объектными файлами: ассемблер (avr-as), линкер (avr-ld), библиотекарь (avr-ar и avr-ranlib). Вместе с ними мы получим утилиту для извлечения данных из объектных файлов (avr-objcopy), дизассемблер (avr-objdump) и стриппер для удаления отладочной информации (avr-strip). Идем сюда - http://sources.redhat.com/binutils/, и качаем файл с соответствующей версией - на момент написания этой статьи ссылка http://ftp.gnu.org/gnu/binutils/binutils-2.19.1.tar.bz2  была рабочей:

$ cd $PREFIX
$ wget -c http://ftp.gnu.org/gnu/binutils/binutils-2.19.1.tar.bz2
$ tar -xjf binutils-2.19.1.tar.bz2
$ cd binutils-2.19.1
$ patch -p0 <../2.19/30-binutils-2.19-avr-size.patch
$ patch -p0 <../2.19/31-binutils-2.19-avr-coff.patch
$ patch -p0 <../2.19/32-binutils-2.19-new-sections.patch
$ patch -p0 <../2.19/33-binutils-2.19-data-origin.patch

Теперь для удобства можно создать отдельный каталог для продуктов компиляции, откуда и запустить скрипт configure, создающий Makefiles для нашей системы:

$ mkdir obj-avr && cd obj-avr
$ ../configure --prefix=$PREFIX --target=avr --disable-nls
$ make
$ make install

Чтобы убедиться, что все идет правильно - проверьте, какая версия ассемблера у вас теперь запускается:

$ avr-as --version
GNU assembler (GNU Binutils) 2.19.1
Copyright 2007 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `avr'.

AVR-GCC

Качаем gcc: http://gcc.gnu.org/, можно целиком - http://ftp.gnu.org/gnu/gcc/gcc-4.3.2/gcc-4.3.2.tar.bz2.  

$ cd $PREFIX
$ wget -c http://ftp.gnu.org/gnu/gcc/gcc-4.3.2/gcc-4.3.2.tar.bz2
$ tar -xjf  gcc-4.3.2.tar.bz2
$ cd gcc-4.3.2

$ patch -p0 <../4.3.2/20-gcc-4.3.2-libiberty-Makefile.in.patch 
$ patch -p0 <../4.3.2/21-gcc-4.3.2-disable-libssp.patch 
$ patch -p0 <../4.3.2/23-gcc-4.3.2-ada-Makefile.patch 
$ patch -p0 <../4.3.2/40-gcc-4.3.2-bug-10768-by-adacore.patch 
$ patch -p0 <../4.3.2/41-gcc-4.3.2-bug-11259_v3.patch 
$ patch -p0 <../4.3.2/42-gcc-4.3.2-bug-spill-v4.patch 
$ patch -p0 <../4.3.2/43-gcc-4.3.2-bug-35013.patch 
$ patch -p0 <../4.3.2/44-gcc-4.3.2-libgcc16.patch 
$ patch -p0 <../4.3.2/45-gcc-4.3.2-bug-33009.patch 
$ patch -p0 <../4.3.2/50-gcc-4.3.2-mega256.patch 
$ patch -p0 <../4.3.2/51-gcc-4.3.2-mega256-additional.patch 
$ patch -p0 <../4.3.2/54-gcc-4.3.2-atmega32m1.patch 
$ patch -p0 <../4.3.2/55-gcc-4.3.2-atmega32c1.patch 
$ patch -p0 <../4.3.2/56-gcc-4.3.2-atmega32u4.patch 
$ patch -p0 <../4.3.2/57-gcc-4.3.2-attiny167.patch 
$ patch -p0 <../4.3.2/58-gcc-4.3.2-remove-atmega32hvb.patch 
$ patch -p0 <../4.3.2/59-gcc-4.3.2-attiny13a.patch 
$ patch -p0 <../4.3.2/60-gcc-4.3.2-atmega32u6.patch 
$ patch -p0 <../4.3.2/61-gcc-4.3.2-osmain.patch 
$ patch -p0 <../4.3.2/70-gcc-4.3.2-ada-mlib.patch 
$ patch -p0 <../4.3.2/71-gcc-4.3.2-ada-freestanding.patch 
$ patch -p0 <../4.3.2/72-gcc-4.3.2-ada-timebase.patch 
$ patch -p0 <../4.3.2/73-gcc-4.3.2-ada-gnat1_print_path.patch 
$ patch -p0 <../4.3.2/74-gcc-4.3.2-ada-optim_static_addr.patch 
$ patch -p0 <../4.3.2/75-gcc-4.3.2-builtins_v6.patch 
$ mkdir obj-avr && cd obj-avr
$ ../configure --prefix=$PREFIX --target=avr --enable-languages=c,c++ --disable-nls --disable-libssp --with-dwarf2
$ make
$ make install

Проверка:


$ avr-gcc --version
avr-gcc (GCC) 4.3.2
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

AVR-LibC


$ cd $PREFIX
$ wget -c http://download.savannah.gnu.org/releases/avr-libc/avr-libc-1.6.4.tar.bz2
$ tar -zjf avr-libc-1.6.4.tar.bz2
$ cd avr-libc-1.6.4
$ patch -p0 <../1.6.4/30-avr-libc-1.6.4-dwarf2.patch
$ patch -p0 <../1.6.4/31-avr-libc-1.6.4-builtins.patch
$ ./configure --prefix=$PREFIX --build=`./config.guess` --host=avr
$ make
$ make install

После копирования замените файл /home/user/avr432/avr/include/avr/eeprom.h на оригинальный, из дистрибутива Arduino 1.0 для Windows.

Наконец-то! Осталось испытать результат - делаем нехитрый скрипт arduino432.sh:

#!/bin/bash
export PATH=/home/user/avr432/bin:$PATH
/full/path/to/arduino

(не забудьте сделать его исполняемым: chmod a+x arduino.sh)

AVR-toolchain by ATMEL

С недавнего времени уже и так давно не обновлявшийся WinAVR был переведен в статус "заморожен", что вызвало определенное смятение в сообществе Arduino, став источником риторических вопросов о том, не пора ли уже проекту поддерживать свой собственный toolchain. Однако, неожиданно вмешался ведущий проекта WinAVR:

WinAVR is not really going away. Yes, Atmel is releasing it's own AVR GCC toolchain... which is really just a continuation and evolution of WinAVR. I have set WinAVR as inactive, because it made no sense to me to be working on two identical projects, one of which would be in my spare time.

И, действительно - ведь теперь соответствующий раздел прямо на сайте ATMEL. Что там нас ждет?
  • binutils-avr: 2.20.1
  • gcc-avr: 4.5.1
  • avr-libc: 1.7.1
  • avr-gdb: 6.7.1
Идеологически, кстати, использование самой свежей binutils очень даже логично. 

После несложной регистрации (придется указать реальный почтовый адрес, через который придет письмо с подтверждающей ссылкой) можно скачать и хидеры, и патчи, и бинарники (ура, не нужно мучиться с компиляцией). Бинарники распаковываются в отдельный каталог и подсовываются в начало $PATH по вышеописанной технологии (см. выше).

Прежде чем начать пробовать этот toolchain с Arduino, найдите файл arduino-1.0/hardware/arduino/cores/arduino/Platform.h и добавьте в самое начало строчку:

#define __DELAY_BACKWARD_COMPATIBLE__   1

Без этой добавки будет использована новая "продвинутая" реализация функции задержки _delay_ms, которую ArduinoIDE явно не переваривает ожидает  ;)

Кстати, если отвлечься от ArduinoIDE: несколько слов по поводу перехода с WinAVR на новый ATMEL-овский toolchain с точки зрения Makefile-ов, можно прочитать здесь

Вместо заключения

Конечно, можно поворчать, что пакет arduino для Ubuntu не содержит зависимостей от номеров версий - ни в текущем, ни в тестируемом дистрибутиве. В сравнении с ним  FreeBSD смотрится более чем выгодно, там зависимости есть: 
  • binutils-avr: 2.20.1
  • gcc-avr: 4.5.1-1
  • avr-libc: 1.8.0.1
Но все равно - отсутствие в комплекте дистрибутива для Linux toolchain-а для ATMEL/AVR - серьезный прокол, в первую очередь именно с точки зрения простоты использования. Чем, собственно, пользователи Linux "хуже" тех, кто сел за Windows или MAC? (вопрос, конечно, риторический). И ответить на него можно цитатой из того самого поста ведущего проекта WinAVR:


Almost all open source projects, including Arduino, are run by volunteers. Even though I may be at Atmel now (and have been there for a few years now), I worked on embedded systems for several years before this, and also worked on the AVR toolchain as a volunteer for quite some time. We always appreciate any sincere help on any aspect of these open source projects, even though some of the skills required may take some time to learn. Help is always welcome.


6 комментариев:

  1. А смысл? Чем не устраивают свежие стабильные пакеты? Вот под Debian пакет arduino-core имеет версию 0018. Ничего хорошего.

    ОтветитьУдалить
    Ответы
    1. Смысл в том, чтобы получить под Ubuntu 11.10 стабильный avr-toolchain для работы ArduinoIDE. Пакеты из официального репо меня не устраивают в первую очередь тем, что генерят неработающий код (см. ссылку в первом абзаце статьи).

      К слову, к arduino-core лично у меня никаких претензий нет: в Linux toolchain туда просто не входит (об этом тоже в первом абзаце написано), и я вообще не понимаю смысл этого пакета, если оно и так работает, будучи скачано с arduino.cc и распаковано в homedir.

      Удалить
    2. Поскольку вы удивляетесь не первый раз, Капитан спешит на помощь. Любой из 10000 пакетов можно где-то найти, скачать, распаковать, пару команд еще, и "и так будет работать". И что, теперь повторять эти нудные действия 10000 раз? Советскому человеку, привыкшему к венде, трудно поверить, что все необходимое действительно входит в систему, не нужно где-то лазить и чего-то выискивать, но это действительно так.

      Удалить
  2. эмм.. странно. всегда думал, что в linux есть совместимость версий снизу-вверх. Вообще, интересная статья, даже несмотря на то, что пользователи linux в большинстве своём матёрые сишники :)

    ОтветитьУдалить
    Ответы
    1. Совместимость "сверху вниз" не есть прерогатива linux, это требование здравого смысла. В этой статье я хотел показать, как компилировать avr toolchain для Artduino, может быть кому-то сэкономит время. Например, предыдущий коммент наглядно демонстрирует, что о наличии проблем подавляющее большинство - не догадывается...

      Удалить
  3. В тему:
    http://www.open-electronics.org/arduino-full-memory-upgrade-to-the-last-atmel-toolchain-version/

    ОтветитьУдалить