Программирование Arduino из консоли, gentoo-way, ничего лишнего

    Условия задачи с одной стороны сложны, с другой стороны очень просто формулируются. Есть сервер очень-очень далеко, к нему через FTDI конвертер подключена Arduino. Доступ у серверу – SSH. А надо исправлять, компилировать и заливать прошивки в плату. Классический пример — оклейка обоями запертой комнаты через замочную скважину. Очевидно ни о какой Arduino IDE, Eclipse и прочих красивых средах программирования речи быть не может.

    С другой стороны — что нам стоит дом построить, нарисуем, будем жить.

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

    Для справки, целевая система:
    Архитектура x86, ядро 3.7.5-hardened-r1
    Установлены стабильные пакеты последних версий.
    Плата Arduino Pro Mini 328p 16МГц 5V и USB конвертер к ней на чипе FTDI


    Установка в ядро поддержку USB конвертера


    Как добавить поддержку модуля для FTDI конвертера в ядро описано в моей предыдущей статье, за подробностями отсылаю именно к ней, а здесь просто укажу, что нужно добавить в конфиг ядра:

    Device Drivers  --->
        [*] USB support  ---> 
            <M>   USB Serial Converter support  --->
                <M>   USB FTDI Single Port Serial Driver
    


    После подключения конвертера к USB должно появиться следующее устройство:

    # ls -l /dev/ttyUSB0
    crw-rw---- 1 root  uucp, 0 марта  9 13:04 /dev/ttyUSB0
    


    Установка окружения toolchain для компиляции


    В целом все аналогично тому, что я писал ранее, но, как говорится, есть нюанс. Целевая система, использует hardened ядро и соответствующие ключи portage, поэтому простая сборка toolchain потерпит крах с ошибкой:

    configure: error: *** --enable-esp is not supported on this XXXX target.


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

    # USE="nopie nossp -hardened -pic -openmp" crossdev -S -t avr


    Попутное решение проблем с некорректными путями

    Как я уже писал, пути могут быть некорректны, поэтому необходимо создать символические ссылки:

    # find /usr/ -name avr5.x
    /usr/lib64/binutils/avr/2.23.1/ldscripts/avr5.x
    # ln -s /usr/lib64/binutils/avr/2.23.1/ldscripts /usr/avr/lib/ldscripts
    
    # find /usr/ -name crtm328p.o
    /usr/avr/lib/avr5/crtm328p.o
    # ln -s /usr/avr/lib/avr5/crtm328p.o /usr/avr/lib/
    


    Устанавливаем заодно программатор и minicom

    # emerge dev-embedded/avrdude net-dialup/minicom


    Создаем пользователя


    Нам больше нечего делать в root-окружении, поэтому создаем себе простого пользователя, если его до сих пор нет, и продолжаем все остальное в его окружении. Не забудьте добавить вашего пользователя в группу uucp.

    # useradd -G uucp -m -U arduino
    # passwd arduino
    # su arduino
    


    Исходники Arduino, ничего личного лишнего


    Если ставить arduino из portage, то она подтянет за собой кучу пакетов и зависимостей, ту же Java VM, и прочее, и прочее. Не вижу никакого смысла все это устанавливать, особенно если вспомнить, что целевая система серверная, где по определению не должно быть ничего лишнего.

    Итак скачиваем и распаковываем исходники, для этого идем сюда arduino.cc/en/Main/Software и смотрим, что есть свеженькое. На момент написания статьи вышел релиз 1.0.4. В вашем случае версия может быть другая, поэтому, чтобы дальнейшие шаги не зависели то версии, просто переименуем каталог.

    $ wget http://arduino.googlecode.com/files/arduino-1.0.4-linux32.tgz
    $ tar -xzvf arduino-1.0.4-linux32.tgz
    $ mv arduino-1.0.4 arduino
    


    Компиляция статической библиотеки


    Существует три варианта получения статической библиотеки для последующей линковки с будущими проектами.

    • Установить где-нибудь полную Arduino IDE, создать в ней любой скетч, скомпилировать, найти нужный файл и стянуть. Возможно это работает, я не пробовал. Мне представляется, что степень идентичности систем должна быть высока. В общем это не наш путь.
    • Компилировать ее внутри каждого проекта. Тоже сомнительное мероприятие, поскольку, см. след. пункт...
    • Библиотеку можно сделать один раз, а потом линковать ее с каждым новым проектом. Как раз это полностью укладывается в наш gentoo-way.


    Создаем папку для библиотеки и подключаем исходники


    $ cd ~
    $ mkdir ArduinoCore
    $ cd ArduinoCore
    $ mkdir src
    $ ln -s ~/arduino/hardware/arduino/cores/arduino/* src/
    


    Если у вас с этим возникли проблемы, то это папка где находится файл Arduino.h и остальные заголовки и исходники, найти можно командой:

    $ find ~/arduino -name Arduino.h 
    /home/arduino/arduino/hardware/arduino/cores/arduino/Arduino.h 
    


    Кроме того нам понадобится заголовочный файл pins_arduino.h специфичный для вашего варианта платы. В моем случае имеются следующие файлы:

    $ find ~/arduino -name pins_arduino.h 
    /home/arduino/arduino/hardware/arduino/variants/micro/pins_arduino.h 
    /home/arduino/arduino/hardware/arduino/variants/standard/pins_arduino.h 
    /home/arduino/arduino/hardware/arduino/variants/leonardo/pins_arduino.h 
    /home/arduino/arduino/hardware/arduino/variants/mega/pins_arduino.h 
    /home/arduino/arduino/hardware/arduino/variants/eightanaloginputs/pins_arduino.h 
    


    Мне подходит стандартный, а вы выбирайте свой:

    $ ln -s ~/arduino/hardware/arduino/variants/standard/pins_arduino.h src/


    Компилируем библиотеку

    Makefile я честно взял из Eclipse и поправил всего две строки, в которых были абсолютные пути вместо относительных. Фактически вся идеология взята оттуда и реализована в консоли. Берем 328P_16MHz.tgz и распаковываем в папку ~/ArduinoCore, должно получиться следующее:

    $ cd ~/ArduinoCore/
    $ wget https://github.com/madixi/ArduinoCore/blob/master/ArduinoCore/328P_16MHz.tgz?raw=true \
    	-O 328P_16MHz.tgz          
    $ tar -xzvf 328P_16MHz.tgz
    
    $ ls -R ~/ArduinoCore
    /home/arduino/ArduinoCore:
    328P_16MHz  328P_16MHz.tgz  src
    
    /home/arduino/ArduinoCore/328P_16MHz:
    makefile  objects.mk  sources.mk  src
    
    /home/arduino/ArduinoCore/328P_16MHz/src:
    subdir.mk
    
    /home/arduino/ArduinoCore/src:
    Arduino.h           IPAddress.h  Stream.h     WCharacter.h   malloc.c          wiring_private.h
    CDC.cpp             Platform.h   Tone.cpp     WInterrupts.c  new.cpp           wiring_pulse.c
    Client.h            Print.cpp    USBAPI.h     WMath.cpp      new.h             wiring_shift.c
    HID.cpp             Print.h      USBCore.cpp  WString.cpp    pins_arduino.h
    HardwareSerial.cpp  Printable.h  USBCore.h    WString.h      wiring.c
    HardwareSerial.h    Server.h     USBDesc.h    binary.h       wiring_analog.c
    IPAddress.cpp       Stream.cpp   Udp.h        main.cpp       wiring_digital.c
    


    Если у вас другая плата (другой чип) и/или другая частота, то достаточно исправить ключи компилятора в файле:

    ~/ArduinoCore/328P_16MHz/src/subdir.mk
            -mmcu=atmega328p
            -DF_CPU=16000000UL
    


    Последнее что нам осталось сделать, это скомпилировать статическую библиотеку:

    $ cd 328P_16MHz
    $ make
    


    в итоге получится что-то похожее на:

    $ ls -l ~/ArduinoCore/328P_16MHz
    total 592
    -rw-r--r-- 1 arduino arduino 187186 Mar 18 10:18 libArduinoCore.a
    -rw-r--r-- 1 arduino arduino 327022 Mar 18 10:18 libArduinoCore.lss
    -rw-r--r-- 1 arduino arduino   2021 Mar 17 14:46 makefile
    -rw-r--r-- 1 arduino arduino    231 Mar 17 14:46 objects.mk
    -rw-r--r-- 1 arduino arduino    599 Mar 17 14:46 sources.mk
    drwxr-xr-x 2 arduino arduino   4096 Mar 18 10:17 src
    


    Ради чего мы все это делали – это статическая библиотека libArduinoCore.a, которую будем линковать с будущими проектами.

    Первый проект


    В каждом языке программирования есть свой Hello world, в Arduino – это Blink, моргающий светодиодом, который распаян непосредственно на плате и подключен к 13-му выводу чипа. Его веселое помаргивание в итоге расскажет о том, что все получилось.

    $ cd ~
    $ mkdir BlinkA
    $ cd BlinkA
    


    Создаем файл main.cpp
    /*
     * main.cpp
     *
     * Example: Blink 'A'-letter Morse code '.-'
     *
     *  Created on: 15.03.2013
     *      Author: madixi
     */
    
    #include <Arduino.h>
    
    int led = 13;
    
    void setup() {
      pinMode(led, OUTPUT);
      Serial.begin(9600);
      Serial.println("Example: Blink 'A'-letter Morse code '.-'");
    }
    
    void loop() {
      digitalWrite(led, HIGH);
      delay(200);
      digitalWrite(led, LOW);
      delay(200);
    
      digitalWrite(led, HIGH);
      delay(600);
      digitalWrite(led, LOW);
      delay(200);
    
      Serial.println("._");
    }
    
    int main(void) {
      init();
      setup();
    
      for (;;) {
              loop();
      }
    }
    


    Как видите, от скетча он отличается незначительно. В начале добавлено подключение заголовочного файла Arduino.h, а в конце тело функции main. Все это Arduino IDE добавляет незаметно от вас. Не модифицируйте функцию main(), если не знаете точно, зачем вам это нужно.

    Компилируем первый проект

    Как и в предыдущем случае, Makefile взят с Eclipse, и правки коснулись исключительно замены абсолютных путей на относительные. Берем файл ArduinoBuild.tgz и распаковываем в папке с проектом. Должно получиться следующее:

    $ cd ~/BlinkA
    $ wget https://github.com/madixi/BlinkA/blob/master/BlinkA/ArduinoBuild.tgz?raw=true -O ArduinoBuild.tgz          
    $ tar -xzvf ArduinoBuild.tgz
    
    $ ls -lR ~/BlinkA/  
    /home/arduino/BlinkA/:
    total 8
    -rw-r--r-- 1 arduino arduino 1430 Mar 18 10:20 ArduinoBuild.tgz
    drwxr-xr-x 2 arduino arduino   71 Mar 17 21:06 Debug
    -rw-r--r-- 1 arduino arduino  563 Mar 17 19:45 main.cpp
    
    /home/arduino/BlinkA/Debug:
    total 16
    -rw-r--r-- 1 arduino arduino 2314 Mar 17 21:06 makefile
    -rw-r--r-- 1 arduino arduino  249 Mar 17 21:06 objects.mk
    -rw-r--r-- 1 arduino arduino  609 Mar 17 21:06 sources.mk
    -rw-r--r-- 1 arduino arduino  761 Mar 17 21:06 subdir.mk
    


    Далее собираем проект:

    cd ~/BlinkA/Debug
    make
    


    Если все прошло успешно, то у вас должно получиться что-то подобное:

    $ ls -lR ~/BlinkA/
    /home/arduino/BlinkA/:
    total 12
    -rw-r--r-- 1 arduino arduino 1430 Mar 18 10:20 ArduinoBuild.tgz
    drwxr-xr-x 2 arduino arduino 4096 Mar 18 10:23 Debug
    -rw-r--r-- 1 arduino arduino  563 Mar 17 19:45 main.cpp
    
    /home/arduino/BlinkA/Debug:
    total 216
    -rwxr-xr-x 1 arduino arduino 29271 Mar 18 10:23 BlinkA.elf
    -rw-r--r-- 1 arduino arduino  7078 Mar 18 10:23 BlinkA.hex
    -rw-r--r-- 1 arduino arduino 41490 Mar 18 10:23 BlinkA.lss
    -rw-r--r-- 1 arduino arduino 98309 Mar 18 10:23 BlinkA.map
    -rw-r--r-- 1 arduino arduino  2994 Mar 18 10:23 BlinkA.symbol
    -rw-r--r-- 1 arduino arduino   713 Mar 18 10:23 main.d
    -rw-r--r-- 1 arduino arduino  6588 Mar 18 10:23 main.o
    -rw-r--r-- 1 arduino arduino  2314 Mar 17 21:06 makefile
    -rw-r--r-- 1 arduino arduino   249 Mar 17 21:06 objects.mk
    -rw-r--r-- 1 arduino arduino   609 Mar 17 21:06 sources.mk
    -rw-r--r-- 1 arduino arduino   761 Mar 17 21:06 subdir.mk
    


    Собственно файл BlinkA.hex – это готовая прошивка, которую мы и будем заливать в контроллер.

    Прошивка

    Команда прошивки простая:

    /usr/bin/avrdude -pm328p -carduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:BlinkA.hex:a


    В данном случае у вас может отличаться тип контроллера, параметр -p, полный список можно посмотреть в man.

    Можно добавить процесс прошивки в makefile, в этом случае прошивка будет происходить по окончании каждого билда. Для этого вместо файла ArduinoBuild.tgz следует взять ArduinoBuildBuild.tgz.

    Как проверить, что заработало

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

    Чтобы заглянуть в последовательный порт понадобится minicom

    $ minicom -b 9600 -D /dev/ttyUSB0


    Если все работает, то вы увидите «пульс» в виде точка-тире '.–'

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


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

    Содержание


    1. Программирование Arduino из Linux, gentoo-way, быстрый старт
    2. Программирование Arduino из консоли, gentoo-way, ничего лишнего


    Использованные Источники:


    1. playground.arduino.cc/linux/gentoo
    2. playground.arduino.cc/code/eclipse
    3. forums.gentoo.org/viewtopic-p-6971658.html
    • +27
    • 25,3k
    • 7
    Поделиться публикацией

    Комментарии 7

      +2
      Вот это хардкор для чайников. Спасибо будем пробовать.
        –1
        Вот спасибо!
          –2
          Жесть!
            0
            Wiring? Зачем? Только Си! только хардкор!
              0
              Arduino хороша тем, что она у всех одинаковая и что ее не надо настраивать. То есть написал под нее либу — и она у всех работает. А если писал не как попало — еще и на нескольких кристаллах сразу, ибо она еще уровень абстракции над железом. А саму либу хоть на С пиши, хоть на ассемблере — главное потом положить как нужно и желательно в класс С++ обернуть.

              И наоборот — под что угодно можно найти код для ардуины и убедиться, что оно (то, под что код) — работает, не ковыряясь только ради этого в даташите и не гадая — то ли руки кривые, то ли модуль.
              0
              На счёт main():
              Оригинальный выглядит малость посложнее, насколько мне вспоминается — помимо вызова loop() нам есть проверка на наличие данных в UART и соответствующая установка Serial.available(). Неплохо бы его добавить в пример. Для полноты, тсзть ;)

              А вообще — DIHALT прав — только C! Только хардкор! ;) тем более, что предварительные настройки — те же, только makefile разок доделать
                0
                Вообще-то есть готовый мейкфайл для ардуины: ed.am/dev/make/arduino-mk
                Ему надо просто задать путь к директории с ардуиной и сказать, что за плата. Он поддерживает целиком и Wiring, и либы ардуиновские — замечательная штука, я его даже почти не менял.

                А по части удаленной компиляции и отладки — я поступил еще прямолинейнее — приспособил для этого Jenkins и Dropbox. Хотел даже статью написать, но, в принципе, все и так уже изложил в этом комментарии :)

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

                Самое читаемое