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"
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
@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.
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?
Replace bossac from /usr/local/lib/udoo-arduino-cli/hardware/tools to https://github.com/UDOOboard/bossac/tree/master/prebuilt/udoo
Nope. Arduino has now its own command line: https://github.com/arduino/Arduino/blob/master/build/shared/manpage.adoc Edit: See also https://www.udoo.org/forum/threads/upload-to-arduino-101-from-cli.7367/ Arduino CLI command to upload MyProgram.ino to the Udoo X86: Code: arduino --board Intel:arc32:arduino_101 --port /dev/ttyACM0 --upload MyProgram.ino
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
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.
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
Arduino announced a new command line interface (CLI) today, so you can programming the Arduino of a Udoo without starting the IDE https://github.com/arduino/arduino-cli/blob/master/README.md
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.
That is because you are doing this in a putty (headless) way. I think it is only supported in a graphic environment (use VNC instead). It is a known arduino cli issue https://github.com/arduino/Arduino/issues/1981 Perhaps the new arduino-cli can handle it? https://github.com/arduino/arduino-cli/blob/master/README.md
For Neo there is also another method implemented to programm the Neo from another PC: https://www.udoo.org/docs-neo/Arduino_M4_Processor/Programming_Arduino_M4_from_External_PC.html