Arduino programming from the console, gentoo-way, nothing more

    The conditions of the problem are complicated on the one hand, and on the other hand are very easily formulated. There is a server very, very far away, Arduino is connected to it via FTDI converter. Server Access - SSH. And you need to fix, compile and upload firmware to the board. A classic example is wallpapering a locked room through a keyhole. Obviously, there can be no talk of any Arduino IDE, Eclipse, or other beautiful programming environments.

    On the other hand - that we should build a house, draw, we will live.

    So the goal is to create an environment on the remote system sufficient to program the Arduino. Of course, there is no talk of possible serious debugging, and I write and debug the sketches myself on a desktop machine in the Eclipse environment, using all the comfort that gives me a comfortable chair and a large beautiful monitor. Accordingly, one board is mounted on a circuit board for rapid prototyping, and the other on a far away server, production can be said in all its glory.

    For reference, the target system:
    X86 architecture, kernel 3.7.5-hardened-r1
    Installed stable packages of the latest versions.
    Arduino Pro Mini 328p 16MHz 5V board and USB converter to it on FTDI chip

    Installing in the kernel support USB converter

    How to add module support for FTDI converter to the kernel is described in my previous article , I refer to it for details, but here I just indicate what needs to be added to the kernel config:

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

    After connecting the converter to USB, the following device should appear:

    # ls -l / dev / ttyUSB0
    crw-rw ---- 1 root uucp, March 0 9 13:04 AM / dev / ttyUSB0

    Setting the compilation toolchain environment

    In general, everything is similar to what I wrote earlier , but, as they say, there is a nuance. The target system uses the hardened kernel and the corresponding portage keys, so a simple build of the toolchain will fail with an error:

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

    To fix this problem, it is necessary to disable keys that are not relevant for the target assembly; for this, the command changes as follows:

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

    Along the way, solving problems with incorrect paths

    As I already wrote , the paths may be incorrect, so you need to create symbolic links:

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

    We install at the same time the programmer and minicom

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

    Create user

    We have nothing more to do in the root environment, so we create a simple user for ourselves if he is still not there, and continue everything else in his environment. Remember to add your user to the uucp group.

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

    Arduino sources, nothing personal extra

    If you install arduino from portage, then it will pull up a bunch of packages and dependencies, the same Java VM, and so on and so forth. I see no reason to install all this, especially if you remember that the target system is a server system, where by definition there should be nothing superfluous.

    So download and unpack the sources, for this we go here and see what is fresh. At the time of writing, release 1.0.4 was released. In your case, the version may be different, so that the next steps do not depend on the version, just rename the directory.

    $ wget
    $ tar -xzvf arduino-1.0.4-linux32.tgz
    $ mv arduino-1.0.4 arduino

    Compiling a static library

    There are three options for obtaining a static library for later linking with future projects.

    • Install somewhere the full Arduino IDE, create any sketch in it, compile, find the file you need and pull it off. Maybe it works, I have not tried it. It seems to me that the degree of identity of systems should be high. In general, this is not our way.
    • Compile it inside each project. Also a dubious event, because, see next. paragraph...
    • The library can be made once, and then link it with each new project. This is exactly what fits our gentoo-way.

    Create a folder for the library and connect the sources

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

    If you have any problems with this, then this is the folder where the Arduino.h file is located and the other headers and sources, you can find the command:

    $ find ~ / arduino -name Arduino.h 

    In addition, we need the header file pins_arduino.h specific to your version of the board. In my case, the following files are available:

    $ find ~ / arduino -name pins_arduino.h 

    The standard one suits me, and you choose yours:

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

    Compiling the library

    I honestly took the Makefile from Eclipse and corrected only two lines in which there were absolute paths instead of relative ones. In fact, the whole ideology is taken from there and implemented in the console. We take 328P_16MHz.tgz and unpack it into the ~ / ArduinoCore folder, the following should turn out:

    $ cd ~ / ArduinoCore /
    $ wget \
    	-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 src
    / home / arduino / ArduinoCore / 328P_16MHz / src:
    / 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

    If you have a different board (another chip) and / or a different frequency, then just fix the compiler keys in the file:

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

    The last thing we need to do is compile the static library:

    $ cd 328P_16MHz
    $ make

    you end up with something similar to:

    $ 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
    -rw-r - r-- 1 arduino arduino 599 Mar 17 14:46
    drwxr-xr-x 2 arduino arduino 4096 Mar 18 10:17 src

    For the sake of what we did all this - this is the static library libArduinoCore.a , which we will link with future projects.

    First project

    Each programming language has its own Hello world, in Arduino it is Blink, a blinking LED that is soldered directly to the board and connected to the 13th pin of the chip. His cheerful blinking in the end will tell that everything worked out.

    $ cd ~
    $ mkdir BlinkA
    $ cd BlinkA

    Create the main.cpp file
     * main.cpp
     * Example: Blink 'A'-letter Morse code '.-'
     *  Created on: 15.03.2013
     *      Author: madixi
    int led = 13;
    void setup() {
      pinMode(led, OUTPUT);
      Serial.println("Example: Blink 'A'-letter Morse code '.-'");
    void loop() {
      digitalWrite(led, HIGH);
      digitalWrite(led, LOW);
      digitalWrite(led, HIGH);
      digitalWrite(led, LOW);
    int main(void) {
      for (;;) {

    As you can see, it differs slightly from a sketch. At the beginning, the connection of the Arduino.h header file is added, and at the end the main function body is added. Arduino IDE adds all this imperceptibly from you. Do not modify the main () function unless you know exactly why you need it.

    Compiling the first project

    As in the previous case, the Makefile was taken from Eclipse, and the edits concerned exclusively the replacement of absolute paths with relative ones. We take the file ArduinoBuild.tgz and unpack it in the folder with the project. You should get the following:

    $ cd ~ / BlinkA
    $ wget -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
    -rw-r - r-- 1 arduino arduino 609 Mar 17 21:06
    -rw-r - r-- 1 arduino arduino 761 Mar 17 21:06

    Next, we assemble the project:

    cd ~ / BlinkA / Debug

    If everything went well, then you should get something like this:

    $ 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
    -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
    -rw-r - r-- 1 arduino arduino 609 Mar 17 21:06
    -rw-r - r-- 1 arduino arduino 761 Mar 17 21:06

    Actually, the BlinkA.hex file is a ready-made firmware, which we will upload to the controller.


    The firmware command is simple:

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

    In this case, your controller type may differ, the -p parameter, the full list can be found in man.

    You can add the firmware process to the makefile, in which case the firmware will occur at the end of each build. To do this, instead of the ArduinoBuild.tgz file, you should take ArduinoBuildBuild.tgz .

    How to check what worked

    In the sketch above, there is not only a funny blinking LED, but also the output of messages to the serial port. In this case, using the output as a means of control is quite convenient, you can even fasten the daemon, which will land all the board messages in syslog, but now I will not stop there.

    To look into the serial port you will need minicom

    $ minicom -b 9600 -D / dev / ttyUSB0

    If everything works, then you will see a "pulse" in the form of a dot-dash '.–'

    Instead of a conclusion

    In the next article, I plan to uncover the issue of using external libraries, of which there are very many at the moment.


    1. Arduino programming from Linux, gentoo-way, quick start
    2. Arduino programming from the console, gentoo-way, nothing more

    Used sources:


    Also popular now: