here's a script to compile & upload Arduino sketches via CLI

Discussion in 'Arduino IDE' started by fetcher, Sep 6, 2014.

  1. fetcher

    fetcher Member

    Joined:
    Mar 9, 2014
    Messages:
    166
    Likes Received:
    20
    This script will build a .bin image from Arduino sketch files (.ino), and optionally flash it to the SAM3X chip (use -f switch, or set FLASH=true up top) without having to invoke the Arduino IDE GUI. You do need to have the IDE installed, so that its cross-compiler and library code are available.

    After the first run, it will save a compiled copy of standard Arduino libraries (as a .a file in /tmp, by default), and link subsequent sketches to that, instead of building these over and over every time, which is a LOT faster. This can be defeated with the -n switch in case it ever causes trouble.

    So far I've only tested this with very simple sketches-- anything using extra libraries not bundled with the Arduino IDE may require some extra steps.

    For some reason I can't discern, the .bin images compiled by this method end up being a few hundred bytes bigger than those generated by the IDE, even though the exact same compiler and linker are being used. Can anyone tell why?

    Feedback and improvements are welcome!

    Download a copy from here,
    http://vt11.net/due-arduino-build.sh

    Or cut-and-paste the code below, but be careful not to split the very long lines.

    Code:
    #!/bin/bash
    
    # due-arduino-build.sh - Jordan Hazen, jnh at vt11.net (fetcher) 
    # v0.1 - 2014-09-05
    #  Compile and flash Arduino Sketch for Due/Udoo from command-line
    #  released to public domain
    #
    # Derived from Daniel Bovensiepen's Ruby script
    #   ( http://blog.mruby.sh/201303161453.html )
    #
    # Tested only on UDOO board, with Udoo-patched bossac
    # Flash procedure may need adjustment for standalone Arduino Due
    #
    # "undefined reference to `_sbrk'" and similar warnings are normal
    # (these appear on Arduino GUI too)
    
    FLASH=false    # erase & flash SAM3X?
    CPBIN=true     # save final .bin file to project dir?
    RMTMP=false    # remove temporary compile directory?
    NEWAR=false    # rebuild Arduino libs each time?
    
    UART="ttymxc3"
    
    PRELINK=/tmp/Arduino-core.a
    
    BUILD_DIR="/tmp/arduino-build-$$"
    
    # Arduino Application Folder
    ARDUINO_DIR="/opt/arduino-1.5.4"
    
    # Standard Paths for build process
    SAM_DIR="${ARDUINO_DIR}/hardware/arduino/sam"
    BIN_DIR="${ARDUINO_DIR}/hardware/tools/arm-none-eabi/bin"
    TARGET_DIR="${SAM_DIR}/variants/arduino_due_x"
    ARDUINO_SRC="${SAM_DIR}/cores/arduino"
    
    # C Flags
    CFLAGS_1="-c -g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500"
    CFLAGS_2="-fno-rtti -fno-exceptions"   # Used for C++ files only
    CFLAGS_3="-Dprintf=iprintf -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=154 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM -D__SAM3X8E__ -mthumb -DUSB_PID=0x003e -DUSB_VID=0x2341 -DUSBCON -DUSB_MANUFACTURER=\"Unknown\" -DUSB_PRODUCT=\"Udoo-SAM3X\""
    
    INCLUDES="-I${SAM_DIR}/system/libsam -I${SAM_DIR}/system/CMSIS/CMSIS/Include/ -I${SAM_DIR}/system/CMSIS/Device/ATMEL/ -I${SAM_DIR}/cores/arduino -I${TARGET_DIR}"
    
    C_FILES="WInterrupts.c syscalls_sam3.c cortex_handlers.c wiring.c wiring_digital.c itoa.c wiring_shift.c wiring_analog.c hooks.c iar_calls_sam3.c"
    
    CPP_FILES="main.cpp WString.cpp RingBuffer.cpp UARTClass.cpp cxxabi-compat.cpp USARTClass.cpp USB/CDC.cpp USB/HID.cpp USB/USBCore.cpp Reset.cpp Stream.cpp Print.cpp WMath.cpp IPAddress.cpp wiring_pulse.cpp"
    
    function add_to_lib () {
      if ! ${BIN_DIR}/arm-none-eabi-ar rcs ${BUILD_DIR}/core.a ${BUILD_DIR}/$1; then exit 1; fi
    }
    
    function flash () {
      echo "Erasing SAM3X and Uploading $1 ..."
      ${ARDUINO_DIR}/hardware/tools/bossac --port=${UART} -U false -e -w -v -b $1 -R
    }
    
    if [ .$1 = . -o .$1 = .-h ]; then
     echo "usage: `basename $0` [-f] [-s] [-r] [-n] sketch-file.ino"
     echo "        -f = erase and flash SAM3X"
     echo "        -s = save compiled .bin file to project directory"
     echo "        -r = remove temporary build directory after compiling"
     echo "        -n = force recompile of Arduino library files"
     exit 1
    fi
    
    while [ .${1:0:1} = .- ]; do
     if [ .$1 = .-n ]; then NEWAR=true
     elif [ .$1 = .-f ]; then FLASH=true
     elif [ .$1 = .-r ]; then RMTMP=true
     elif [ .$1 = .-s ]; then CPBIN=true
     else
       echo "Unknown option $1"
       exit 1
     fi
      shift
    done
    
    if [ "${1:(-3)}" = "bin" -a $FLASH = true ]; then
      flash $1
      exit 0
    fi
    
    if [ -e ${BUILD_DIR} ]; then
      echo "${BUILD_DIR} already exists -- please remove first."
      exit 1
    fi
    
    mkdir ${BUILD_DIR}
    
    if [ $NEWAR = true -o ! -f $PRELINK ]; then
    
     echo "CC (Arduino library C Files)"
     for src_file in ${C_FILES}; do
       obj_file="${src_file%.*}.o"
       if ! ${BIN_DIR}/arm-none-eabi-gcc ${CFLAGS_1} ${CFLAGS_3} ${INCLUDES} ${ARDUINO_SRC}/${src_file} -o ${BUILD_DIR}/${obj_file}; then exit 1; fi
       add_to_lib $obj_file
     done
     
     echo "CC (Arduino library CPP Files)"
     for src_file in ${CPP_FILES}; do
       obj_file=`echo "${src_file%.*}.o" | sed 's/USB\///'`
       if ! ${BIN_DIR}/arm-none-eabi-g++ ${CFLAGS_1} ${CFLAGS_2} ${CFLAGS_3} ${INCLUDES} ${ARDUINO_SRC}/${src_file} -o ${BUILD_DIR}/${obj_file}; then exit 1; fi
       add_to_lib $obj_file
     done
    
     echo "CC (variant)"
     if ! ${BIN_DIR}/arm-none-eabi-g++ ${CFLAGS_1} ${CFLAGS_2} ${CFLAGS_3} ${INCLUDES} ${TARGET_DIR}/variant.cpp -o ${BUILD_DIR}/variant.cpp.o; then exit 1; fi
     add_to_lib variant.cpp.o
    
     cp ${BUILD_DIR}/core.a $PRELINK
    
    else
    
     cd $BUILD_DIR
     cp $PRELINK core.a
     ar x core.a syscalls_sam3.o
     cd -
    
    fi
    
    echo "CPP/INO (User Files)"
    for src_file in $*; do
      if [ ! -f $src_file ]; then
         echo "Source file $src_file not found!"
         exit 1
      fi
      obj_file="${src_file%.*}.o"
    
      if [ "${src_file:(-3)}" = "ino" ]; then
        TMPF=${BUILD_DIR}/tmp.${src_file}.cpp
        cat <<EOI >$TMPF
    #include "Arduino.h"
    EOI
        cat ${src_file} >>$TMPF
        src_file=$TMPF
      fi
    
      if ! ${BIN_DIR}/arm-none-eabi-g++ ${CFLAGS_1} ${CFLAGS_2} ${CFLAGS_3} ${INCLUDES} ${src_file} -o ${BUILD_DIR}/${obj_file}; then exit 1; fi
      add_to_lib $obj_file
    done
    
    SKETCH=${1%.*}
    
    echo "LD"
    # Link User specific things and Arduino Specific things together
    if ! ${BIN_DIR}/arm-none-eabi-g++ -Os -Wl,--gc-sections -mcpu=cortex-m3 -T${TARGET_DIR}/linker_scripts/gcc/flash.ld -Wl,-Map,${BUILD_DIR}/${SKETCH}.map -o ${BUILD_DIR}/${SKETCH}.elf -L${BUILD_DIR} -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group ${BUILD_DIR}/syscalls_sam3.o ${BUILD_DIR}/${SKETCH}.o ${TARGET_DIR}/libsam_sam3x8e_gcc_rel.a ${BUILD_DIR}/core.a -Wl,--end-group; then exit 1; fi
    
    echo "BIN ${SKETCH}.bin"
    if ! ${BIN_DIR}/arm-none-eabi-objcopy -O binary ${BUILD_DIR}/${SKETCH}.elf ${BUILD_DIR}/${SKETCH}.bin; then exit 1; fi
    
    echo
    echo "Binary file is ready to upload:"
    du -sb ${BUILD_DIR}/${SKETCH}.bin
    
    if [ $CPBIN = true ]; then
      cp ${BUILD_DIR}/${SKETCH}.bin .
    fi
    
    if [ $FLASH = true ]; then
      # Upload to Board
      flash ${BUILD_DIR}/${SKETCH}.bin
    fi
    
    if [ .$RMTMP = .true ]; then
      rm -rf ${BUILD_DIR}
    fi
    
    #-possible extra includes to add after Arduino.h above-
    #include "stdbool.h"
    
     
    Maurice likes this.
  2. matheussouza

    matheussouza New Member

    Joined:
    Nov 8, 2014
    Messages:
    2
    Likes Received:
    0
    THANKS \o/
     
  3. delba

    delba Administrator Staff Member

    Joined:
    May 8, 2013
    Messages:
    1,064
    Likes Received:
    9
    Re: here's a script to compile & upload Arduino sketches via

    Yep, Thanks a lot fetcher ;)
     
  4. TomFreudenberg

    TomFreudenberg Member

    Joined:
    May 12, 2014
    Messages:
    59
    Likes Received:
    2
    Hi @fetcher, hi all

    I was looking for a suitable solution for having a script to compile and flash the Arduino Due directly on my UDOO boards. I liked your idea about the script and made a full debian package environment with Arduino libraries and compiler etc. I did also a number of improvements on script to add INCLUDES and Standard libraries +++

    https://github.com/TomFreudenberg/udoo-arduino-cli

    Cheers,
    Tom
     
    qRayner likes this.
  5. fetcher

    fetcher Member

    Joined:
    Mar 9, 2014
    Messages:
    166
    Likes Received:
    20
    @TomFreudenberg - thanks for extending this. I'd been dealing with includes & libraries in a hackish way (copying them into the build directory and specifying full paths) but your method is a big improvement, especially for more complex projects.
     
  6. Mitchell Spryn

    Mitchell Spryn New Member

    Joined:
    Nov 12, 2015
    Messages:
    5
    Likes Received:
    0
    Bumping this.

    I really want to be able to use this script, but it does not appear to work with the newest version of the kernel. I'm able to compile arduino programs with the script, but I cannot upload. Whenever I attempt to run a command with the --flash-sam, I get the following errors:


    root@udoo:~/test# udoo-arduino-build --flash-sam test.ino
    Building binary file for sketch [test] ...

    CC (Project INO/CPP files)
    CC (Project added Arduino global library CPP files)
    CC (Arduino standard library C files)
    CC (Arduino standard library CPP files)
    CC (Arduino architecture files)
    LD (Link OBJ files)
    BIN (Build binary file for test.bin)

    Binary file is ready ...
    15048 /tmp/udoo-arduino-build-1711/test.bin

    Erasing SAM3X and flashing /tmp/udoo-arduino-build-1711/test.bin ...
    sh: 1: cannot create /sys/class/gpio/gpio117/direction: Directory nonexistent
    sh: 1: cannot create /sys/class/gpio/gpio117/value: Directory nonexistent
    sh: 1: cannot create /sys/class/gpio/gpio117/direction: Directory nonexistent
    sh: 1: cannot create /sys/class/gpio/gpio0/direction: Directory nonexistent
    sh: 1: cannot create /sys/class/gpio/gpio0/value: Directory nonexistent
    sh: 1: cannot create /sys/class/gpio/gpio0/value: Directory nonexistent

    Inner erase and reset routine: failed
    No device found on ttymxc3

    FWIW, I also can't export pins 117 or 0:


    root@udoo:/sys/class/gpio# echo 117 > export
    -bash: echo: write error: Device or resource busy

    This is off of a clean install of the latest kernel. Any ideas?
     
  7. marcinozog

    marcinozog New Member

    Joined:
    Nov 1, 2013
    Messages:
    4
    Likes Received:
    0
  8. soujiro0725

    soujiro0725 New Member

    Joined:
    Aug 10, 2017
    Messages:
    2
    Likes Received:
    0
    The script described above does not work for x86 (hence Arduino 101), does it?
     
  9. waltervl

    waltervl UDOOer

    Joined:
    Dec 12, 2015
    Messages:
    2,314
    Likes Received:
    580
    Last edited: Aug 10, 2017
  10. soujiro0725

    soujiro0725 New Member

    Joined:
    Aug 10, 2017
    Messages:
    2
    Likes Received:
    0
    thanks! it will help.
     
  11. Francis Augusto Medeiros

    Francis Augusto Medeiros New Member

    Joined:
    Sep 10, 2016
    Messages:
    8
    Likes Received:
    0
    I am trying to use udoo-arduino-cli, but am getting this error:

    `error: 'sendSignal' was not declared in this scope`

    (sendSignal() is a function).

    It compiles fine on the IDE on the Udoo side. Am I missing something?

    Best,

    Francis
     
  12. waltervl

    waltervl UDOOer

    Joined:
    Dec 12, 2015
    Messages:
    2,314
    Likes Received:
    580
    You do not need this anymore. Arduino has now its own command line interface. See my message little bit earlier in this thread. Works for all Udoo' s with Arduino IDE installed on the OS side.
     
  13. Francis Augusto Medeiros

    Francis Augusto Medeiros New Member

    Joined:
    Sep 10, 2016
    Messages:
    8
    Likes Received:
    0
    Thanks @waltervl . I saw your post earlier, but I thought you were referring to Intel Udoo's.
    I will give it a try!

    Best,
    Francis
     
  14. waltervl

    waltervl UDOOer

    Joined:
    Dec 12, 2015
    Messages:
    2,314
    Likes Received:
    580
  15. kim19

    kim19 New Member

    Joined:
    Nov 26, 2018
    Messages:
    1
    Likes Received:
    1
    Arduino's CLI is not workig for me. I am getting this error:

    udooer@udooneo:~$ arduino --port /dev/ttyMCC --upload mq135.ino
    Picked up JAVA_TOOL_OPTIONS:
    Exception in thread "main" java.lang.ExceptionInInitializerError
    Caused by: java.awt.HeadlessException:
    No X11 DISPLAY variable was set, but this program performed an operation which requires it.
    at java.awt.SplashScreen.getSplashScreen(SplashScreen.java:117)
    at processing.app.Base.<clinit>(Base.java:94)

    Arduino IDE version is 1.6.5. I don't have CLI option available here, whenever I type arduino command in my putty window it gives this kind of error.
     
    Argha Sen likes this.
  16. waltervl

    waltervl UDOOer

    Joined:
    Dec 12, 2015
    Messages:
    2,314
    Likes Received:
    580
  17. waltervl

    waltervl UDOOer

    Joined:
    Dec 12, 2015
    Messages:
    2,314
    Likes Received:
    580

Share This Page