queezythegreat / arduino-cmake

Arduino CMake Build system
648 stars 216 forks source link

Would not work under CLion with Arduino Nano 328 -- workaround found #162

Open mizraith opened 8 years ago

mizraith commented 8 years ago

I'm putting this here to help others that may be struggling with the same issue. I'm working on identifying a fix for arduino-cmake Downloaded CLion and the CLion-Arduino 1.2.1 plugin (which uses arduino-cmake), but wanted to get down my workaround for others to find.
I'll follow up with a possible workaround, but the crux of it is that the arduino-cmake doesn't seem to be able to process the new boards.txt format when there are core variants. I'm on a Mac (10.11) and have several Arduino SDK installs (1.06, 1.56, 1.6x) under /Applications. [ I truly wish the Arduino maintainers would reign in development efforts so that the SDKs don't all behave so differently and have arbitrarily different internal workings! ]

First Lesson -- arduino-cmake looks for /Applications/Arduino.app So rename your preferred SDK as "Arduino.app". Arduino 1.06 and 1.5+ have a different internal structure...but Arduino-Cmake seem stop handle this okay.

Second Lesson -- I tried at least a dozen different settings (CFLAGS, CXXFLAGS, ARDUINO FLAGS, etc etc), but kept getting a warning the the avr-g++ compiler was not getting the "-mmcu" flag. Sure enough, when you look at the cmake log, the line contains "-mmcu= " (nothing afterwards. Again, tried every setting....but was only able to compile under 1.06.
QUESTION: Is there an Arduino-Cmake setting that allows you to pass in a -mmcu flag to the avr-g++ compiler without deleting the other flags already built up?

Third Lesson -- something about the Clion-Arduino or the Arduino-Cmake process retains too much info, even after a quit. When I found a clear workaround, it was not reloading the boards.txt file. I seem to also not see a result from print_board_list() every time either. This inconsistency makes it very hard to debug. Workaround: I ended up going into the CMakeFiles directory and selectively deleting stuff (your mileage will vary).

Workaround steps to compile for nano328 on Arduino 1.5+ I opened the 1.08 boards.txt file and simply copied the nano328 section into the 1.5+ boards.txt file. It looks like this:

``

nano328b.name=Arduino Nano w/ ATmega328

nano328b.upload.protocol=arduino
nano328b.upload.maximum_size=30720
nano328b.upload.speed=57600

nano328b.bootloader.low_fuses=0xFF
nano328b.bootloader.high_fuses=0xDA
nano328b.bootloader.extended_fuses=0x05
nano328b.bootloader.path=atmega
nano328b.bootloader.file=ATmegaBOOT_168_atmega328.hex
nano328b.bootloader.unlock_bits=0x3F
nano328b.bootloader.lock_bits=0x0F

nano328b.build.mcu=atmega328p
nano328b.build.f_cpu=16000000L
nano328b.build.core=arduino
nano328b.build.variant=eightanaloginputs

Again -- if you don't see "nano328" from your print_board_list() call, then you'll need to do some cleaning of CMakeFiles

With the above workaround, I don't need to edit any of the internal arduino-cmake files and my CMakeLists.txt file looks like:

cmake_minimum_required(VERSION 2.8.4)
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/cmake/ArduinoToolchain.cmake)
set(PROJECT_NAME test_clion3)
project(${PROJECT_NAME})

print_board_list()

set(ARDUINO_SKETCH_FOLDER   /Users/mizraith/Documents/ARDUINO_DEVELOPMENT)
link_directories(${ARDUINO_SKETCH_FOLDER}/libraries )

set(ARDUINO_DEFAULT_BAORD nano328)
set(ARDUINO_DEFAULT_PORT /dev/tty.usbmodem1411)

set(${CMAKE_PROJECT_NAME}_SKETCH test_clion3.ino)
generate_arduino_firmware(${CMAKE_PROJECT_NAME}
        BOARD nano328
        PORT /dev/tty.usbmodem1411)

`

mizraith commented 8 years ago

Looking at the Arduino.cmake file, around line 822, inside the function get_arduino_flags, there is the line:

set(COMPILE_FLAGS "-DF_CPU=${${BOARD_ID}${ARDUINO_CPUMENU}.build.f_cpu} -DARDUINO=${ARDUINO_VERSION_DEFINE} -DARDUINO_${${BOARD_ID}.build.board} -DARDUINO_ARCH_AVR -mmcu=${${BOARD_ID}${ARDUINO_CPUMENU}.build.mcu}")

The worked for the old Arduino nano328 definition (see earlier post), as there is a "nano328.build.mcu=atmeta328p" line.

However, the new Arduino 1.6 boards.txt looks like this:

nano.name=Arduino Nano

nano.upload.tool=avrdude
nano.upload.protocol=arduino

nano.bootloader.tool=avrdude
nano.bootloader.unlock_bits=0x3F
nano.bootloader.lock_bits=0x0F

nano.build.f_cpu=16000000L
nano.build.board=AVR_NANO
nano.build.core=arduino
nano.build.variant=eightanaloginputs

## Arduino Nano w/ ATmega328
## -------------------------
nano.menu.cpu.atmega328=ATmega328

nano.menu.cpu.atmega328.upload.maximum_size=30720
nano.menu.cpu.atmega328.upload.maximum_data_size=2048
nano.menu.cpu.atmega328.upload.speed=57600

nano.menu.cpu.atmega328.bootloader.low_fuses=0xFF
nano.menu.cpu.atmega328.bootloader.high_fuses=0xDA
nano.menu.cpu.atmega328.bootloader.extended_fuses=0x05
nano.menu.cpu.atmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex

nano.menu.cpu.atmega328.build.mcu=atmega328p

## Arduino Nano w/ ATmega168
## -------------------------
nano.menu.cpu.atmega168=ATmega168

nano.menu.cpu.atmega168.upload.maximum_size=14336
nano.menu.cpu.atmega168.upload.maximum_data_size=1024
nano.menu.cpu.atmega168.upload.speed=19200

nano.menu.cpu.atmega168.bootloader.low_fuses=0xff
nano.menu.cpu.atmega168.bootloader.high_fuses=0xdd
nano.menu.cpu.atmega168.bootloader.extended_fuses=0x00
nano.menu.cpu.atmega168.bootloader.file=atmega/ATmegaBOOT_168_diecimila.hex

nano.menu.cpu.atmega168.build.mcu=atmega168

But at this point, I lack the CMAKE knowledge to make it handle the .menu cases in the new boards.txt file format.

peterkolski commented 8 years ago

Thank you for sharing your experience! Do you know how I can include the libs of the Arduino SDK. Like eg. 'Servo.h' For now I use the Arduino SDK 1.6.7

In the Arduino IDE the code below compiles fine, while in CLion/CMake there is the following error message:

undefined reference to `Servo::Servo()'

#include

void setup() {
Servo one;
}

void loop() {
}

Thank you very much

mizraith commented 8 years ago

Looking at the example, shouldn't the code read: `

include

`

That said, I tried to use the Servo Sweep example within CLion using CMake, and even though I set the ARDLIBS Servo flag, it still wouldn't compile. I also tried various link_directories options, pointing directly to my Servo.h location. Variations include directory locations and ARDLIBS (Servo, Servo.h, Servo.cpp) options.

link_directories(/Applications/Arduino.app/Contents/Resources/Java/libraries)
set(${CMAKE_PROJECT_NAME}_ARDLIBS Servo)

And I still got the cmake error: undefined reference to `Servo::Servo()'

Anyone else out there that can help?

mizraith commented 8 years ago

Got Servo to Work with the following addition to CMakeLists.txt

link_directories(/Applications/Arduino.app/Contents/Resources/Java/libraries/Servo/src/avr)
set(Servo_RECURSE True)

This also worked:

link_directories(/Applications/Arduino.app/Contents/Resources/Java/libraries)
set(Servo_RECURSE True)

This also worked, without the link directories. set(Servo_RECURSE True)

Milenkij commented 8 years ago

This also work for Stepper library set(Stepper_RECURSE True)

ltearno commented 7 years ago

@mizraith Thanks for your answer it helped me to find another workaround which I will put here just for people if needed.

The workaround ressembles a lot, but instead of changing the platform files, I only change the CMakeList.txt file, by settings the cmake variables.

I add the following in the CMakeList.txt file. This comes from the installed boards.txt file in the arduino cmake tools so you might need to check that yours is the same.

set(nano.upload.maximum_size 30720)
set(nano.upload.maximum_data_size 2048)
set(nano.upload.speed 57600)
set(nano.bootloader.low_fuses 0xFF)
set(nano.bootloader.high_fuses 0xDA)
set(nano.bootloader.extended_fuses 0x05)
set(nano.bootloader.file atmega/ATmegaBOOT_168_atmega328.hex)
set(nano.build.mcu atmega328p)

Then the entire project file looks like this :

cmake_minimum_required(VERSION 2.8.4)
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/cmake/ArduinoToolchain.cmake)
set(PROJECT_NAME Arduino101)
project(${PROJECT_NAME})

print_board_list()

set(${CMAKE_PROJECT_NAME}_BOARD nano)
set(${CMAKE_PROJECT_NAME}_PORT COM4)

set(nano.upload.maximum_size 30720)
set(nano.upload.maximum_data_size 2048)
set(nano.upload.speed 57600)
set(nano.bootloader.low_fuses 0xFF)
set(nano.bootloader.high_fuses 0xDA)
set(nano.bootloader.extended_fuses 0x05)
set(nano.bootloader.file atmega/ATmegaBOOT_168_atmega328.hex)
set(nano.build.mcu atmega328p)

set(${CMAKE_PROJECT_NAME}_SKETCH Arduino101.ino)
generate_arduino_firmware(${CMAKE_PROJECT_NAME})

Again, thanks for your findings !