"Low Level"-Programmierung des Arduino DUE SAM3 Controllers mit eigener Entwicklungsumgebung
"Low level" programming of the Arduino DUE SAM3 controller with a custom IDE
The Arduino DUE is known as an elegant and easy-to-use micro controller platform, encompassing electronics, controller libraries and a lightweight (Java based) IDE. The main controller used is the ARM architecture based Atmel chip SAM3X8E. The PCB additionally contains two micro USB ports, circuit parts for power management, and a second Atmel controller for programming purposes. Normally the DUE is programed in C++ using the Arduino IDE, which uses a common wrapper library for synergy with other Arduino types, and which makes it really easy and transparent to implement a program ("sketch").
However, if you are interested in going more into the matter of the SAM3 controller (without using the Arduino C++ "wrapper library"), or if you like to work with an IDE of your choice, then you can still use the DUE electronics - as well without JTAG. The following descriptions show how you can accomplish this.
Der Arduino DUE ist bekannt als eine sehr elegante und leicht zu bedienende Mikrocontroller-Plattform, bestehend aus Elektronik, Controller-Bibliotheken, und einer kleinen Entwicklungsumgebung. Als Haupt-Controller wird ein ARM-basierter Atmel-Chip SAM3X8E verwendet. Desweiteren enthält die Platine zwei Mikro-USB-Ports, die Anschlüsse für externe elektrische Schaltungen, Elektronik zur Spannungsversorgung, sowie einen weiteren Atmel-Chip (mit fester Firmware), der nur der Programmierung dient. Der Controller wird normalerweise in C++ mit der Arduino-IDE (Java) programmiert. Letztere bindet automatisch eine vereinheitlichte Arduino-Bibliothek ein und vereinfacht Handhabung damit sehr.
Wer Interesse daran hat, einen SAM3-Controller ohne diese vereinheitlichte Abstaktionsebene in einer selbstgewählten Entwicklungsumgebung zu programmieren, der kann das DUE-Board ebenfalls dafür verwenden - auch ohne JTAG und Co. Im Weiteren wird beschrieben wie's geht.
The very quick way ...
If you don't have much time now to read the details below, simply try this:
(This works on Linux and MacOSX, for Windows you need to make it manually, sorry)
You need PHP (I had some trouble with Linux-MacOS incompatabilities of some shell programs, so this is now a PHP CLI script - not ideal but works fine).
Download and extract/install the official Arduino IDE application (Linux:
tar -xvzf arduino-xxx.tgz
, MacOS:Arduino.app --> /Applications/
).Download this
fiddling script
and extract it somewhere into your home folder. You get a directory calledinstall
.Switch into this
install
directory and execute the setup script, where you specify the resource path of the Adruino application as command line argument (I mean the directiry in the Arduino app that contains the folderstools
andhardware
). Example for MacOS:./setup-from-arduino-app.php /Applications/Arduino.app/Contents/Resources/Java/
The script will "fiddle", compile the
libsam
(the basic controller library) and puts all this together with some additional files that are in theresources
directory in the output folder calleddue
. Note: You will get a lot of warnings during the compilation because the verbosity is quite high. That is ok as long as there is no error.Now you have all you need, including an example controller program in the folder
due
. Copy it wherever you like.For checking, connect the Arduino board with the programming port to your device, switch to the
example
folder, edit the port in theMakefile
to your port (/dev/cu.usbmodemfa141
in my case) and saymake install
. After quickly compiling/linking, resetting the controller and flashing, the amber LED should blink with 2Hz.Inspect the
due
folder, setup your project and start working :-)
In aller Kürze ...
Wenn gerade die Zeit für die untenstehenden Details fehlt, hier die Kurzanweisung:
(Das ganze funktioniert leider nur unter *nix, also Linux und MacOSX, bei Windows muss das leider manuell gemacht werden - siehe weiter unten :)
PHP wird benötigt (Ich hatte ein paar Komparibilitätsprobleme mit Shellprogrammen unter Linux vs. MacOS, daher ist es jetzt ein PHP-Script - "nicht ideal, aber geht").
Lade die offizielle Arduino IDE herunter und installiere/extrahiere sie (Linux:
tar -xvzf arduino-xxx.tgz
, MacOS:Arduino.app --> /Applications/
).Lade dieses Installationsskript herunter und entpacke es irgendwo im Homeordner. Es enthält einen Ordner namens
install
.Wechsle in dieses
install
-Verzeichnis und führe das Installationsscript aus, wobei als Kommandozeilenparameter der Pfad zum "Resourcenordner" in der Arduino-IDE angegeben wird (Damit meine ich den Ordner, der die Verzeichnissetools
undhardware
enthält). Beispiel für MacOSX:./setup-from-arduino-app.php /Applications/Arduino.app/Contents/Resources/Java/
Jetzt sucht das Script die benötigten Dateien/Verzeichnisse heraus und kopiert sie in den Ergebnisordner
due
, der im selben Verzeichnis angelegt wird wo auch das Installationsscript ist. Weiterhin werden ein paar Header- und Makefiles von mir mit hineinkopiert. Dann wird dielibsam
mit der Toolchain erstellt. Dabei entstehen viele Warnungen, das ist normal.Jetzt ist in
due
alles da, was gebraucht wird. Er kann an eine beliebige Stelle kopiert werden.Zum Prüfen, schieße das Arduino DUE Board an den Programmierport an und wechsle in Verzeichnis
due/example/
. Nun muss noch eine kleine Anpassung imMakefile
gemacht werden - die Portbeschreibung. Bei mir ist das/dev/cu.usbmodemfa141
- besser nochmals nachschauen. Dann einfachmake install
sagen, und nach Kompilieren, Achivieren, Linken, Flashen und Resetten sollte jetzt die gelbe bzw. "bernstein" LED mit 2Hz blinken.
More details ...
Let's take a look what we need to build the controller program, how to get it on the board and what to take into account:
We need a building toolchain. For Linux/MacOS the GCC for ARM (more precisely gcc/g++-arm-none-eabi, maintained by CodeSourcery) covers this. It is also used in the Arduino IDE.
We need a flashing tool. A solution for this is BOSSA ("Basic Open Source SAM-BA Application"), which is as well included in the Arduino IDE.
We need the manufacturer libraries, which cover the basic definitions and functions for the controller and its peripherals. That is the
CMSIS
"Cortex Microcontroller Software Interface Standard" (defined by ARM and adapted by Atmel), an extended Atmel/SAM peripheral library, as well a linker command file.We need to implement our initialization and interrupt routines ("handlers") outself. (an example is shown below).
We need the controller documentation, which is here.
We need to know which board pins are connected to which controller pins, that is written down here, and the schematic here is quite helpful as well.
We need a boot mechanism - fortunately that is all done and we don't need to care about it. Arduino uses the default Atmel loader, which allows in-circuit- programming via USB using the SAM-BA protocol Atmel SAM-BA In-system Programmer, which is implemented in the already mentioned open source tool
BOSSA
. Context: The controller always starts from ROM, where the boot loader lives (except maybe with JTAG), makes some very basic initialisations and then jumps to a defined address in the flash, where our software starts.We need to take some little Arduino specific stuff into account, especially when it comes to transfering (flashing) the program: There is a second AVR IC on the DUE board, which is connected to the programming USB port. It is able to send a hardware (I/O) signal to reset and erase the flash program of the SAM3 (or set a "don't boot from flash flag"). Hence, it has the same effect as if you would push the
ERASE
button on the board. Slangy speaking, the SAM bootloader then recognises that no flash program is present and switches to the "flash-me-mode". A second function of that AVR is that it is a serial to USB converter (connected to the UART RX/TX of the SAM3), so it flashes the main controller via serial. The Schematic shows (much better than a few words) how this is wired. From the practical point of view: All we need to do for flashing is to connect to the programming port with 1200bps, then the AVR will initiate theERASE
and the program can be transferred. I implemented aMakefile
(shown below) to meet the requirements for this feature. Take a look at themake install
rule.
Well, all we need to do is to extract the tools and library (and linker) files from the great tool that the Arduino guys provide.
On Linux the main directory I am talking about is the root of the extracted Arduino IDE
tar.gz
. It contains the executablearduino
.On MacOSX, the directory is burried in the abyss of Arduino.app:
/Applications/Arduino.app/Contents/Resources/Java
. Note that "Apps" are directories with the extension.app
.
There we find the interesting directories ...
hardware/tools/g++_arm_none_eabi/
: GCChardware/tools/bossac
: BOSSAhardware/arduino/sam/variants/arduino_due_x/linker_scripts/
: Linker command fileshardware/arduino/sam/system/
Herstellerbibliotheken
These files and directories are fiddled out of the IDE with the fillowing setup
script. After running you have a directory due
in the parent folder of the
script.
And that's pretty much all to say about this. You can use Eclipse or Netbeans as IDE (an example for Netbeans on the bottom of this page) - and code.
Ein paar Details ...
Schauen wir uns zuerst an, welche Komponenten bzw. Aspekte wir berücksichtigen müssen um ein Programm für den SAM3 zu erstellen und es dann auf das Board zu transferieren:
Wir benötigen eine Toolchain zum erstellen unserer Controller-Software. Hier gibt es für Linux/MacOS den GCC für ARM (gcc/g++-arm-none-eabi), der von CodeSourcery kommt. Er wird auch in der Arduino-Software verwendet.
Wir benötigen ein Tool, mit dem das Programm auf den Controller geladen werden kann. Auch hier gibt es eine Lösung namens BOSSA ("Basic Open Source SAM-BA Application"), welches für den Arduino nochmals angepasst wurde. Es ist ebenfalls in der Arduinosoftware enhalten.
Wir benötigen herstellerspezifische Bibliotheken, in denen die Basics für den Controller definiert sind. Dazu gehören nicht nur Definitions-Headers und generische Funktionen, sondern auch Anweisungen, wie der Linker das Speicherabbild zusammenschrauben soll (Linker command file). All dies ist natürlich ebenfalls in der Arduino-IDE mit enthalten, denn die Arduino-Bibliothek und die Binärdatei des Programms müssen dort ebenfalls irgendwie erstellt werden. Zu nennen ist hier noch die Bedeutung der
CMSIS
"Cortex Microcontroller Software Interface Standard", eine Bibliothek, die für Cortex-Rechner eine einheitliche Schnittstelle bietet und von ARM definiert ist.libsam
stellt implementiert die erweiterte Peripherie- Funktionalität für den SAM. Das alles ist hier natürlich für die Atmel-Peripherievariante zugeschnitten.Wir müssen die (Teil-)Initialisierung unseres Programms selbst machen. Dazu habe ich unten ein Beiepiel angegeben. Das macht normalerweise die Arduino-Bibliothek.
Wir brauchen die Dokumentation für den Controller. Die findet man hier.
Wir müssen wissen welche Pins am DUE Board an welchen Controller-Pins angeschlossen sind. Diese Info gibt es hier, den Schaltplan hier.
Wir benötigen einen Boot-Mechanismus für den Controller - darum brauchen wir uns allerdings hier nicht zu kümmern. Kontext: Der Controller started immer erstmal an einer definierten Addresse im ROM (nicht Flash-ROM), und da ist der Boot loader fest eingebrannt. Mit ihm werden dann die ersten Initialisierungen durchgeführt, bevor er dann normalerweise an eine Stelle im Flash springt, wo unser Program sitzt. Der Bootloader kann aber auch verwendet werden, um den Flash-Speicher zu verändern (der Controller flasht sich eigentlich selbst wenn wir ihn programmieren, und wir können den Flash mit unserem Programm ebenfalls verändern). Für den Arduino ist dieser Bootloader der Standard-Bootloader von Atmel, welcher es erlaubt mit dem Atmel SAM-BA In-system Programmer geflasht zu werden. Die Open Source-Variante des PC-seitigen Flashprogramms ist das oben genante BOSSA.
Wir müssen die Besonderheiten des DUEs beim Erstellen und beim Flashen beachten. Dafür habe ich unten ein
Makefile
angegeben. Bei der Elektronik gibt es auch noch etwas: Es sind eigentlich zwei Controller auf dem Board. Ein kleiner AVR hängt am Programmierport und kann das Controllerprogramm "löschen" (bzw. wird ein Flag verändet, dass den normalen Start im Flash verhindert), und den Controller "resetten". Salop gesagt: Damit kapiert der Bootloader, dass kein Programm auf dem SAM ist und geht implizit in den "Flash-mich-Modus". Das selbe passiert wenn dieERASE
-Taste auf dem Board gedrückt wird. Gleichzeitig dient der kleine AVR IC als USB-RS232 (besser gesagt URAT) -Umsetzer, d.h. bei Verwendung des Programmierports lauscht auf Seiten des SAM3 die UART Schnittstelle zum Flashen (aber auch als normale Serielle Schnittstelle, die z.B. fürs Debugging gut ist). Ein Blick in den Schaltplan zeigt diese Verdrahtung. Praktisch gesehen brauchen wir nichts zu tun als kurz eine Verbindung mit 1200bps am Programmierport aufzubauen, damit wird ERASE getriggert. Das passiert im unten angegebenenMakefile
beimake install
.
Was wir also tun müssen ist die Arduino-Sofware herunterladen und die benötigten Teile extrahieren.
Bei Linux ist das Hauptverzeichnis bereits das extrahierte
tgz
. Es enthält die ausführbare Dateiarduino
.Beim Mac ist es in den Untiefen der App versteckt (die ja ein Ordner mit der Endung
.app
ist:/Applications/Arduino.app/Contents/Resources/Java
.
Darin sind folgende Unterverzeichnisse und Dateien interessant:
hardware/tools/g++_arm_none_eabi/
: GCChardware/tools/bossac
: BOSSAhardware/arduino/sam/variants/arduino_due_x/linker_scripts/
: Linker command fileshardware/arduino/sam/system/
Herstellerbibliotheken
Die jeweiligen Dateien werden mit dem nachfolgenden Setup-Skript extrahiert.
Nach Ausführung gibt es ein Verzeichnis due
im Ordner, in dem auch das
Skript selbst liegt.
"Sonst war's das eigehtlich schon". Als IDE verwende ich Netbeans oder Eclipse, diese erlauben eine gute Auto-Vervollständigung, direkte Code-Prüfung, und mit einem Klick in den Tiefen der Definitions-Headers zu verschwinden :). Ein Beispiel für ein Netbeans-Projekt ganz steht ganz unten.
Setup
The setup script shown below simply fiddles required tools and files out
of the normal Arduino application that you download. Interesting for us
are are the ARM GCC toolchain (more precisely gcc/g++ arm-none-eabi), the
upload tool (bossac) and the basic libraries for the controller (CMSIS and
Atmel specific sam). Latter is directly compiled and archived to libsam-<...>.a
that we add to the linking process when we build our controller programs.
Additionally I added some resources that I use: a build Makefile
that is
includable in the project Makefiles, a header that includes all required
library headers, and a piece of initialisation code that is included only in
the main file.
The installation process looked on my (Linux/Mac) machines as follows:
Installation
Das weiter unten angegebene Setup-Skript extrahiert benötigte Tools und
Dateien aus der "normalen" Arduino-Applikation, welche bei Auduino.cc heruntergeladen
wird. Für mich interessant sind dabei die ARM GCC toolchain, das Upload-Tool
(bossac) und die Kernbibliotheken für den Controller (CMSIS und die Atmel-spezifische
SAM-Bibliothek). Letztere wird bei der Installation direkt zu einem Archiv
libsam<...>.a
kompiliert/gebunden, die wir dann beim Erstellen unserer Programme
mit in die Ausgabe-Binärdatei linken.
Zusätzlich habe ich ein paar Resourcen, die ich verwende, hinzugefügt: Ein
Build-Makefile
, welches in das Projekt-Makefile eingebunden werden kann, ein
"Verteiler-Header", der die bentigten Controller-Bibliotheken einbindet, sowie
ein Stück Initialisierungs-Code, welches ich in der main
-Datei einmal einbinde.
Der Installationsablauf sieht bei mit (auf Linux und MacOX) so aus:
Setup process
You can download the "fiddling script" here. You get a directory
called install
:
Installationsablauf
Das Installationsskript kann hier heruntergeladen werden. Im
Archiv ist ein Ordner install
:
--------------------------------------------------------------------------------
-- The decompressed install directory before running the setup:
--------------------------------------------------------------------------------
$ tree -C install
.
├── resources
│ ├── example
│ │ ├── Makefile
│ │ └── main.c
│ ├── include
│ │ ├── due_sam3x.h
│ │ └── due_sam3x.init.h
│ └── make
│ └── make_due_firmware.mk
└── setup-from-arduino-app.php
--------------------------------------------------------------------------------
-- Start the setup script, specifying the resource directory (works for both
-- Linux and MacOS/BSD. Example here is Arduino.app under MacOS.
--------------------------------------------------------------------------------
$ ./setup-from-arduino-app.php /Applications/Arduino.app/Contents/Resources/Java/
GCC ARM EABI toolchain ...
BOSSA uploader/downloader ...
Arduino & Atmel libraries (SAM, CMSIS) ...
Copying existing libraries ...
Copying 'patch' resources
Creating libsam ...
In file included from ../source/../chip.h:71,
from ../source/adc.c:30:
[ ... YOU WILL GET A LOT OF WARNINGS HERE BECAUSE THE VERBOSITY DURING THIS
BUILD IS VERY HIGH. IT'S FINE ... ]
../../../tools/g++_arm_none_eabi/bin/arm-none-eabi-ar: creating ../../../lib/libsam_sam3x8e_gcc_rel.a
--------------------------------------------------------------------------------
-- After the setup fiddled the required tools and built the SAM library with CSMIS
-- There is now a directory called "due". This is where the results are stored.
--------------------------------------------------------------------------------
$ tree -C -L 3 due
due
├── example <<< EXAMPLE PROGRAM
│ ├── Makefile
│ └── main.c
│
├── include <<< INCLUDE DIRECTORY FOR YOUR PROJECT
│ ├── due_sam3x.h <<< WRAPPER TO INCLUDE ALL SAM/CSMIS
│ └── due_sam3x.init.h <<< INCLUDE IN YOUR MAIN FOR INIT
│
├── lib
│ ├── libarm_cortexM3l_math.a <<< ARM MATH LIB
│ ├── libsam_sam3x8e_gcc_rel.a <<< BUILT LIBSAM FOR SAM3X8E
│ └── libsam_sam3x8e_gcc_rel.a.txt <<< DUMPFILE OF THE LIBSAM CONTENTS
│
├── make
│ └── make_due_firmware.mk <<< INCLUDE THIS MAKEFILE IN YOUR MAKEFILE
│
├── sam <<< ARM/ATMEL/CSMIS INCLUDE DIRECTORY
│ ├── CMSIS <<< CSMIS INCLUDES
│ ├── libsam <<< ATMEL PERIPHERAL SPECIFIC INCLUDES
│ └── linker_scripts <<< LINKER SCRIPTS
│
└── tools <<< TOOLCHAIN
├── bossac <<< BOSSAC (BOSSA-UPLOADER FOR SAM-BA)
└── g++_arm_none_eabi <<< GCC FOR ARM (CODE SOURCERY)
Setup script
Because of some incompatibilities with shell programs under Linux and MacOS I transferred the installation to a PHP CLI script:
Installationsskript
Wegen ein paar Inkompatibilitäten mit Shellprogrammen unter Linux und MacOS habe ich das Installationsskript in ein PHP CLI-Skript umgeschrieben:
#!/usr/bin/php
<?
// Short functions
define("CHK_ROOT_PATH", rtrim(__DIR__, '/'));
function chk($f) { if(realpath(dirname($f))===false || stripos(realpath(dirname($f)),
CHK_ROOT_PATH) === false) yield("Path '$f' is not in the allowed base path."); }
function yield($text) { file_put_contents("php://stderr", "\e[31m$text\e[0m\n");
exit(1); }
function e($arg) { return escapeshellarg($arg); }
function sh($cmd) { @system($cmd, $r); return $r; }
function gsh($cmd) { ob_start(); @system($cmd); return @ob_get_clean(); }
function cp($from, $to) { chk(($to)); if(sh("cp -R " . e($from) . " " . e($to)))
yield("Failed to copy '$from' --> '$to'"); }
function cd($to) { if(!chdir($to)) yield("Failed to change directory to '$to'"); }
function mv($from, $to) { chk(($to)); if(sh("mv ".e($from)." ".e($to)))
yield("Failed to move '$from' --> '$to'"); }
function rm($f) { chk(($f)); if(!($f=realpath($f)) || sh("rm -rf " .e($f) != 0))
yield("Failed to remove $f"); } ;
function md($dir) { chk(($dir)); if(sh("mkdir -p " . e($dir)))
yield("Failed create directory '$dir'"); }
function arg($i) { return isset($_SERVER['argv'][$i]) ? $_SERVER['argv'][$i] : null; }
function pwd() { return getcwd(); }
function gfile($f) { if(($t=file_get_contents($f))===false)
yield("Failed to read file '$f'"); return $t; }
function wfile($f, $t) { chk(($f)); if(!file_put_contents($f, $t))
yield("Failed to write file '$f'"); }
function cat($f) { print gfile($f) . "\n"; }
function repf($f, $s, $r, $sim=false) { chk(($f)); $t=preg_replace($s, $r, gfile($f));
if(!$ret) wfile($f, $t); return $t; }
function srchf($f, $s, &$m=null) { return preg_match($s, gfile($f), $m); }
function relpath($r, $f) { if($r==$f) return "."; while(strlen($r) && strlen($f)
&& substr($r,0,1)===substr($f,0,1)) { $r=substr($r,1); $f=substr($f, 1); }
return trim(!strlen($r) ? '.' : str_repeat('../', count(explode('/', $r))) .
$f, '/'); }
// Config
$ROOT_DIR = rtrim(__DIR__, "/") . "/due";
$SCRIPT_RESOURCE_DIR = __DIR__ . "/resources";
$TOOLS_DIR = "$ROOT_DIR/tools";
$GCC_EABI_DIR = "$TOOLS_DIR/g++_arm_none_eabi";
$BOSSAC = "$TOOLS_DIR/bossac";
$HARDW_DIR = "$ROOT_DIR/sam";
$DIST_LIB_DIR = "$ROOT_DIR/lib";
$DIST_INC_DIR = "$ROOT_DIR/include";
$DIST_SRC_DIR = "$ROOT_DIR/src";
// Run
if(!is_dir(arg(1))) yield('You need to specify your Arduino directory. ' .
'It contains the folders examples, hardware, ...');
cd(arg(1));
$SRC_DIR = pwd();
md($ROOT_DIR);
md($TOOLS_DIR);
md($HARDW_DIR);
md($DIST_LIB_DIR);
print "GCC ARM EABI toolchain ...\n";
md("$TOOLS_DIR/g++_arm_none_eabi");
cp("hardware/tools/g++_arm_none_eabi", "$TOOLS_DIR/");
print "BOSSA uploader/downloader ...\n";
cp("hardware/tools/bossac", $BOSSAC);
print "Arduino & Atmel libraries (SAM, CMSIS) ...\n";
cp("hardware/arduino/sam/system/CMSIS", "$HARDW_DIR/");
cp("hardware/arduino/sam/system/libsam", "$HARDW_DIR/");
cp("hardware/arduino/sam/variants/arduino_due_x/linker_scripts", "$HARDW_DIR/");
cd($HARDW_DIR);
print "Copying existing libraries ... \n";
sh("find . -type f -exec chmod 644 {} \\;");
sh("find . -type d -exec chmod 755 {} \\;");
sh("find . -type f -name *.a -exec cp {} '$DIST_LIB_DIR' \\;");
print "Copying 'patch' resources \n";
system("cp -R " . e("$SCRIPT_RESOURCE_DIR/include") . "* " . e("$DIST_INC_DIR") .
" >/dev/null 2>&1");
system("cp -R " . e("$SCRIPT_RESOURCE_DIR/make") . "* " . e("$ROOT_DIR/make") .
" >/dev/null 2>&1");
system("cp -R " . e("$SCRIPT_RESOURCE_DIR/example") . "* " . e("$ROOT_DIR/example") .
" >/dev/null 2>&1");
print "Creating libsam ... \n";
cd("$HARDW_DIR/libsam/build_gcc");
repf("Makefile", "|(OUTPUT_BIN)[\\s]*=[\\s]*[^\\s]+|ismx", "\\1=" . relpath(pwd(), $DIST_LIB_DIR));
repf("sam3.mk", "|(OUTPUT_BIN)[\\s]*=[\\s]*[^\\s]+|ismx", "\\1=" . relpath(pwd(), $DIST_LIB_DIR));
if(!srchf("gcc.mk", "|\\nARM_GCC_TOOLCHAIN=|i")) {
repf("gcc.mk", "|[\n]([\s]*CROSS_COMPILE[\s]*=)|ismx", "\nARM_GCC_TOOLCHAIN=" .
relpath(pwd(), $TOOLS_DIR) . "/g++_arm_none_eabi/bin\n\\1");
}
if(($ec=sh("make clean >/dev/null"))!=0) yield("Make returned exit code $ec.");
if(($ec=sh("make arduino_due_x >/dev/null"))!=0) yield("Make returned exit code $ec.");
Example application
Beispielprogramm
Main file
Main-Datei
#include "../include/due_sam3x.init.h"
#ifndef USE_PWM_TC0
/**
* Simply blink the amber LED on the DUE with 2Hz:
*/
int main(void)
{
/* The general init (clock, libc, watchdog ...) */
init_controller();
/* Board pin 13 == PB27 */
PIO_Configure(PIOB, PIO_OUTPUT_1, PIO_PB27, PIO_DEFAULT);
/* Main loop */
while(1) {
Sleep(250);
if(PIOB->PIO_ODSR & PIO_PB27) {
/* Set clear register */
PIOB->PIO_CODR = PIO_PB27;
} else {
/* Set set register */
PIOB->PIO_SODR = PIO_PB27;
}
}
return 0;
}
#else
/*
* The Arduino DUE LED is on pin 13 on the board, that is PB27 on the chip,
* which has the timer/counter I/O TIOB0 alternative. Atmel defines for this
* are PIO_PB27, PIO_PB27B_TIOB0 (Port B 27, Timer I/O B channel 0).
*/
int main(void)
{
/* The general init (clock, libc, watchdog disable) */
init_controller();
/* Use Timer/Counter 0 (enable its clock) */
pmc_enable_periph_clk(ID_TC0);
#define LED_CH (0)
#define TC0_PERIOD (0xffff)
/* Configure as PWM using upward counter */
TC_Configure(TC0, LED_CH, 0 /* Channel 0 on TC0 */
|TC_CMR_TCCLKS_TIMER_CLOCK2 /* Use TCLK2 as source === MCLK/8 */
|TC_CMR_WAVE /* Waveform mode ("PWM") */
|TC_CMR_WAVSEL_UP_RC /* Count upwards to register C (==RC) */
|TC_CMR_BCPB_CLEAR /* Switch TIOB off when reaching RB Compare */
|TC_CMR_BCPC_SET /* Switch TIOB on when reaching RC Compare */
|TC_CMR_EEVT_XC0
);
PIO_Configure(PIOB, PIO_PERIPH_B, PIO_PB27B_TIOB0, PIO_DEFAULT);
TC_SetRC(TC0, LED_CH, TC0_PERIOD);/* Period: CLK/65536 == 10Hz */
TC_SetRB(TC0, 0, 0); /* Initial duty cycle: 0 */
TC_Start(TC0, LED_CH); /* Start timer (for channel 0) */
/* Main loop */
int16_t d = 1;
int16_t duty_cycle = 25;
while(1) {
Sleep(25);
duty_cycle += d;
if(duty_cycle >= 48 || duty_cycle <= 2) d = -d;
TC_SetRB(TC0, 0, duty_cycle * TC0_PERIOD / 50);
}
return 0;
}
#endif
Makefile
OUTPUT_DIR = .
PROJECT_DIR = .
UPLOAD_PORT=/dev/cu.usbmodemfa141
all: binary install
include ../make/make_due_firmware.mk
Build output
Ausgabe der Erstellung
--------------------------------------------------------------------------------
-- Make the binary:
--------------------------------------------------------------------------------
$ cd due/example/
$ make binary
"[...]/due/tools/g++_arm_none_eabi/bin/arm-none-eabi-gcc"
-c -Wall --param max-inline-insns-single=500 -mcpu=cortex-m3 -mthumb -mlong-calls
-ffunction-sections -fdata-sections -nostdlib -std=c99 -Os -I[...]/due/include
-I[...]/due/sam -I[...]/due/sam/libsam -I[...]/due/sam/CMSIS/CMSIS/Include
-I[...]/due/sam/CMSIS/Device/ATMEL main.c -o release/main.o
"[...]/due/tools/g++_arm_none_eabi/bin/arm-none-eabi-ar" rcs release/firmware.a release/main.o
"[...]/due/tools/g++_arm_none_eabi/bin/arm-none-eabi-nm" release/firmware.a > release/firmware.a.txt
"[...]/due/tools/g++_arm_none_eabi/bin/arm-none-eabi-g++" -Os -Wl,--gc-sections -mcpu=cortex-m3 \
"-T[...]/due/sam/linker_scripts/gcc/flash.ld" "-Wl,-Map,release/firmware.map" \
-o release/firmware.elf \
"-Lrelease" \
-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 \
release/firmware.a [...]/due/lib/libsam_sam3x8e_gcc_rel.a \
-Wl,--end-group
"[...]/due/tools/g++_arm_none_eabi/bin/arm-none-eabi-objcopy" -O binary
release/firmware.elf release/firmware.bin
--------------------------------------------------------------------------------
-- Send binary to controller:
--------------------------------------------------------------------------------
$ make install
Touch programming port ...
Waiting before uploading ...
Uploading ...
Erase flash
Write 1564 bytes to flash
[==============================] 100% (7/7 pages)
Verify 1564 bytes of flash
[==============================] 100% (7/7 pages)
Verify successful
Set boot flash true
CPU reset.
Done.
Resources added to the setup script
An das Setup-Skript angefügte Resourcen
Build Makefile
Build Makefile
#-------------------------------------------------------------------------------
# @author stfwi
# @file make_due_firmware.mk
#
# INCLUDE THIS FILE IN YOUR MAKEFILE USING THE ...
#
# include <path/to/>make_due_firmware.mk
#
# ... MAKEFILE DIRECTIVE.
#
# You have then the options:
#
# make all : Everything except uploading
# make binary : Makes the binary that can be uploaded (default firmware.bin)
# make install : Uploads to the DUE using BOSSA
# make clean : Cleans up the "$OUTPUT_DIR/release" or "$OUTPUT_DIR/debug"
#
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# CONFIG: OVERWRITE as params to modify
#-------------------------------------------------------------------------------
.SUFFIXES: .o .a .c .s
SHELL = /bin/sh
OUTPUT_NAME=firmware
OUTPUT_DIR = .
PROJECT_DIR = .
UPLOAD_PORT=/dev/cu.usbmodemfa141
USB_DEFINITIONS=-DUSB_VID=0x2341 -DUSB_PID=0x003e -DUSBCON '-DUSB_MANUFACTURER="Unknown"' '-DUSB_PRODUCT="Arduino Due"'
#-------------------------------------------------------------------------------
# Related directories and files
#-------------------------------------------------------------------------------
ROOT := $(realpath $(shell dirname '$(dir $(lastword $(MAKEFILE_LIST)))'))
vpath %.c $(PROJECT_DIR)
VPATH+=$(PROJECT_DIR)
INCLUDES =
INCLUDES += -I$(ROOT)/include
INCLUDES += -I$(ROOT)/sam
INCLUDES += -I$(ROOT)/sam/libsam
INCLUDES += -I$(ROOT)/sam/CMSIS/CMSIS/Include
INCLUDES += -I$(ROOT)/sam/CMSIS/Device/ATMEL
#-------------------------------------------------------------------------------
# Target selection
#-------------------------------------------------------------------------------
ifdef DEBUG
OPTIMIZATION = -g -O0 -DDEBUG
OBJ_DIR=debug
else
OPTIMIZATION = -Os
OBJ_DIR=release
endif
#-------------------------------------------------------------------------------
# Toolchain
#-------------------------------------------------------------------------------
CROSS_COMPILE = $(ROOT)/tools/g++_arm_none_eabi/bin/arm-none-eabi-
AR = $(CROSS_COMPILE)ar
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++
AS = $(CROSS_COMPILE)as
NM = $(CROSS_COMPILE)nm
LKELF = $(CROSS_COMPILE)g++
OBJCP = $(CROSS_COMPILE)objcopy
RM=rm -Rf
MKDIR=mkdir -p
UPLOAD_BOSSA=$(ROOT)/tools/bossac
#-------------------------------------------------------------------------------
# Flags
#-------------------------------------------------------------------------------
CFLAGS += -Wall --param max-inline-insns-single=500 -mcpu=cortex-m3 -mthumb -mlong-calls
CFLAGS += -ffunction-sections -fdata-sections -nostdlib -std=c99
CFLAGS += $(OPTIMIZATION) $(INCLUDES)
#CFLAGS += -Dprintf=iprintf
CPPFLAGS += -Wall --param max-inline-insns-single=500 -mcpu=cortex-m3 -mthumb -mlong-calls -nostdlib
CPPFLAGS += -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -std=c++98
CPPFLAGS += $(OPTIMIZATION) $(INCLUDES)
#CPPFLAGS += -Dprintf=iprintf
ASFLAGS = -mcpu=cortex-m3 -mthumb -Wall -g $(OPTIMIZATION) $(INCLUDES)
ARFLAGS = rcs
LNK_SCRIPT=$(ROOT)/sam/linker_scripts/gcc/flash.ld
LIBSAM_ARCHIVE=$(ROOT)/lib/libsam_sam3x8e_gcc_rel.a
UPLOAD_PORT_BASENAME=$(patsubst /dev/%,%,$(UPLOAD_PORT))
#-------------------------------------------------------------------------------
# High verbosity flags
#-------------------------------------------------------------------------------
ifdef VERBOSE
CFLAGS += -Wall -Wchar-subscripts -Wcomment -Wformat=2 -Wimplicit-int
CFLAGS += -Werror-implicit-function-declaration -Wmain -Wparentheses
CFLAGS += -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs -Wunused
CFLAGS += -Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wundef
CFLAGS += -Wshadow -Wpointer-arith -Wbad-function-cast -Wwrite-strings
CFLAGS += -Wsign-compare -Waggregate-return -Wstrict-prototypes
CFLAGS += -Wmissing-prototypes -Wmissing-declarations
CFLAGS += -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations
CFLAGS += -Wredundant-decls -Wnested-externs -Winline -Wlong-long
CFLAGS += -Wunreachable-code
CFLAGS += -Wcast-align
CFLAGS += -Wmissing-noreturn
CFLAGS += -Wconversion
CPPFLAGS += -Wall -Wchar-subscripts -Wcomment -Wformat=2
CPPFLAGS += -Wmain -Wparentheses -Wcast-align -Wunreachable-code
CPPFLAGS += -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs -Wunused
CPPFLAGS += -Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wundef
CPPFLAGS += -Wshadow -Wpointer-arith -Wwrite-strings
CPPFLAGS += -Wsign-compare -Waggregate-return -Wmissing-declarations
CPPFLAGS += -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations
CPPFLAGS += -Wpacked -Wredundant-decls -Winline -Wlong-long
CPPFLAGS += -Wmissing-noreturn
CPPFLAGS += -Wconversion
UPLOAD_VERBOSE_FLAGS += -i -d
endif
#-------------------------------------------------------------------------------
# Source files and objects
#-------------------------------------------------------------------------------
C_SRC=$(wildcard $(PROJECT_DIR)/*.c) $(wildcard ../src/*.c)
C_OBJ=$(patsubst %.c, %.o, $(notdir $(C_SRC)))
CPP_SRC=$(wildcard $(PROJECT_DIR)/*.cpp)
CPP_OBJ=$(patsubst %.cpp, %.o, $(notdir $(CPP_SRC)))
A_SRC=$(wildcard $(PROJECT_DIR)/*.s)
A_OBJ=$(patsubst %.s, %.o, $(notdir $(A_SRC)))
#-------------------------------------------------------------------------------
# Rules
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
all: binary
#-------------------------------------------------------------------------------
.PHONY: clean
clean:
-@$(RM) $(OBJ_DIR) 1>/dev/null 2>&1
-@$(RM) $(OUTPUT_DIR)/$(OUTPUT_NAME) 1>/dev/null 2>&1
#-------------------------------------------------------------------------------
.PHONY: prepare
prepare:
-@$(MKDIR) $(OBJ_DIR) 1>/dev/null 2>&1
#-------------------------------------------------------------------------------
.PHONY: binary
binary: prepare $(OBJ_DIR)/$(OUTPUT_NAME).bin
#-------------------------------------------------------------------------------
# .bin ------> UPLOAD TO CONTROLLER
.PHONY: install
install: binary
-@echo "Touch programming port ..."
-@stty -f "/dev/$(UPLOAD_PORT_BASENAME)" raw ispeed 1200 ospeed 1200 cs8 -cstopb ignpar eol 255 eof 255
-@printf "\x00" > "/dev/$(UPLOAD_PORT_BASENAME)"
-@echo "Waiting before uploading ..."
-@sleep 1
-@echo "Uploading ..."
$(UPLOAD_BOSSA) $(UPLOAD_VERBOSE_FLAGS) --port="$(UPLOAD_PORT_BASENAME)" -U false -e -w -v -b "$(OBJ_DIR)/$(OUTPUT_NAME).bin" -R
# $(UPLOAD_BOSSA) $(UPLOAD_VERBOSE_FLAGS) --port="$(UPLOAD_PORT_BASENAME)" -U false -e -w -b "$(OBJ_DIR)/$(OUTPUT_NAME).bin" -R
@echo "Done."
#-------------------------------------------------------------------------------
# .c -> .o
$(addprefix $(OBJ_DIR)/,$(C_OBJ)): $(OBJ_DIR)/%.o: %.c
"$(CC)" -c $(CFLAGS) $< -o $@
# .cpp -> .o
$(addprefix $(OBJ_DIR)/,$(CPP_OBJ)): $(OBJ_DIR)/%.o: %.cpp
"$(CC)" -xc++ -c $(CPPFLAGS) $< -o $@
# .s -> .o
$(addprefix $(OBJ_DIR)/,$(A_OBJ)): $(OBJ_DIR)/%.o: %.s
"$(AS)" -c $(ASFLAGS) $< -o $@
# .o -> .a
$(OBJ_DIR)/$(OUTPUT_NAME).a: $(addprefix $(OBJ_DIR)/, $(C_OBJ)) $(addprefix $(OBJ_DIR)/, $(CPP_OBJ)) $(addprefix $(OBJ_DIR)/, $(A_OBJ))
"$(AR)" $(ARFLAGS) $@ $^
"$(NM)" $@ > $@.txt
# -> .elf
$(OBJ_DIR)/$(OUTPUT_NAME).elf: $(OBJ_DIR)/$(OUTPUT_NAME).a
"$(LKELF)" -Os -Wl,--gc-sections -mcpu=cortex-m3 \
"-T$(LNK_SCRIPT)" "-Wl,-Map,$(OBJ_DIR)/$(OUTPUT_NAME).map" \
-o $@ \
"-L$(OBJ_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 \
$^ $(LIBSAM_ARCHIVE) \
-Wl,--end-group
# .elf -> .bin
$(OBJ_DIR)/$(OUTPUT_NAME).bin: $(OBJ_DIR)/$(OUTPUT_NAME).elf
"$(OBJCP)" -O binary $< $@
Library include
Library include
/**
* Include file for the basic libraries - Arduino DUE with SAM3X8E
*
* - It defines __SAM3X8E__, MAIN_OSC_FREQ (main oscillator frequency),
* MASTER_CLK_FREQ (the master clock frequency).
*
* - It includes the peripheral specific libsam and sam.h
*
* @file due_sam3x.h
* @author stfwi
*/
#ifndef __ARDUINO_DUE_X_H__INCLUDED__
#define __ARDUINO_DUE_X_H__INCLUDED__
#ifdef __cplusplus
extern "C" {
#endif
#define __SAM3X8E__
#ifdef __SAM3X8E__
#define MAIN_OSC_FREQ (12000000)
#define MASTER_CLK_FREQ (84000000)
#endif
#include "../sam/libsam/chip.h"
#include "../sam/CMSIS/Device/ATMEL/sam.h"
extern void init_controller(void);
#ifdef __cplusplus
}
#endif
#endif
Initialisation code
Initialisierungs-Quelltext
/**
* Include or paste this file only in your main file (before your main function).
*
* It defines the basics to run the SAM3 controller:
*
* - Interrupt handlers (like interrupt service routines (ISR))
*
* - The system default system tick ISR is used with a 32 bit counter.
* Modify SysTick_Handler as you like it.
*
* - Provides the "init_controller()" function, that simply forwards
* to SAM SystemInit(), ensures that the libc is initialized the system
* tick interrupt is set to one millisecond, and that the watchdog is
* disabled (and dies not throw an NMI after a bit of time).
*
* - That's pretty much it - now you have the plain controller and full
* control over it.
*
* @file due_am3x.init.h
* @author stfwi
*/
#include "due_sam3x.h"
#ifdef __cplusplus
extern "C" {
#endif
/********************************************************************************
* Device interrupt vector. Functions are overwritable (weak aliases).
********************************************************************************/
static void __phantom_handler(void) { while(1); }
void NMI_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void HardFault_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void MemManage_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void BusFault_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void UsageFault_Handler(void) __attribute__ ((weak, alias("__phantom_handler")));
void DebugMon_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void SVC_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void PendSV_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void SysTick_Handler(void) { TimeTick_Increment(); }
void SUPC_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void RSTC_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void RTC_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void RTT_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void WDT_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void PMC_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void EFC0_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void EFC1_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void UART_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
#ifdef _SAM3XA_SMC_INSTANCE_
void SMC_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
#endif
#ifdef _SAM3XA_SDRAMC_INSTANCE_
void SDRAMC_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
#endif
void PIOA_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void PIOB_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
#ifdef _SAM3XA_PIOC_INSTANCE_
void PIOC_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
#endif
#ifdef _SAM3XA_PIOD_INSTANCE_
void PIOD_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
#endif
#ifdef _SAM3XA_PIOE_INSTANCE_
void PIOE_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
#endif
#ifdef _SAM3XA_PIOF_INSTANCE_
void PIOF_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
#endif
void USART0_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void USART1_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void USART2_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
#ifdef _SAM3XA_USART3_INSTANCE_
void USART3_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
#endif
void HSMCI_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void TWI0_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void TWI1_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void SPI0_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
#ifdef _SAM3XA_SPI1_INSTANCE_
void SPI1_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
#endif
void SSC_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void TC0_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void TC1_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void TC2_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void TC3_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void TC4_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void TC5_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
#ifdef _SAM3XA_TC2_INSTANCE_
void TC6_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void TC7_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void TC8_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
#endif
void PWM_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void ADC_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void DACC_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void DMAC_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void UOTGHS_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void TRNG_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
#ifdef _SAM3XA_EMAC_INSTANCE_
void EMAC_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
#endif
void CAN0_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
void CAN1_Handler (void) __attribute__ ((weak, alias("__phantom_handler")));
/********************************************************************************
* Controller initialisation. Call this function in main(), which is itself called
* from Reset_Handler()
********************************************************************************/
void __libc_init_array(void);
void init_controller(void)
{
/*
* SAM System init: Initializes the PLL / clock.
* Defined in CMSIS/ATMEL/sam3xa/source/system_sam3xa.c
*/
SystemInit();
/*
* Config systick interrupt timing, core clock is in microseconds --> 1ms
* Defined in CMSIS/CMSIS/include/core_cm3.h
*/
if (SysTick_Config(SystemCoreClock / 1000)) while (1);
/*
* No watchdog now
*
*/
WDT_Disable(WDT);
/*
* GCC libc init, also done in Reset_Handler()
*/
__libc_init_array();
}
/********************************************************************************
* C++ catching pure virtual methods ( virtual myMethod = 0)
********************************************************************************/
void __cxa_pure_virtual(void)
{ while(1); }
#ifdef __cplusplus
}
#endif
/********************************************************************************
* EOF
********************************************************************************/
Netbeans-Project
To use Netbeans as IDE simply copy the example folder somewhere, modify the repative
paths in the Makefile
and main
, open Netbeans and say "New C/C++ Project -- With existing sources",
and select your project folder. This should already compile (and flash if your
Makefile
reads all: binary install
instead of all: binary
).
To make the code assistance better, open the project properties and specify in
section "Code Assistance" for both C
and C++
:
Netbeans-Project
Um Netbeans als IDE zu verwenden, kopiere den Beispiel-Ordner einfach an eine
andere Stelle, passe die relativen Pfade an, öffne Netbeans, sag "New C/C++ Project -- With existing sources",
und wähle den neu erstellten Projektordner aus. Jetzt sollte direkt kompiliert
werden (und auch geflasht werden wenn im Makefile
statt all: binary
all: binary install
steht).
Für den "Code Assist" einzustellen einfach die Projekteinstellungen öffnen und
im Abschnitt "Code Assistance" für C
und C++
angeben:
Preprocessor definitions:
__SAM3X8E__
Include directories:
[path-to-due]/include
[path-to-due]/libsam
[path-to-due]/CMSIS/CMSIS/include
[path-to-due]/CMSIS/Device/Atmel
[path-to-due]/CMSIS/Device/Atmel/sam3xa/include
That's it, have fun with it !
Links and resources
Fertig, viel Spaß !