-
Notifications
You must be signed in to change notification settings - Fork 0
/
README_arduino-cmake
1001 lines (599 loc) · 36.4 KB
/
README_arduino-cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
=============
Arduino CMake
=============
Arduino is a great development platform, which is easy to use. It has everything a beginner should need. The *Arduino IDE* simplifies a lot of things for the standard user, but if you are a professional programmer the IDE can feel simplistic and restrictive.
One major drawback of the *Arduino IDE* is that you cannot do anything without it, which for me is a **complete buzz kill**. Thats why I created an alternative build system for the Arduino using CMake.
CMake is great cross-platform build system that works on practically any operating system. With it you are not constrained to a single build system. CMake lets you generated the build system that fits your needs, using the tools you like. It can generate any type of build system, from simple Makefiles, to complete projects for Eclipse, Visual Studio, XCode, etc.
The **Arduino CMake** build system integrates tightly with the *Arduino SDK*.
*Arduino SDK* version **0.19** or higher is required.
So if you like to do things from the command line (using make), or to build you're firmware where you're in control, or if you would like to use an IDE such as Eclipse, KDevelop, XCode, CodeBlocks or something similar, then **Arduino CMake** is the system for you.
Features
--------
* Integrates with *Arduino SDK*
* Supports all Arduino boards.
* Supports Arduino type libraries
* Automatic detection of Arduino libraries.
* Generates firmware images.
* Generates libraries.
* Sketch support.
* Upload support.
* Programmer support (with bootloader upload).
* Supports multiple build system types (Makefiles, Eclipse, KDevelop, CodeBlocks, XCode, etc).
* Cross-platform: Windows, Linux, Mac
* Extensible build system, thanks to CMake
Feedback
--------
**Arduino CMake** is hosted on GitHUB and is available at:
https://github.com/queezythegreat/arduino-cmake
Did you find a bug or would like a specific feature, please report it at:
https://github.com/queezythegreat/arduino-cmake/issues
If you would like to hack on this project, don't hesitate to fork it on GitHub.
I will be glad to integrate you'r changes if you send me a ``Pull Request``.
Requirements
------------
* Base requirements:
- ``CMake`` - http://www.cmake.org/cmake/resources/software.html
- ``Arduino SDK`` - http://www.arduino.cc/en/Main/Software
* Linux requirements:
- ``gcc-avr`` - AVR GNU GCC compiler
- ``binutils-avr`` - AVR binary tools
- ``avr-libc`` - AVR C library
- ``avrdude`` - Firmware uploader
Contributors
------------
I would like to thank the following people for contributing to **Arduino CMake**:
* Marc Plano-Lesay (`Kernald`_)
* James Goppert (`jgoppert`_)
* Matt Tyler (`matt-tyler`_)
* Andrew Stromme (`astromme`_)
* `johnyb`_
.. _Kernald: https://github.com/Kernald
.. _jgoppert: https://github.com/jgoppert
.. _matt-tyler: https://github.com/matt-tyler
.. _astromme: https://github.com/astromme
.. _johnyb: https://github.com/johnyb
License
-------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this file,
You can obtain one at http://mozilla.org/MPL/2.0/.
TODO
----
* Test more complex configurations and error handling
Contents
--------
1. `Getting Started`_
2. `Using Arduino CMake`_
1. `Creating firmware images`_
2. `Creating libraries`_
3. `Arduino Sketches`_
4. `Arduino Libraries`_
5. `Arduino Library Examples`_
6. `Compiler and Linker Flags`_
7. `Programmers`_
8. `Advanced Options`_
9. `Miscellaneous Functions`_
10. `Bundling Arduino CMake`_
3. `Linux Environment`_
1. `Linux Serial Naming`_
2. `Linux Serial Terminals`_
4. `Mac OS X Environment`_
1. `Mac Serial Naming`_
2. `Mac Serial Terminals`_
5. `Windows Environment`_
1. `CMake Generators`_
2. `Windows Serial Naming`_
3. `Windows Serial Terminals`_
6. `Eclipse Environment`_
7. `Troubleshooting`_
1. `undefined reference to `__cxa_pure_virtual'`_
2. `Arduino Mega 2560 image does not work`_
3. `Library not detected automatically`_
8. `Resources`_
Getting Started
---------------
The following instructions are for **\*nix** type systems, specifically this is a Linux example.
In short you can get up and running using the following commands::
mkdir build
cd build
cmake ..
make
make upload # to upload all firmware images [optional]
make blink-serial # to get a serial terminal to wire_serial [optional]
For a more detailed explanation, please read on...
1. Toolchain file
In order to build firmware for the Arduino you have to specify a toolchain file to enable cross-compilation. There are two ways of specifying the file, either at the command line or from within the *CMakeLists.txt* configuration files. The bundled example uses the second approach like so::
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/cmake/ArduinoToolchain.cmake)
Please note that this must be before the ``project(...)`` command.
If you would like to specify it from the command line, heres how::
cmake -DCMAKE_TOOLCHAIN_FILE=../path/to/toolchain/file.cmake PATH_TO_SOURCE_DIR
2. Creating a build directory
The second order of business is creating a build directory. CMake has a great feature called out-of-source builds, what this means is the building is done in a completely separate directory, than where the sources are. The benefits of this is you don't have any clutter in you source directory and you won't accidentally commit something in, that is auto-generated.
So lets create that build directory::
mkdir build
cd build
3. Creating the build system
Now lets create the build system that will create our firmware::
cmake ..
To specify the build system type, use the ``-G`` option, for example::
cmake -G"Eclipse CDT4 - Unix Makefiles" ..
If you rather use a GUI, use::
cmake-gui ..
4. Building
Next we will build everything::
make
5. Uploading
Once everything built correctly we can upload. Depending on your Arduino you will have to update the serial port used for uploading the firmware. To change the port please edit the following variable in *CMakeLists.txt*::
set(${FIRMWARE_NAME}_PORT /path/to/device)
Ok lets do a upload of all firmware images::
make upload
If you have an upload sync error then try resetting/ power cycling the board before starting the upload process.
6. Serial output
If you have some serial output, you can launch a serial terminal from the build system. The command used for executing the serial terminal is user configurable by the following setting::
set(${FIRMWARE_NAME}_SERIAL serial command goes here)
In order to get access to the serial port use the following in your command::
@INPUT_PORT@
That constant will get replaced with the actual serial port used (see uploading). In the case of our example configuration we can get the serial terminal by executing the following::
make blink-serial
Using Arduino CMake
-------------------
In order to use **Arduino CMake** just include the toolchain file, everything will get set up for building. You can set the toolchain
in `CMakeList.txt` like so::
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/cmake/ArduinoToolchain.cmake)
Please note that this must be before the ``project(...)`` command.
You can also specify it at build configuration time::
cmake -DCMAKE_TOOLCHAIN_FILE=../path/to/toolchain/file.cmake PATH_TO_SOURCE_DIR
Creating firmware images
~~~~~~~~~~~~~~~~~~~~~~~~
Once you have the **Arduino CMake** loaded you can start defining firmware images.
To create Arduino firmware in CMake you use the ``generate_arduino_firmware`` command. The full syntax of the command is::
generate_arduino_firmware(target_name
[BOARD board_id]
[SKETCH sketch_path | SRCS src1 src2 ... srcN]
[HDRS hdr1 hdr2 ... hdrN]
[LIBS lib1 lib2 ... libN]
[PORT port]
[SERIAL serial_cmd]
[PROGRAMMER programmer_id]
[AFLAGS flags]
[NO_AUTOLIBS])
The options are:
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **Name** | **Description** | **Required** |
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **BOARD** | Board ID *(such as uno, mega2560, ...)* | **REQUIRED** |
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **SKETCH** | Sketch path (see `Arduino Sketches`_) | **SKETCH or SRCS are REQUIRED** |
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **SRCS** | Source files | **SKETCH or SRCS are REQUIRED** |
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **HDRS** | Headers files *(for project based build systems)* | |
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **LIBS** | Libraries to link (see `Creating libraries`_) | |
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **PORT** | Serial port, for upload and serial targets (see `Upload Firmware`_) | |
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **SERIAL** | Serial command for serial target (see `Serial Terminal`_) | |
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **PROGRAMMER** | Programmer ID, enables programmer burning (see `Programmers`_). | |
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **AFLAGS** | avrdude flags for target | |
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **NO_AUTOLIBS** | Disable Arduino library detection *(default On)* | |
+--------------------+----------------------------------------------------------------------+------------------------------------+
You can specify the options in two ways, either as the command arguments or as variables. When specifying the options as variables they must be named::
${TARGET_NAME}_${OPTION_NAME}
Where **${TARGET_NAME}** is the name of you target and **${OPTION_NAME}** is the name of the option.
So to create a target (firmware image) called ``blink``, composed of ``blink.h`` and ``blink.cpp`` source files for the *Arduino Uno*, you write the following::
set(blink_SRCS blink.cpp)
set(blink_HDRS blink.h)
set(blink_BOARD uno)
generate_arduino_firmware(blink)
The previous example can be rewritten as::
generate_arduino_firmware(blink
SRCS blink.cpp
HDRS blink.h
BOARD uno)
Upload Firmware
_______________
To enable firmware upload functionality, you need to add the ``PORT`` option::
set(blink_SRCS blink.cpp)
set(blink_HDRS blink.h)
set(blink_PORT /dev/ttyUSB0)
set(blink_BOARD uno)
generate_arduino_firmware(blink)
Or::
generate_arduino_firmware(blink
SRCS blink.cpp
HDRS blink.h
PORT /dev/ttyUSB0
BOARD uno)
Once defined there will be two targets available for uploading, ``${TARGET_NAME}-upload`` and a global ``upload`` target (which will depend on all other upload targets defined in the build):
* ``blink-upload`` - will upload just the ``blink`` firmware
* ``upload`` - upload all firmware images registered for uploading
Serial Terminal
_______________
To enable serial terminal, use the ``SERIAL`` option (``@INPUT_PORT@`` will be replaced with the ``PORT`` option)::
set(blink_SRCS blink.cpp)
set(blink_HDRS blink.h)
set(blink_PORT /dev/ttyUSB0)
set(blink_SERIAL "picocom @INPUT_PORT@ -b 9600 -l")
set(blink_BOARD uno)
generate_arduino_firmware(blink)
Alternatively::
generate_arduino_firmware(blink
SRCS blink.cpp
HDRS blink.h
PORT /dev/ttyUSB0
SERIAL "picocom @INPUT_PORT@ -b 9600 -l"
BOARD uno)
This will create a target named ``${TARGET_NAME}-serial`` (in this example: blink-serial).
Creating libraries
~~~~~~~~~~~~~~~~~~
Creating libraries is very similar to defining a firmware image, except we use the ``generate_arduino_library`` command. This command creates static libraries, and are not to be confused with `Arduino Libraries`_. The full command syntax::
generate_arduino_library(name
[BOARD board_id]
[SRCS src1 src2 ... srcN]
[HDRS hdr1 hdr2 ... hdrN]
[LIBS lib1 lib2 ... libN]
[NO_AUTOLIBS])
The options are:
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **Name** | **Description** | **Required** |
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **BOARD** | Board ID *(such as uno, mega2560, ...)* | **REQUIRED** |
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **SRCS** | Source files | **REQUIRED** |
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **HDRS** | Headers files *(for project based build systems)* | |
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **LIBS** | Libraries to link *(sets up dependency tracking)* | |
+--------------------+----------------------------------------------------------------------+------------------------------------+
| **NO_AUTOLIBS** | Disable Arduino library detection *(default On)* | |
+--------------------+----------------------------------------------------------------------+------------------------------------+
You can specify the options in two ways, either as the command arguments or as variables. When specifying the options as variables they must be named::
${TARGET_NAME}_${OPTION_NAME}
Where **${TARGET_NAME}** is the name of you target and **${OPTION_NAME}** is the name of the option.
Lets define a simple library called ``blink_lib``, with two sources files for the *Arduino Uno*::
set(blink_lib_SRCS blink_lib.cpp)
set(blink_lib_HDRS blink_lib.h)
set(blink_lib_BOARD uno)
generate_arduino_library(blink_lib)
The other way of defining the same thing is::
generate_arduino_library(blink_lib
SRCS blink_lib.cpp
HDRS blink_lib.h
BOARD uno)
Once that library is defined we can use it in our other firmware images... Lets add ``blink_lib`` to the ``blink`` firmware::
set(blink_SRCS blink.cpp)
set(blink_HDRS blink.h)
set(blink_LIBS blink_lib)
set(blink_BOARD uno)
generate_arduino_firmware(blink)
CMake has automatic dependency tracking, so when you build the ``blink`` target, ``blink_lib`` will automatically get built, in the right order.
Arduino Sketches
~~~~~~~~~~~~~~~~
To build a Arduino sketch use the **SKETCH** option (see `Creating firmware images`_). For example::
set(blink_SKETCH ${ARDUINO_SDK_PATH}/examples/1.Basics/Blink) # Path to sketch directory
set(blink_BOARD uno)
generate_arduino_firmware(blink)
This will build the **blink** example from the **Arduino SDK**.
Arduino Libraries
~~~~~~~~~~~~~~~~~
Libraries are one of the more powerful features which the Arduino offers to users. Instead of rewriting code, people bundle their code in libraries and share them with others.
The structure of these libraries is very simple, which makes them easy to create.
An Arduino library is **any directory which contains a header named after the directory**, simple.
Any source files contained within that directory is part of the library. Here is a example of library a called ExampleLib::
ExampleLib/
|-- ExampleLib.h
|-- ExampleLib.cpp
`-- OtherLibSource.cpp
Now because the power of Arduino lies within those user created libraries, support for them is built right into **Arduino CMake**. The **Arduino SDK** comes with a large number of default libraries, adding new libraries is simple.
To incorporate a library into your firmware, you can do one of three things:
1. Place the library next to the default Arduino libraries (located at **${ARDUINO_SDK}/libraries**)
2. Place the library next to the firmware configuration file (same directory as the **CMakeLists.txt**)
3. Place the library in a separate folder and tell **Arduino CMake** the path to that directory.
To tell CMake where to search for libraries use the `link_directories` command. The command has to be used before defining any firmware or libraries requiring those libraries.
For example::
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/libraries)
link_directories(/home/username/arduino_libraries)
If a library contains nested sources, a special option must be defined to enable recursion. For example to enable recursion for the Arduino Wire library use::
set(Wire_RECURSE True)
The option name should be **${LIBRARY_NAME}_RECURSE**, where in this case **LIBRARY_NAME** is equal to *Wire*.
Arduino Libraries are not to be confused with normal static libraries (for exmaple *system libraries* or libraries created using generate_arduino_library). The **LIBS** option only accepts static libraries, so do not list the Arduino Libraries in that option (as you will get an error).
Arduino Library Examples
~~~~~~~~~~~~~~~~~~~~~~~~
Most Arduino libraries have examples bundled with them. If you would like to generate and upload some of those examples you can use the `generate_arduino_example` command. The syntax of the command is::
generate_arduino_example(LIBRARY_NAME EXAMPLE_NAME BOARD_ID [SERIAL_PORT] [SERIAL_COMMAND] [PROGRAMMER_ID])
where **SERIAL_PORT**, **SERIAL_COMMAND** and **PROGRAMMER_ID** are optional.
To generate a target for the **master_writer** example from the **Wire** library for the **Uno**::
generate_arduino_example(Wire master_writer uno /dev/ttyACM0)
The previous example will generate the following two target::
example-Wire-master_writer
example-Wire-master_writer-upload
Compiler and Linker Flags
~~~~~~~~~~~~~~~~~~~~~~~~~
The default compiler and linker flags should be fine for most projects. If you required specific compiler/linker flags, use the following options to change them:
+--------------------------+----------------------+
| **Name** | **Description** |
+--------------------------+----------------------+
| **ARDUINO_C_FLAGS** | C compiler flags |
+--------------------------+----------------------+
| **ARDUINO_CXX_FLAGS** | C++ compiler flags |
+--------------------------+----------------------+
| **ARDUINO_LINKER_FLAGS** | Linker flags |
+--------------------------+----------------------+
Set these option either before the `project()` like so::
set(ARDUINO_C_FLAGS "-ffunction-sections -fdata-sections")
set(ARDUINO_CXX_FLAGS "${ARDUINO_C_FLAGS} -fno-exceptions")
set(ARDUINO_LINKER_FLAGS "-Wl,--gc-sections")
project(ArduinoExample C CXX)
or when configuring the project::
cmake -D"ARDUINO_C_FLAGS=-ffunction-sections -fdata-sections" ../path/to/sources/
Programmers
~~~~~~~~~~~
**Arduino CMake** fully supports programmers, for burning firmware and bootloader images directly onto the Arduino.
If you have a programmer that is supported by the *Arduino SDK*, everything should work out of the box.
As of version 1.0 of the *Arduino SDK*, the following programmers are supported:
+--------------------+---------------------+
| **Programmer ID** | **Description** |
+--------------------+---------------------+
| **avrisp** | AVR ISP |
+--------------------+---------------------+
| **avrispmkii** | AVRISP mkII |
+--------------------+---------------------+
| **usbtinyisp** | USBtinyISP |
+--------------------+---------------------+
| **parallel** | Parallel Programmer |
+--------------------+---------------------+
| **arduinoisp** | Arduino as ISP |
+--------------------+---------------------+
The programmers.txt file located in `${ARDUINO_SDK_PATH}/hardware/arduino/` lists all supported programmers by the *Arduino SDK*.
In order to enable programmer support, you have to use the **PROGRAMMER** option (see `Creating firmware images`_)::
set(${TARGET_NAME}_PROGRAMMER programmer_id)
where `programmer_id` is the name of the programmer supported by the *Arduino SDK*.
Once you have enabled programmer support, two new targets are available in the build system:
* **${TARGET_NAME}-burn** - burns the firmware image via the programmer
* **${TARGET_NAME}-burn-bootloader** - burns the original **Arduino bootloader** image via the programmer
If you need to restore the original **Arduino bootloader** onto your Arduino, so that you can use the traditional way of uploading firmware images via the bootloader, use **${TARGET_NAME}-burn-bootloader** to restore it.
Advanced Options
~~~~~~~~~~~~~~~~
The following options control how **Arduino CMake** is configured:
+---------------------------------+-----------------------------------------------------+
| **Name** | **Description** |
+---------------------------------+-----------------------------------------------------+
| **ARDUINO_SDK_PATH** | Full path to the **Arduino SDK** |
+---------------------------------+-----------------------------------------------------+
| **ARDUINO_AVRDUDE_PROGRAM** | Full path to `avrdude` programmer |
+---------------------------------+-----------------------------------------------------+
| **ARDUINO_AVRDUDE_CONFIG_PATH** | Full path to `avrdude` configuration file |
+---------------------------------+-----------------------------------------------------+
| **ARDUINO_DEFAULT_BOARD** | Default Arduino Board ID, when not specified. |
+---------------------------------+-----------------------------------------------------+
| **ARDUINO_DEFAULT_PORT** | Default Arduino port, when not specified. |
+---------------------------------+-----------------------------------------------------+
| **ARDUINO_DEFAULT_SERIAL** | Default Arduino Serial command, when not specified. |
+---------------------------------+-----------------------------------------------------+
| **ARDUINO_DEFAULT_PROGRAMMER** | Default Arduino Programmer ID, when not specified. |
+---------------------------------+-----------------------------------------------------+
To force a specific version of **Arduino SDK**, configure the project like so::
cmake -DARDUINO_SDK_PATH=/path/to/arduino_sdk ../path/to/sources
Note: You must create a new build system if you change **ARDUINO_SDK_PATH**.
When **Arduino CMake** is configured properly, these options are defined:
* **ARDUINO_FOUND** - Set to True when the **Arduino SDK** is detected and configured.
* **ARDUINO_SDK_VERSION** - Version of the detected **Arduino SDK** (ex: 1.0)
Miscellaneous Functions
~~~~~~~~~~~~~~~~~~~~~~~
This section will outlines some of the additional miscellaneous functions available to the user.
* **print_board_list()**:
Print list of detected Arduino Boards.
* **print_programmer_list()**:
Print list of detected Programmers.
* **print_programmer_settings(PROGRAMMER)**:
*PROGRAMMER* - programmer id
Print the detected Programmer settings.
* **print_board_settings(BOARD_ID)**:
*BOARD_ID* - Board ID
Print the detected Arduino board settings.
Bundling Arduino CMake
~~~~~~~~~~~~~~~~~~~~~~
Using **Arduino CMake** in your own project is simple, you just need a single directory called **cmake**. Just copy that entire directory into you project and you are set.
Copying the **cmake** directory, although simple is not the best solution. If you are using GIT for source code versioning, the best solution is using a submodule. The submodule gives you the power of updating to the latest version of **Arduino CMake** without any effort. To add a submodule do::
git submodule add git://github.com/queezythegreat/arduino-cmake.git arduino-cmake
Then just set the CMAKE_TOOLCHAIN_FILE variable::
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/arduino-cmake/cmake/ArduinoToolchain.cmake)
For more information on GIT submodules please read: `GIT Book - Submodules`_
.. _GIT Book - Submodules: http://book.git-scm.com/5_submodules.html
Linux Environment
-----------------
Running the *Arduino SDK* on Linux is a little bit more involved, because not everything is bundled with the SDK. The AVR GCC toolchain is not distributed alongside the Arduino SDK, so it has to be installed seperately.
To get **Arduino CMake** up and running follow these steps:
1. Install the following packages using your package manager:
* ``gcc-avr`` - AVR GNU GCC compiler
* ``binutils-avr`` - AVR binary tools
* ``avr-libc`` - AVR C library
* ``avrdude`` - Firmware uploader
2. Install the *Arduino SDK*.
Depending on your distribution, the *Arduino SDK* may or may not be available.
If it is available please install it using your packages manager otherwise do:
1. Download the `Arduino SDK`_
2. Extract it into ``/usr/share``
NOTE: Arduino version **0.19** or newer is required!
3. Install CMake:
* Using the package manager or
* Using the `CMake installer`_
NOTE: CMake version 2.8 or newer is required!
Linux Serial Naming
~~~~~~~~~~~~~~~~~~~
On Linux the Arduino serial device is named as follows (where **X** is the device number)::
/dev/ttyUSBX
/dev/ttyACMX
Where ``/dev/ttyACMX`` is for the new **Uno** and **Mega** Arduino's, while ``/dev/ttyUSBX`` is for the old ones.
CMake configuration example::
set(${FIRMWARE_NAME}_PORT /dev/ttyUSB0)
Linux Serial Terminals
~~~~~~~~~~~~~~~~~~~~~~
On Linux a wide range on serial terminal are availabe. Here is a list of a couple:
* ``minicom``
* ``picocom``
* ``gtkterm``
* ``screen``
Mac OS X Environment
--------------------
The *Arduino SDK*, as on Windows, is self contained and has everything needed for building. To get started do the following:
1. Install the *Arduino SDK*
1. Download `Arduino SDK`_
2. Copy ``Arduino`` into ``Applications``
3. Install ``FTDIUSBSerialDrviver*`` (for FTDI USB Serial)
2. Install CMake
1. Download `CMake`_
2. Install ``cmake-*.pkg``
NOTE: Make sure to click on **`Install Command Line Links`**
Mac Serial Naming
~~~~~~~~~~~~~~~~~
When specifying the serial port name on Mac OS X, use the following names (where XXX is a unique ID)::
/dev/tty.usbmodemXXX
/dev/tty.usbserialXXX
Where ``tty.usbmodemXXX`` is for new **Uno** and **Mega** Arduino's, while ``tty.usbserialXXX`` are the older ones.
CMake configuration example::
set(${FIRMWARE_NAME}_PORT /dev/tty.usbmodem1d11)
Mac Serial Terminals
~~~~~~~~~~~~~~~~~~~~
On Mac the easiest way to get a Serial Terminal is to use the ``screen`` terminal emulator. To start a ``screen`` serial session::
screen /dev/tty.usbmodemXXX
Where ``/dev/tty.usbmodemXXX`` is the terminal device. To exit press ``C-a C-\``.
CMake configuration example::
set(${FIRMWARE_NAME}_SERIAL screen @INPUT_PORT@)
Windows Environment
-------------------
On Windows the *Arduino SDK* is self contained and has everything needed for building. To setup the environment do the following:
1. Place the `Arduino SDK`_ either
* into **Program Files**, or
* onto the **System Path**
NOTE: Don't change the default *Arduino SDK* directory name, otherwise auto detection will no work properly!
2. Add to the **System Path**: ``${ARDUINO_SDK_PATH}/hardware/tools/avr/utils/bin``
3. Install `CMake 2.8`_
NOTE: Make sure you check the option to add CMake to the **System Path**.
CMake Generators
~~~~~~~~~~~~~~~~
Once installed, you can start using CMake the usual way, just make sure to chose either a **MSYS Makefiles** or **Unix Makefiles** type generator::
MSYS Makefiles = Generates MSYS makefiles.
Unix Makefiles = Generates standard UNIX makefiles.
CodeBlocks - Unix Makefiles = Generates CodeBlocks project files.
Eclipse CDT4 - Unix Makefiles
= Generates Eclipse CDT 4.0 project files.
If you want to use a **MinGW Makefiles** type generator, you must generate the build system the following way:
1. Remove ``${ARDUINO_SDK_PATH}/hardware/tools/avr/utils/bin`` from the **System Path**
2. Generate the build system using CMake with the following option set (either through the GUI or from the command line)::
CMAKE_MAKE_PROGRAM=${ARDIUNO_SDK_PATH}/hardware/tools/avr/utils/bin/make.exe
3. Then build the normal way
The reason for doing this is the MinGW generator cannot have the ``sh.exe`` binary on the **System Path** during generation, otherwise you get an error.
Windows Serial Naming
~~~~~~~~~~~~~~~~~~~~~
When specifying the serial port name on Windows, use the following names::
com1 com2 ... comN
CMake configuration example::
set(${FIRMWARE_NAME}_PORT com3)
Windows Serial Terminals
~~~~~~~~~~~~~~~~~~~~~~~~
Putty is a great multi-protocol terminal, which supports SSH, Telnet, Serial, and many more... The latest development snapshot supports command line options for launching a serial terminal, for example::
putty -serial COM3 -sercfg 9600,8,n,1,X
CMake configuration example (assuming putty is on the **System Path**)::
set(${FIRMWARE_NAME}_SERIAL putty -serial @INPUT_PORT@)
Putty - http://tartarus.org/~simon/putty-snapshots/x86/putty-installer.exe
Eclipse Environment
-------------------
Eclipse is a great IDE which has a lot of functionality and is much more powerful than the *Arduino IDE*. In order to use Eclipse you will need the following:
1. Eclipse
2. Eclipse CDT extension (for C/C++ development)
On most Linux distribution you can install Eclipse + CDT using your package manager, otherwise you can download the `Eclipse IDE for C/C++ Developers`_ bundle.
Once you have Eclipse, here is how to generate a project using CMake:
1. Create a build directory that is next to your source directory, like this::
build_directory/
source_directory/
2. Run CMake with the `Eclipse CDT4 - Unix Makefiles` generator, inside the build directory::
cd build_directory/
cmake -G"Eclipse CDT4 - Unix Makefiles" ../source_directory
3. Open Eclipse and import the project from the build directory.
1. **File > Import**
2. Select `Existing Project into Workspace`, and click **Next**
3. Select *Browse*, and select the build directoy.
4. Select the project in the **Projects:** list
5. Click **Finish**
.. _Eclipse IDE for C/C++ Developers: http://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/heliossr2
Troubleshooting
---------------
The following section will outline some solutions to common problems that you may encounter.
undefined reference to `__cxa_pure_virtual'
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When linking you'r firmware image you may encounter this error on some systems. An easy fix is to add the following to your firmware source code::
extern "C" void __cxa_pure_virtual(void);
void __cxa_pure_virtual(void) { while(1); }
The contents of the ``__cxa_pure_virtual`` function can be any error handling code; this function will be called whenever a pure virtual function is called.
* `What is the purpose of `cxa_pure_virtual``_
.. _What is the purpose of `cxa_pure_virtual`: http://stackoverflow.com/questions/920500/what-is-the-purpose-of-cxa-pure-virtual
Arduino Mega 2560 image does not work
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you are working on Linux, and have ``avr-gcc`` >= 4.5 you might have a unpatched version gcc which has the C++ constructor bug. This bug affects the **Atmega2560** when using classes which causes the Arduino firmware to crash.
If you encounter this problem either downgrade ``avr-gcc`` to **4.3** or rebuild gcc with the following patch::
--- gcc-4.5.1.orig/gcc/config/avr/libgcc.S 2009-05-23 17:16:07 +1000
+++ gcc-4.5.1/gcc/config/avr/libgcc.S 2010-08-12 09:38:05 +1000
@@ -802,7 +802,9 @@
mov_h r31, r29
mov_l r30, r28
out __RAMPZ__, r20
+ push r20
XCALL __tablejump_elpm__
+ pop r20
.L__do_global_ctors_start:
cpi r28, lo8(__ctors_start)
cpc r29, r17
@@ -843,7 +845,9 @@
mov_h r31, r29
mov_l r30, r28
out __RAMPZ__, r20
+ push r20
XCALL __tablejump_elpm__
+ pop r20
.L__do_global_dtors_start:
cpi r28, lo8(__dtors_end)
cpc r29, r17
* `AVR GCC Bug 45263 Report`_
* `The global constructor bug in avr-gcc`_
.. _AVR GCC Bug 45263 Report: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45263
.. _The global constructor bug in avr-gcc: http://andybrown.me.uk/ws/2010/10/24/the-major-global-constructor-bug-in-avr-gcc/
Library not detected automatically
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When a Arduino library does not get detected automatically, it usually means CMake cannot find it (obvious).
One common reason why the library is not detected, is because the directory name of the library does not match the header.
If I'm including a library header like so::
#include "my_library.h"
Based on this include, **Arduino CMake** is expecting to find a library that has a directory name **my_libray**.
If the directory name does not match the header, it won't be consider a Arduino Library (see `Arduino Libraries`_).
When a library being used is located in a non-standard location (not in the **Arduino SDK** or next to the firmware), then that directory must be registered.
To register a non-standard directory containing Arduino libraries, use the following::
link_directories(path_to_directory_containing_libraries)
Remember to **use this command before defining the firmware**, which requires the library from that directory.
Resources
---------
Here are some resources you might find useful in getting started.
1. CMake:
* `Offical CMake Tutorial`_
* `CMake Tutorial`_
* `CMake Reference`_
.. _Offical CMake Tutorial: http://www.cmake.org/cmake/help/cmake_tutorial.html
.. _CMake Tutorial: http://mathnathan.com/2010/07/11/getting-started-with-cmake/
.. _CMake Reference: http://www.cmake.org/cmake/help/cmake-2-8-docs.html
2. Arduino:
* `Getting Started`_ - Introduction to Arduino
* `Playground`_ - User contributed documentation and help
* `Arduino Forums`_ - Official forums
* `Arduino Reference`_ - Official reference manual
.. _Getting Started: http://www.arduino.cc/en/Guide/HomePage
.. _Playground: http://www.arduino.cc/playground/
.. _Arduino Reference: http://www.arduino.cc/en/Reference/HomePage
.. _Arduino Forums: http://www.arduino.cc/forum/
.. _CMake 2.8: http://www.cmake.org/cmake/resources/software.html
.. _CMake: http://www.cmake.org/cmake/resources/software.html
.. _CMake Installer: http://www.cmake.org/cmake/resources/software.html
.. _Arduino SDK: http://www.arduino.cc/en/Main/Software