Moin,
in meinen WinARM Makefiles gibt es die Einträge SCRARM +=
für Dateien die im "ARM-Mode" kompeliert werden sollen.
Leider habe ich bis jetzt noch keine Erklärung gefunden,
was sich hinter diesem Modus verbirgt, und wann man eine
Datei damit kompelieren muss.
Kann jemand Licht in die Dunkelheit bringen?
Vielen Dank,
Arne
Die ARM Architekturen ARMv4t, ARMv5 (also alle ARM7, ARM9, ..., aber
nicht Cortex-M3) definieren den normalen ARM-mode, und zusätzlich einen
sogenannten Thumb-mode, der mit 16-bit Instruktionen auskommt. Dadurch
lassen sich in einen gleich grossen Programmspeicher (z.B. on-chip
Flash) groessere Programme unterbringen.
Ausserdem ist nur die halbe Speicherbandbreite erforderlich, was bei uCs
mit einer schlechteren Flash Anbindung wie dem AT91SAM7 Performance
Vorteile bietet. Der Nachteil ist, dass etwas mehr Instruktionen für die
selbe Aufgabe nötig sind, da in einen 16-bit Befehlssatz einfach nicht
so viele Befehle untergebracht werden koennen.
Gruss,
Dominic
Nur als Ergänzung:
Die Unterscheidung "SRCARM" und "SRC" in den Makefiles meiner
WinARM-Beispiele dient dazu, dass man in einem Projekt beide
Befehlssätze nutzen kann. Schlussendlich läuft es bei den Makefiles
darauf hinaus festzulegen, welche Sourcen mit -mthumb kompiliert werden
und welche nicht. In den Makefiles habe ich auch oft Schalter um
Thumb-Mode ein- und auszuschalten. Wenn Thumb-Mode aus, werden alle
Source (in SRC und SRCARM) im ARM-Mode compiliert. Wenn Thumb-Mode an,
werden die Sourcen in SRC mit -mthumb kompiliert, die in SRCARM ohne
diese Option. Vgl. auch gcc-Dokumentation zu -mthumb und
-mthumb-interwork. Bei vielen ARM-cores (z.B. ARM7TDMI) muss der Code,
der direkt über die Exceptions-Vektoren angesprungen wird, im ARM-Mode
implementiert sein, -mthumb ist dann tabu auch wenn es Platz spart oder
wegen langsamer Anbindung des Flashspeichers von Vorteil wäre. Ist gibt
noch diverse Möglichkeiten (ARM-Code aus RAM ausführen oder kleiner
Assembler-Wrapper im ARM-Mode für Exceptions u.a.) aber hat wohl nicht
mehr wirklich was mit der Frage zu tun.
Martin Thomas
Noch ein bischen Zusatzinfo.
Der ARM mode codiert alle Befehle 32-bit breit, der Thumb mode codiert
alles 16-bit breit.
Vorteil Thumb mode sehr gut beschrieben von Dominic.
Natuerlich hat er auch recht mit Vorteilen fuer nicht so tolle
Speicheranbindung im Thumb mode.
Vorteile ARM mode. Es gibt zusaetzliche Befehle im ARM mode und somit
kann der micro schneller laufen, falls die SPeicheranbindung dafuer
optimiert ist.
Ein Beispiel:
Es benoetigt im Durchschnitt ca. 7 ARM Befehle um dieselbe Funktion
auszufuehren wie 10 Thumb Befehle. Das ergibt einen Code Unterschied von
7x32-bit genenueber 10x16-bit also 224 bit / 160 bit. Damit kann mehr
Funktion in denselben Speicher gepackt werden. Der ARM7 fuehrt im
Durchschnitt alle 1.9 Taktzyklen einen Befehl aus und es ist nut wenig
Unterschied zwischen der Ausfuehrung eines ARM Befehls und eine Thumb
Befehls. Also braucht ein ARM7 ohne Flaschenhals in der
Speicheranbindung ca. 13.3 Zyklen um die 7 ARM Befehle auszufuehren aber
ungefaher 19 Zyklen fuer dieselbe Funktion im Thumb mode.
Was ist jetzt eine optimierte Speicheranbindung and wann macht das einen
Unterschied? Wenn DU den ARM unter 20 MHz betreiben moechtest, dann
braucht keiner der Flash ARMs eine Bremse. Zwischen 20 und 30 MHz hat
der SAM7 den besten Bereich, denn er kann noch ohne WS im ARM mode
arbeiten, waehrend z.B. der LPC2000 durch das dazwischen geschobene
Interface ca. 5% an Leistung verliert. Oberhalb von 30 MHz ist
allerdings der LPC2000 viel schneller im ARM mode, weil das optimierte
Speicherinterface nahezu 0 WS bis (je nach Typ) 72 MHz zulaesst.
Als allgemeine Regel koennte man sagen, wenn auf maximale Lesitung
optimiert werden soll, dann kannst Du einen LPC nehmen und im ARM mode
laufen oder die Programmteile im SAM7 ins SRAM kopieren. Was immer aus
dem FLash abgearbeitet wird, sollte beim Atmel (oder auch STR7, Analog
Devices, TMS470, OKI...) bei Frequenzen oberhalb 30 MHz immer im Thumb
mode sein. Die Geschwindigkeit ist begrenzt durch die Speicherbreite,
32-bit oder gar nur 16-bit.
Anders beim LPC, der hat einen 128-bit breiten Flash-Bus und man braucht
nichts ins SRAM kopieren fuer maximalen Durschsatz, sondern man kann
immer aus dem Flash im ARM mode abarbeiten.
Alle Klarheiten beseitigt?
Ach ja, noch ne Kleinigkeit. Wenn ein Interrupt auftritt, dann schaelt
der ARM7 automatisch in den ARM mode, kann man nichts machen. Das ist
somit sehr flott wenn die Interrupt Service Routine im SRAM steht aber
bremst wenn im Flash (ausser LPC).
Na denn viel Spass im ARM und Thumb mode, Robert
@robert
>Anders beim LPC, der hat einen 128-bit breiten Flash-Bus und man braucht>nichts ins SRAM kopieren fuer maximalen Durschsatz, sondern man kann>immer aus dem Flash im ARM mode abarbeiten.
wenn du auch o.a. aussage öfters wiederholst gewinnt sie auch nicht mehr
an wahrheit.
fakt ist, das der von dir erwähnte vorteil nur besteht, wenn es sich um
linearen code handelt, sobald sprünge oder call's enthalte nsind muss
auch der lpc aus dem flash neu fetchen und dabei entsprechende
waitstates einlegen.
gruss
gerhard
Der Vorteil bleibt - sicher kann auch der LPC bei typischem Code nicht
mit 0 Waitstates arbeiten, aber auf jeden Fall deutlich schneller als
ein uC, der nur über ein 32-bit breites Interface und keine Prefetch
Hardware verfügt.
Eventuell könnte man Robert vorwerfen, dass er nur von "nahezu 0 WS"
spricht, ohne deutlich auf die Sprungproblematik hinzuweisen, unwahr ist
seine Behauptung meines Erachtens nach aber nicht.
Gruss,
Dominic
Nun, noch "2 Cents" und noch weiter abseits vom eigentlichen Thema: Mir
sind beide Familien LPC2xxx und AT91SAM7 eigentlich schnell genug für
meine Anwendungen (die bisher auch keine arg großen Anforderungen
stellen, viel Spielerei, noch relativ wenig Ertrag). Eigentliche
Entscheidung, welchen Controller "besser" ist, hängt für mich mehr von
den Funktionen der verfügbaren internen Peripherie (z.B. denen der
UARTs) und von der verfügbaren Dokumentation und Beispielcode für
komplexere Funktionen ab (z.B. USB). "Besser" steht also eher für
passender oder besser geeignet. Wirklichen Kontakt mit dem LPC236x hatte
ich noch nicht (10 Minuten "bespielt", aber der Vorsprung der AT91SAM7,
zumindest was DMA betrifft, wurde laut Datenblattinformation wohl
verringert. Digi-key zeigt auch einen interessanten Preis. Schade, dass
die 100+-Pinner noch unhandlicher geworden sind, aber einem Großabnehmer
wird's wohl egal sein ob 100 oder noch mehr Pins im Mini-Package. Ein
"wenig-Pin" 236x wäre was für die "Wunschliste" unter dem Punkt ARM in
PLCC-Gehäusen (oder habe ich deren vor langem angekündigte Verfügbarkeit
bisher übersehen?).
Aber zumindest wieder halbwegs zum Thema: Interessant wäre ein möglichst
realitätsnaher Benchmark (also keine simplen Mini-Routinen) zur Messung
der Verarbeitungszeiten von
- stark verschachteltem Code bei Ausführung aus dem Flash bei
verschiedenen Familien. o.k., ich weiss auch nicht, wie so ein Code
genau aussehen sollte, v.a. wenn der Compiler ordentlich optimiert. Aber
das sollte sich anhand der Assembler-Listings herausfinden lassen.
- dito wenn Code im RAM
- Zeit zur Verarbeitung von Interrupts (INT, FIQ und SWI), wenn die
Interrupt-Routine im Flash abgelegt ist und direkt durch die Adresse vom
Interrupt-Controller (LPC: VIC, AT91AIC) angesprungen wird, also im
ARM-mode vorliegt ("typisches" Setup bei Beispielen nach dem
Keil-"Schema" bei LPC)
- Dito aber Interrupt-Routine im RAM (weiterhin ARM-Mode)
- Dito wenn die Interrupt-Routine eine "Wrapper-Funktion" im ARM-Mode
ist und auf die eigentlichen Verarbeitungsanweisungen verzweigt ("BXt"),
die im Thumb-Mode und im Flash vorliegen ("typisches" Setup bei
AT91-Beispielen von Atmel)
Das Ganze dann noch in Relation zur benötigten Codegröße. "Code im RAM"
nimmt ja doppelt Platz (bei "LMA" und bei "VMA") und verbraucht u.U. für
die Anwendung dringend benötigten RAM-Speicher. Interrupt-Routine selbst
sollte nicht allzu "simpel" sein und auch etwas im Speicher
herumspringen (Gerhards Einwand). Core-Frequenzen sollten gleich sein
(sagen wir 48MHz). Ausser Interrupt-Controller keine intere Peripherie
nutzen, die das Messergebnis in Bezug auf Ausführungsgeschwindigkeit in
verschiedenen Speichern und Modi verfälscht. Es bleibt dann zwar immer
noch ein relativ syntetischer Benchmark aber wäre eine interessante und
hoffentlich informative "Spielerei". Vielleicht kennt ja jemand schon
eine brauchbare Code-Basis für den Anfang (was nutzt NXP zum Vergleich
mit den Mitbewerbern?). Würde etwas mithelfen, solchen Code an LPC214x
oder AT91SAM7S256 anzupassen (GNU-Toolchain). Finetuning durch Robert
Teufel in der NXP-Ecke und Gerhard in der Atmel-Ecke des "Rings".
Entscheidung dann als Webcast ;-).
Martin Thomas