ARM GCC: Unterschied zwischen den Versionen
(11 dazwischenliegende Versionen von 6 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
[[ | ARM-GCC bezeichnet die für [[ARM]]-Mikrocontroller konfigurierte Variante des C- und C++- [[Compiler|Crosscompilers]] GCC. | ||
== GCC Binärdistributionen == | |||
In diesem Artikel geht es primär um den arm-none-eabi-gcc, der ein für embedded Systems optimiertes ABI (Application Binary Interface) hat. Für ARM-System, die ein eigenständiges OS (wie Linux) haben, gibt es den arm-elf-gcc. | |||
Es gibt diverse fertige Binärdistributionen die für verschiedene Controller mit ARM-Kern verwendet werden können. | |||
== Bestandteile == | |||
Die Toolchain besteht aus mehreren Kommandozeilen-Programmen, die sich auf einfache Weise in einen Editor oder eine Entwicklungsumgebung einbinden lassen. Weit verbreitet ist die Verwendung von make zur Steuerung. | |||
Die Bestandteile im einzelnen: | |||
* Binutils: Assembler, Linker und weitere Hilfsprogramme. | |||
* GCC: Der eigentliche C(++)-Compiler. | |||
* eine C-Standardbibliothek | |||
Die vorherrschende C-Bibliothek ist die [https://sourceware.org/newlib/ newlib] (oder auch [https://github.com/32bitmicro/newlib-nano-1.0 newlib-nano]), für andere Optionen siehe [http://wiki.osdev.org/C_Library#Implementations hier]. | |||
Bei der Auswahl der Toolchain sollte beachtet werden, dass es größere Unterschiede bei den bereitgestellten C-Bibliotheken gibt. Die Sourcery Codebench Lite-Edition stellt z.B. keine Bibliotheken mit FPU-Unterstützung bereit, so dass trotz vorhandener FPU beim Cortex-M4 nur suboptimaler Code erzegt werden kann. Siehe [http://wiki.debian.org/ArmHardFloatPort/VfpComparison] für ein kleines Beispiel und eine Erklärung. | |||
== Fertige GCC Binärdistributionen == | |||
* [https://developer.arm.com/open-source/gnu-toolchain/gnu-rm GCC-ARM-Embedded] ([https://launchpad.net/gcc-arm-embedded Ältere Releases]) für Cortex-R4/R5/R7/R8/M0(+)/M3/M4(F)/M7/M23/M33. Windows, Linux, Mac, bereitgestellt von ARM selbst, vollständiger Support für FPUs, C++17, kein Code-Size-Limit | |||
* [https://bugs.launchpad.net/gcc-arm-embedded/+bug/1742188 Windows Windows 64bit Binaries] vom GCC-ARM-Embedded und Anleitung zum Selbstkompilieren; nützlich für extrem speicherhungrige Kompilationen (z.B. bei templates) | |||
* [http://www.mentor.com/embedded-software/codesourcery Mentor Graphics Sourcery Tools (vormals CodeSourcery CodeBench Lite)] Windows, Linux | * [http://www.mentor.com/embedded-software/codesourcery Mentor Graphics Sourcery Tools (vormals CodeSourcery CodeBench Lite)] Windows, Linux | ||
* [http://sourceforge.net/projects/devkitpro/ devkitPro] | * [http://sourceforge.net/projects/devkitpro/ devkitPro] | ||
* [http://www.lpcware.com/lpcxpresso/home LPCXpresso] (vormals CodeRed IDE) ist eine IDE von NXP für die LPC-Mikrocontroller die den GCC enthält | * [http://www.lpcware.com/lpcxpresso/home LPCXpresso] (vormals CodeRed IDE) ist eine IDE von NXP für die LPC-Mikrocontroller die den GCC enthält | ||
Zeile 8: | Zeile 26: | ||
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/#winarm WinARM] - veraltet | * [http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/#winarm WinARM] - veraltet | ||
* GNUARM - veraltet | * GNUARM - veraltet | ||
* summon-arm Toolchain: hat einen Compiler-Bug [http://www.mail-archive.com/gcc-bugs@gcc.gnu.org/msg353473.html] und sollte daher nicht verwendet werden, wenn man floatingpoint-Typen einsetzen möchte (egal ob mit oder ohne FPU). | |||
Beim Einsatz des gcc in Verbindung mit in C geschriebenem startup-Code bei den Optimierungsleveln "-O2" und "-O3" muss zusätzlich "-fno-gcse" gesetzt werden, da ansonsten die von der CPU benötigte NVIC-Tabelle(n) und zugehörige Funktionen unter Umständen nicht so aussehen wie sie sollten. | |||
Beim Einsatz des gcc in Verbindung mit in C geschriebenem startup-Code bei den | |||
Siehe auch [http://embdev.net/topic/129986#1175214 ARM-GCC development resources] im Forum. | Siehe auch [http://embdev.net/topic/129986#1175214 ARM-GCC development resources] im Forum. | ||
Zeile 20: | Zeile 35: | ||
Hier einige Hinweise wie man den GCC direkt verwenden kann (zB. mit selbstgebautem makefile), falls man das nicht von einer Entwicklungsumgebung machen lässt. | Hier einige Hinweise wie man den GCC direkt verwenden kann (zB. mit selbstgebautem makefile), falls man das nicht von einer Entwicklungsumgebung machen lässt. | ||
=== Compiler & Linker Flags === | === Compiler & Linker Flags === | ||
Die Flags, die festlegen, welcher Core verwendet wird, sind in der folgenden Tabelle beschrieben: | |||
{| class="wikitable" | {| class="wikitable" | ||
! Option | |||
! style="text-align: center;" | Cortex-M0 | |||
! style="text-align: center;" | Cortex-M0+ | |||
! style="text-align: center;" | Cortex-M3 | |||
! style="text-align: center;" | Cortex-M4 | |||
! style="text-align: center;" | Cortex-M7 | |||
! style="text-align: center;" | Cortex-M33 | |||
! style="text-align: center;" | Cortex-M23 | |||
|- | |- | ||
| CPU | |||
| -mcpu=cortex-m0<sup>[1]</sup> | |||
| -mcpu=cortex-m0plus<sup>[1]</sup> | |||
| -mcpu=cortex-m3 | |||
| -mcpu=cortex-m4 | |||
| -mcpu=cortex-m7 | |||
| -mcpu=cortex-m33 | |||
| -mcpu=cortex-m23 | |||
|- | |- | ||
| | | Float ABI | ||
| colspan="3" style="text-align: center;" | -mfloat-abi=soft | |||
| colspan="3" style="text-align: center;" | -mfloat-abi=soft | |||
|- | |||
-mfloat-abi=softfp | |||
-mfloat-abi=hard | |||
| style="text-align: center;" | -mfloat-abi=soft | |||
|- | |- | ||
| | | FPU | ||
|- | | colspan="3" | | ||
| -mfpu=fpv4-sp-d16 | |||
| -mfpu=fpv5-d16 | |||
| -mfpu=fpv5-sp-d16 / -mfpu=fpv5-d16 | |||
| | |||
|- | |- | ||
| Instruction Set | |||
| colspan="7" style="text-align: center;" | -mthumb | |||
|} | |} | ||
* | <sup>[1]</sup><small>Anmerkung: Es gibt für diese Cores 2 Optionen (für den Hersteller): diese Betreffen die Multiplikationsbefehle. | ||
* Die übliche Implementierung enthält einen 1-Takt-Multiplizierer | |||
* Für reduzierte Chipfläche kann auche ein 32-Takt-Multiplizierer ausgewählt werden | |||
Um nun bei Multiplikationen mit Konstanten nicht die langsame 32-Takt-Multiplikation zu nutzen kann der Compiler angewiesen werden, dort Shifts oder Ähnliches zu generieren. | |||
Um dem Compiler das mitzuteilen wird der Parameter, der die CPU angibt, abgeändert: -mcpu=cortex-m0[plus].small-multiply</small> | |||
Zusätzlich zu diesen Flags gibt es noch die Maschinenunabhängigen Parameter, wovon hier nur einige wichtigen erläutert werden: | |||
{| class="wikitable" | {| class="wikitable" | ||
! style="width: 20% | Option !! Erklärung | |||
|- | |- | ||
| -W[all, extra] | |||
| Lässt den Compiler Warnungen ausgeben. | |||
-Wall gibt nur Standard-Warnungen aus, nicht alle! | |||
-Wextra erzeugt noch einmal mehr Warnungen. | |||
|- | |- | ||
| | | -O[0,1,2,3,s,g] | ||
| Wählt die Art der Optimierung. | |||
-O0: keine Optimierung | |||
-O[1,2,3]: Optimierung auf Ausführungsgeschwindigkeit. Je höher die Stufe, desto aggressiver ist die Optimierung. Das führt unter Umständen zu beträchtlich größerem Code | |||
-Os: Optimierung auf Codegröße | |||
-Og: Optimierung, aber so, dass das Debugging nicht erschwert wird | |||
|- | |- | ||
| -fdata-sections | |||
-ffunction-sections | |||
| Teilt jeder Funktion/jeder Variable eine eigene Section zu.Damit kann der Linker mit der Option --gc-sections ungenutzte Funktionen entfernen. Siehe [[GCC:_unbenutzte_Funktionen_entfernen]] | |||
|- | |- | ||
| | | -Wl,--gc-sections | ||
| Der Linker verwirft unreferenzierte Sections und packt diese damit nicht ins Binary. Siehe [[GCC:_unbenutzte_Funktionen_entfernen]] | |||
|- | |- | ||
| | | -g | ||
| Erzeugt Debugging-Informationen. | |||
Siehe auch [https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html GCC Debugging Options] | |||
|- | |- | ||
| | | -fno-rtti | ||
-fno-exceptions | |||
| C++-Optionen | |||
Teilt dem Compiler mit, dass | |||
- keine Runtime Type Information zu generieren sind | |||
- keine Exceptions benutzt werden und damit kein Overhead generiert werden muss. | |||
|- | |- | ||
| -flto | |||
| Link-Time-Optimizations: | |||
Der Linker optimiert den kompletten Code. Da er nicht nur ein Source-File, sondern alle kennt, kann er optimieren, wo dem Compiler Informationen fehlen. | |||
Achtung: bei älteren Compiler-Versionen muss nach diesem Flag noch einmal die Optimierungsstufe angegeben werden. | |||
|} | |} | ||
Die [http://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html#Option-Summary GCC Dokumentation] listet alle Parameter auf, auch [http://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html#ARM-Options Parameter speziell für ARM]. | |||
* Siehe auch das [https://launchpadlibrarian.net/135588846/readme.txt Readme vom GCC-ARM-Embedded] | * Siehe auch das [https://launchpadlibrarian.net/135588846/readme.txt Readme vom GCC-ARM-Embedded] | ||
Zeile 58: | Zeile 127: | ||
* Die LTO erkennt die ISR's und den Interrupt Vector möglicherweise als "unbenutzt" und optimiert sie daher weg. Dies kann durch Markierung der Funktionen & Variablen mit "__attribute__ ((used))" verhindert werden. | * Die LTO erkennt die ISR's und den Interrupt Vector möglicherweise als "unbenutzt" und optimiert sie daher weg. Dies kann durch Markierung der Funktionen & Variablen mit "__attribute__ ((used))" verhindert werden. | ||
* Alle Compileroptionen müssen auch beim Linken mit angegeben werden (ist in obiger Tabelle berücksichtigt), da auch dann u.U. Code generiert werden kann. | * Alle Compileroptionen müssen auch beim Linken mit angegeben werden (ist in obiger Tabelle berücksichtigt), da auch dann u.U. Code generiert werden kann. | ||
=== Startupcode & Linkerscript === | === Startupcode & Linkerscript === | ||
* Damit der compilierte Code an den richtigen Stellen im Controller landet (d.h. dem Flash) muss man dem Linker ein Linkerscript mitgeben. Dies geht per "-T ''pfad_zum_linkerscript.ld''" an den Linker-Befehl. Das Script ist praktisch Controller-spezifisch, es gibt Beispiel-Scripte der Controller-Hersteller. | * Damit der compilierte Code an den richtigen Stellen im Controller landet (d.h. dem Flash) muss man dem Linker ein Linkerscript mitgeben. Dies geht per "-T ''pfad_zum_linkerscript.ld''" an den Linker-Befehl. Das Script ist praktisch Controller-spezifisch, es gibt Beispiel-Scripte der Controller-Hersteller. | ||
* Damit beim Starten die richtigen Initialisierungen vorgenommen werden (wie globale Variablen und bei C++ Konstruktoren globaler Objekt-Instanzen) muss als erstes ein Startupcode laufen, der dann die main()-Funktion aufruft. | * Damit beim Starten die richtigen Initialisierungen vorgenommen werden (wie globale Variablen und bei C++ Konstruktoren globaler Objekt-Instanzen) muss als erstes ein Startupcode laufen, der dann die main()-Funktion aufruft. Startupcode im allgemeinen ist meistens in Assembler geschrieben, aber die ARM-Architektur macht aber auch einfacheren C/C++-Code möglich. Auch für den Startupcode gibt es Beispiele der Controller-Hersteller. | ||
Zusammen bieten die beiden Dateien der Anwendung ein Standard-C-Interface, d.h. man kann wie gewohnt globale Variablen verwenden und seinen Code in die main()-Funktion schreiben. | Zusammen bieten die beiden Dateien der Anwendung ein Standard-C-Interface, d.h. man kann wie gewohnt globale Variablen verwenden und seinen Code in die main()-Funktion schreiben. | ||
=== FPU der Cortex-M4F nutzen === | === FPU der Cortex-M4F nutzen === | ||
Um die FPU zu nutzen, muss | Um die FPU zu nutzen, muss der Compiler per [[#Compiler_.26_Linker_Flags|Flag]] dazu gebracht werden, FPU-Instruktionen zu generieren. | ||
Außerdem muss vor Benutzung der FPU-Befehle die FPU aktiviert werden, dies geschieht typischerweise im Startupcode, bevor die main() -Funktion aufgerufen wird. Hier die entsprechenden Befehle, falls sie im verwendeten Startupcode nicht onehin schon enthalten sind: | Außerdem muss vor Benutzung der FPU-Befehle die FPU aktiviert werden, dies geschieht typischerweise im Startupcode, bevor die main() -Funktion aufgerufen wird. Hier die entsprechenden Befehle, falls sie im verwendeten Startupcode nicht onehin schon enthalten sind: | ||
< | <syntaxhighlight lang="asm">/*FPU settings*/ | ||
ldr r0, =0xE000ED88 /* Enable CP10,CP11 */ | ldr r0, =0xE000ED88 /* Enable CP10,CP11 */ | ||
ldr r1,[r0] | ldr r1,[r0] | ||
orr r1,r1,#(0xF << 20) | orr r1,r1,#(0xF << 20) | ||
str r1,[r0]</ | str r1,[r0] | ||
</syntaxhighlight> | |||
In C/C++ unter Verwendung der CMSIS geht es so: | In C/C++ unter Verwendung der CMSIS geht es so: | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
Zeile 77: | Zeile 149: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Weiterhin sollte die GCC-Distribution auch Laufzeitbibliotheken mit FPU-Unterstützung mitbringen (CodeBench lite und Yagarto werden ohne | Weiterhin sollte die GCC-Distribution auch Laufzeitbibliotheken mit FPU-Unterstützung mitbringen (CodeBench lite und Yagarto werden ohne ausgeliefert, GCC-ARM-Embedded mit). | ||
Am Beispiel der STM32F4 mehr dazu in diesem Thread: [http://www.mikrocontroller.net/topic/261021 Floating Pointing Unit STM32F4] | Am Beispiel der STM32F4 mehr dazu in diesem Thread: [http://www.mikrocontroller.net/topic/261021 Floating Pointing Unit STM32F4] | ||
=== | == Links == | ||
arm-none-eabi- | * [http://www.mikrocontroller.net/topic/298976#3197418 Hier] finden sich noch ein paar Tipps, für den 1. kann aber mittlerweile der GCC-ARM-Embedded direkt verwendet werden, da er jetzt LTO unterstützt (s.o.). | ||
* [https://www.mikrocontroller.net/topic/178840 Thread]: Unterschied arm-none-eabi-gcc und arm-elf-gcc | |||
[[Category:ARM]] | |||
[[Category:Compiler]] | |||
Aktuelle Version vom 5. Juni 2020, 06:30 Uhr
ARM-GCC bezeichnet die für ARM-Mikrocontroller konfigurierte Variante des C- und C++- Crosscompilers GCC.
In diesem Artikel geht es primär um den arm-none-eabi-gcc, der ein für embedded Systems optimiertes ABI (Application Binary Interface) hat. Für ARM-System, die ein eigenständiges OS (wie Linux) haben, gibt es den arm-elf-gcc.
Es gibt diverse fertige Binärdistributionen die für verschiedene Controller mit ARM-Kern verwendet werden können.
Bestandteile
Die Toolchain besteht aus mehreren Kommandozeilen-Programmen, die sich auf einfache Weise in einen Editor oder eine Entwicklungsumgebung einbinden lassen. Weit verbreitet ist die Verwendung von make zur Steuerung.
Die Bestandteile im einzelnen:
- Binutils: Assembler, Linker und weitere Hilfsprogramme.
- GCC: Der eigentliche C(++)-Compiler.
- eine C-Standardbibliothek
Die vorherrschende C-Bibliothek ist die newlib (oder auch newlib-nano), für andere Optionen siehe hier.
Bei der Auswahl der Toolchain sollte beachtet werden, dass es größere Unterschiede bei den bereitgestellten C-Bibliotheken gibt. Die Sourcery Codebench Lite-Edition stellt z.B. keine Bibliotheken mit FPU-Unterstützung bereit, so dass trotz vorhandener FPU beim Cortex-M4 nur suboptimaler Code erzegt werden kann. Siehe [1] für ein kleines Beispiel und eine Erklärung.
Fertige GCC Binärdistributionen
- GCC-ARM-Embedded (Ältere Releases) für Cortex-R4/R5/R7/R8/M0(+)/M3/M4(F)/M7/M23/M33. Windows, Linux, Mac, bereitgestellt von ARM selbst, vollständiger Support für FPUs, C++17, kein Code-Size-Limit
- Windows Windows 64bit Binaries vom GCC-ARM-Embedded und Anleitung zum Selbstkompilieren; nützlich für extrem speicherhungrige Kompilationen (z.B. bei templates)
- Mentor Graphics Sourcery Tools (vormals CodeSourcery CodeBench Lite) Windows, Linux
- devkitPro
- LPCXpresso (vormals CodeRed IDE) ist eine IDE von NXP für die LPC-Mikrocontroller die den GCC enthält
- Yagarto (Windows, mit Eclipse-Integration) - veraltet
- WinARM - veraltet
- GNUARM - veraltet
- summon-arm Toolchain: hat einen Compiler-Bug [2] und sollte daher nicht verwendet werden, wenn man floatingpoint-Typen einsetzen möchte (egal ob mit oder ohne FPU).
Beim Einsatz des gcc in Verbindung mit in C geschriebenem startup-Code bei den Optimierungsleveln "-O2" und "-O3" muss zusätzlich "-fno-gcse" gesetzt werden, da ansonsten die von der CPU benötigte NVIC-Tabelle(n) und zugehörige Funktionen unter Umständen nicht so aussehen wie sie sollten.
Siehe auch ARM-GCC development resources im Forum.
Nutzung mit eigener Umgebung/Kommandozeile
Hier einige Hinweise wie man den GCC direkt verwenden kann (zB. mit selbstgebautem makefile), falls man das nicht von einer Entwicklungsumgebung machen lässt.
Compiler & Linker Flags
Die Flags, die festlegen, welcher Core verwendet wird, sind in der folgenden Tabelle beschrieben:
Option | Cortex-M0 | Cortex-M0+ | Cortex-M3 | Cortex-M4 | Cortex-M7 | Cortex-M33 | Cortex-M23 |
---|---|---|---|---|---|---|---|
CPU | -mcpu=cortex-m0[1] | -mcpu=cortex-m0plus[1] | -mcpu=cortex-m3 | -mcpu=cortex-m4 | -mcpu=cortex-m7 | -mcpu=cortex-m33 | -mcpu=cortex-m23 |
Float ABI | -mfloat-abi=soft | -mfloat-abi=soft
-mfloat-abi=softfp -mfloat-abi=hard |
-mfloat-abi=soft | ||||
FPU | -mfpu=fpv4-sp-d16 | -mfpu=fpv5-d16 | -mfpu=fpv5-sp-d16 / -mfpu=fpv5-d16 | ||||
Instruction Set | -mthumb |
[1]Anmerkung: Es gibt für diese Cores 2 Optionen (für den Hersteller): diese Betreffen die Multiplikationsbefehle.
- Die übliche Implementierung enthält einen 1-Takt-Multiplizierer
- Für reduzierte Chipfläche kann auche ein 32-Takt-Multiplizierer ausgewählt werden
Um nun bei Multiplikationen mit Konstanten nicht die langsame 32-Takt-Multiplikation zu nutzen kann der Compiler angewiesen werden, dort Shifts oder Ähnliches zu generieren. Um dem Compiler das mitzuteilen wird der Parameter, der die CPU angibt, abgeändert: -mcpu=cortex-m0[plus].small-multiply
Zusätzlich zu diesen Flags gibt es noch die Maschinenunabhängigen Parameter, wovon hier nur einige wichtigen erläutert werden:
Option | Erklärung |
---|---|
-W[all, extra] | Lässt den Compiler Warnungen ausgeben.
-Wall gibt nur Standard-Warnungen aus, nicht alle! -Wextra erzeugt noch einmal mehr Warnungen. |
-O[0,1,2,3,s,g] | Wählt die Art der Optimierung.
-O0: keine Optimierung -O[1,2,3]: Optimierung auf Ausführungsgeschwindigkeit. Je höher die Stufe, desto aggressiver ist die Optimierung. Das führt unter Umständen zu beträchtlich größerem Code -Os: Optimierung auf Codegröße -Og: Optimierung, aber so, dass das Debugging nicht erschwert wird |
-fdata-sections
-ffunction-sections |
Teilt jeder Funktion/jeder Variable eine eigene Section zu.Damit kann der Linker mit der Option --gc-sections ungenutzte Funktionen entfernen. Siehe GCC:_unbenutzte_Funktionen_entfernen |
-Wl,--gc-sections | Der Linker verwirft unreferenzierte Sections und packt diese damit nicht ins Binary. Siehe GCC:_unbenutzte_Funktionen_entfernen |
-g | Erzeugt Debugging-Informationen.
Siehe auch GCC Debugging Options |
-fno-rtti
-fno-exceptions |
C++-Optionen
Teilt dem Compiler mit, dass - keine Runtime Type Information zu generieren sind - keine Exceptions benutzt werden und damit kein Overhead generiert werden muss. |
-flto | Link-Time-Optimizations:
Der Linker optimiert den kompletten Code. Da er nicht nur ein Source-File, sondern alle kennt, kann er optimieren, wo dem Compiler Informationen fehlen. Achtung: bei älteren Compiler-Versionen muss nach diesem Flag noch einmal die Optimierungsstufe angegeben werden. |
Die GCC Dokumentation listet alle Parameter auf, auch Parameter speziell für ARM.
- Siehe auch das Readme vom GCC-ARM-Embedded
- Um das -flto -Flag verwenden zu können, muss der GCC LTO unterstützen. Beim GCC-ARM-Embedded ist dies ab Version 4.7-2013-q2-update der Fall.
- Die LTO erkennt die ISR's und den Interrupt Vector möglicherweise als "unbenutzt" und optimiert sie daher weg. Dies kann durch Markierung der Funktionen & Variablen mit "__attribute__ ((used))" verhindert werden.
- Alle Compileroptionen müssen auch beim Linken mit angegeben werden (ist in obiger Tabelle berücksichtigt), da auch dann u.U. Code generiert werden kann.
Startupcode & Linkerscript
- Damit der compilierte Code an den richtigen Stellen im Controller landet (d.h. dem Flash) muss man dem Linker ein Linkerscript mitgeben. Dies geht per "-T pfad_zum_linkerscript.ld" an den Linker-Befehl. Das Script ist praktisch Controller-spezifisch, es gibt Beispiel-Scripte der Controller-Hersteller.
- Damit beim Starten die richtigen Initialisierungen vorgenommen werden (wie globale Variablen und bei C++ Konstruktoren globaler Objekt-Instanzen) muss als erstes ein Startupcode laufen, der dann die main()-Funktion aufruft. Startupcode im allgemeinen ist meistens in Assembler geschrieben, aber die ARM-Architektur macht aber auch einfacheren C/C++-Code möglich. Auch für den Startupcode gibt es Beispiele der Controller-Hersteller.
Zusammen bieten die beiden Dateien der Anwendung ein Standard-C-Interface, d.h. man kann wie gewohnt globale Variablen verwenden und seinen Code in die main()-Funktion schreiben.
FPU der Cortex-M4F nutzen
Um die FPU zu nutzen, muss der Compiler per Flag dazu gebracht werden, FPU-Instruktionen zu generieren.
Außerdem muss vor Benutzung der FPU-Befehle die FPU aktiviert werden, dies geschieht typischerweise im Startupcode, bevor die main() -Funktion aufgerufen wird. Hier die entsprechenden Befehle, falls sie im verwendeten Startupcode nicht onehin schon enthalten sind:
/*FPU settings*/
ldr r0, =0xE000ED88 /* Enable CP10,CP11 */
ldr r1,[r0]
orr r1,r1,#(0xF << 20)
str r1,[r0]
In C/C++ unter Verwendung der CMSIS geht es so:
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
Weiterhin sollte die GCC-Distribution auch Laufzeitbibliotheken mit FPU-Unterstützung mitbringen (CodeBench lite und Yagarto werden ohne ausgeliefert, GCC-ARM-Embedded mit).
Am Beispiel der STM32F4 mehr dazu in diesem Thread: Floating Pointing Unit STM32F4