Hi,
ich habe (mal wieder :) ) ein Tutorial geschrieben und würde mich über
Feedback hier im Thread freuen. Diesmal auf Englisch, vielleicht hilft
es so mehr Leuten.
Es geht um das Programmieren von ARM-Cortex-M in Assembler. Auch wenn
Hochsprachen wie C und C++ dort gut verfügbar sind, sind
Assembler-Kenntnisse zum Debuggen und Low-Level-Code sinnvoll.
Zum Text: ARM-ASM-Tutorial
Beispiel-Code: https://github.com/Erlkoenig90/ArmAsmTutorial
Fragen und Anregungen können hier abgegeben werden :)
@erlkoenig
... Tutorials sind immer willkommen - auch für Assembler, aber warum nur
in Englisch?
Sind wir schon soweit, dass wir das Deutsche verleugnen müssen?
Eine deutsche Version wäre mir (und vielleicht auch vielen Anderen) viel
angenehmer.
Grüsse aus Berlin
PSblnkd
PSblnkd schrieb:> aber warum nur> in Englisch?
Damit mehr Menschen in aller Welt das lesen können.
PSblnkd schrieb:> Eine deutsche Version wäre mir (und vielleicht auch vielen Anderen) viel> angenehmer.
Vielen anderen Menschen, welche kein Deutsch können, wäre eine englische
Version lieber.
PSblnkd schrieb:> @erlkoenig> ... Tutorials sind immer willkommen - auch für Assembler, aber warum nur> in Englisch?
Damit es so gut wie jeden erreicht.
Jemand aus dem Bereich Technik/Informatik, der des Englischen zumindest
lesend nicht mächtig ist, hat den Schuss nicht gehört.
>> Sind wir schon soweit, dass wir das Deutsche verleugnen müssen?
Tut er doch gar nicht. Er nimmt einfacht die internationale lingua
franca für Technik (s.o.).
>> Eine deutsche Version wäre mir (und vielleicht auch vielen Anderen) viel> angenehmer.
Mimimi, lern endlich Englisch, damit Du die Handbücher zu ARM auch lesen
kannst.
Niklas G. schrieb:> ch habe (mal wieder :) ) ein Tutorial geschrieben
Wow. Danke.
Wenn es um Reichweite geht, würde vielleicht der Einstieg über
Inline-Assembler oder Assembler-Funktionen noch breiteres Interesse
finden als Projekte komplett in Assembler von Null aufzubauen.
Walter T. schrieb:> Wenn es um Reichweite geht, würde vielleicht der Einstieg über> Inline-Assembler
Inline-Assembler ist recht komplex mit diversen Fallstricken. Damit
sollte man sich lieber erst befassen nachdem man die Assembler-Sprache
an sich beherrscht...
Walter T. schrieb:> Assembler-Funktionen
Wie man Assembler-Funktionen aus C aufruft ist ja auch gezeigt. Die
Kapitel über Startup-Code und Linker könnte man zwar überspringen wenn
man Assembler-Funktionen in C-Projekte einbinden will, aber Kenntnis
dieser Themen ist allgemein hilfreich wenn man mit Assembler arbeitet. C
kann einem ziemlich dazwischen funken, weshalb es nicht ganz verkehrt
ist erstmal nur Assembler und Linker zu nutzen...
schöne Anleitung die Du da geschrieben hast, kommt für mich leider etwa
ein Jahr zu spät....hab es mir aufwändig selbst beigebracht.
Deshalb hier noch einen Verbesserungsvorschlag:
Wenn die Register noch eigene Namen erhalten liest sich der Code fast
wie von selbst...
//Arbeits-Register benennen
BASE .req r0
OFFSET .req r1
COUNTER .req r2
POINTER .req r3
VALUE .req r4
TEMP .req r5
MASK .req r6
DELAY .req r7
//Funktions-Register benennen
.equ RCC_AHB1ENR, 0x40023830
//Bitnamen für die Funktionsregister benennen
.equ GPIOAEN, 0
.equ GPIOGEN, 6
//TAKT für die Ports G und A einschalten
LDR POINTER, = RCC_AHB1ENR //lade die Adresse in den Pointer
LDR VALUE,[POINTER] //lade den Wert aus der aus der Adresse
LDR VALUE, = #((1<<GPIOGEN)|(1<<GPIOAEN)) //schreibe neuen Wert
STR VALUE,[POINTER] //schreibe den Wert zurück in die Adresse
Roland F. schrieb:> https://azeria-labs.com/writing-arm-assembly-part-1/
Dieses Tutorial ist zwar gut gemacht, aber nicht sehr ausführlich und
vernachlässigt die Toolchain (Linker, Linkerscripte...). Es zeigt auch
nicht wie man konkret ein Mikrocontroller-Programm umsetzt.
Roland F. schrieb:> Youtube-Video "Assembly Language Tutorial"
Kann in 38 Minuten wohl kaum die gleiche Menge an Inhalt wie mein
Tutorial vermitteln.
Roland F. schrieb:> Youtube-Video "ARM Assembly Language Tutorial - Part 1 - Setup ARM> Tools"
In 11 Minuten auch nicht.
Roland F. schrieb:> http://infocenter.arm.com/help/topic/com.arm.doc.dui0068b/DUI0068.pdf
Ist keine Schritt-Für-Schritt-Anleitung welche den Leser an konkrete
Projekte heranführt. Funktioniert außerdem so nur mit den
proprietären/teuren Tools von ARM selbst. Natürlich ist die ARM-Doku an
sich aber sehr gut.
Roland F. schrieb:> http://www.peter-cockerell.net/aalp/html/frames.html
Dito. Ist von 1987 und daher kaum relevant für Cortex-M MCUs.
Gerd schrieb:> Bin trotzdem der Meinung dass Asm bei den 8Bittern viel besser> aufgehoben ist.
Wie schon erwähnt sind Assembler-Kenntnisse für bestimmte Situationen
erforderlich. Ganze Anwendungen wird man da nicht drin schreiben.
Bernd schrieb:> Wenn die Register noch eigene Namen erhalten liest sich der Code fast> wie von selbst...
Genau das passiert auch im Tutorial. Der .req Befehl wird gezeigt, aber
ich halte es für nicht sehr flexibel, den Prozessor-Registern derart
fixe Bedeutungen zuzuordnen.
Ist ganz interessant, aber hat mir gerade wieder gezeigt, dass mir ASM
auf ARM mit dem Thumb(2) Befehlssatz keine Freude bereiten wird :)
In 68k Assembler konnte man tatsächlich sehr guten Code schreiben, der
oft effizienter als C und dennoch übersichtlich war. Bei Thumb2 muss man
viele triviale Sachen "zu Fuß" machen, das kostet Zeit und
Übersichtlichkeit.
Aber zum Verstehen von übersetztem Code ist es natürlich schön das
zumindest mal gesehen zu haben.
Meinen Artikel zu QO-100 habe ich zuerst in deutsch verfasst und jetzt
noch im englischen Forum https://embdev.net/articles gepostet. Das macht
zwar etwas mehr Arbeit, aber dank automatischer Rohübersetzung ging das
recht schnell. Die Stilblüten muss ich noch im Laufe der Zeit ausmerzen,
ich hoffe, das mir kompetentere Mitleser dabei helfen.
Am ARM Assembler interessieren mich vor allem die DSP-Möglichkeiten. Es
gibt anscheinend einige ARM-Typen, die z.B. MAC-Befehle und begrenzende
mathematische Operationen beherrschen, also bei Überschreiten der 16-
oder 32-Bit Grenze nicht ins negative rutschen.
Markus M. schrieb:> Ist ganz interessant, aber hat mir gerade wieder gezeigt, dass mir ASM> auf ARM mit dem Thumb(2) Befehlssatz keine Freude bereiten wird :)
Ja, die Architektur ist darauf optimiert Hochsprachen-Code effizient
ausführen zu können, nicht darauf, schönen Assembler-Code zu haben. Es
sind einige clevere Tricks nötig, welche in Assembler nicht sehr schön
sind, aber vom Compiler gut beherrscht werden können.
Christoph db1uq K. schrieb:> Meinen Artikel zu QO-100 habe ich zuerst in deutsch verfasst und jetzt> noch im englischen Forum https://embdev.net/articles gepostet.
Na, wenn es einmal schon auf Englisch vorliegt, ist es schon ziemlich
universell. Wenn jemand Interesse hat das ins Deutsche zu übersetzen...
Christoph db1uq K. schrieb:> Es> gibt anscheinend einige ARM-Typen, die z.B. MAC-Befehle und begrenzende> mathematische Operationen beherrschen
Ja, die Cortex-M4F haben das. Das sind die "saturating" Operationen.
Bevor man sich damit auseinandersetzt sollte man aber erstmal die Basics
kennen :)
Laut Wikipedia wären das:
Atmel: SAM4-Familie (Cortex-M4)
Freescale: Kinetis-Familie (Cortex-M4 und Cortex-M4F)
STMicroelectronics: STM32-F3/F4-Familie (Cortex-M4F)
Infineon: XMC4000-Familie (Cortex-M4F)
Texas Instruments: MSP432, Stellaris-LM4F- und Tiva-TM4C-Familie
(Cortex-M4F)
NXP Semiconductors: LPC4300-Familie (Cortex-M4)
Wie liegen die preislich, rentiert es sich, die speziell als low-cost
DSP zu benutzen?
Christoph db1uq K. schrieb:> Wie liegen die preislich, rentiert es sich, die speziell als low-cost> DSP zu benutzen?
Die meisten gibt es so im Bereich 3-10€. Das ziemlich beliebte
STM32F407G Discovery Board mit Cortex-M4 inklusive Debug-Adapter gibt's
für ca 15€.
Die 15€ scheinen vom Billighuber zu sein, Reichelt will 25 und Digikey
18+Steuer. Der billigste M4F von ST, STM32G441KBT6 bei Reichelt kostet
4,30€ im LQFP32.
Ich habe mein altes DSP-Projekt schon mehrfach erwähnt, ein IIR-Hilpert
als Breitband 90 Grad Phasenschieber zur SSB-Erzeugung. Passt mit Mühe
noch in einen Arduino, aber 2 Bit mehr ADC und viel mehr Power in
derselben Preislage wäre interessant. Das sind 8 IIR-Allpassfilter mit
jeweils nur einer Multiplikation und ein paar Additionen.
Christoph db1uq K. schrieb:> Die 15€ scheinen vom Billighuber zu sein, Reichelt will 25 und Digikey> 18+Steuer.
Das war mal billiger, scheint wohl etwas vergriffen zu sein. Das
NUCLEO-F446RE hat sogar noch etwas mehr Leistung, kostet aber weniger.
Christoph db1uq K. schrieb:> Der billigste M4F von ST, STM32G441KBT6 bei Reichelt kostet> 4,30€ im LQFP32.
Reichelt ist für sowas auch keine Referenz ;-)
Niklas G. schrieb:> ...
Ich wollte es nicht nochmal alles zitieren, aber ich sehe es zu 97% wie
du.
Ergänzend :
Gerade bei dem Drumherum (binutils, Linker, Debugger, ASM) fehlt es
meistens den Studenten die kommen. Ich habe den Eindruck das ist als
Basics Einführung für Neueinsteiger genau richtig. Das braucht man nicht
oft, aber es hilft wenn man eine Vorstellung von dem hat wie sich das
ganze drum herum aufbaut und welche Möglichkeiten sich da evtl. bei
bestimmten Problemstellungen ergeben.
An vielen Hochschulen ist es leider so, dass es ein vorgefertigtes
Project Template gibt wo man nur noch hier und dorthin klickt ohne zu
wissen was im Hintergrund passiert. Wir hatten hier schon Bewerber
Embedded Abschlussarbeit die auf die Frage nach dem verwendeten Compiler
Eclipse gesagt haben :(. Was ein elf/hex/bin File oder Assembler ist
haben die auch nicht gewusst.
Wünschen würde ich mir auch einen Blick auf inline ASM ... vielleicht
sollte ich mal selbst den Hintern hochbekommen.
Aber ich bin da auch immer wieder halb raus, nur für Assembler Code in
meinem Team (10 Personen) zuständig macht ca. 1-4 Tage im Jahr Assembler
schreiben und das auch noch auf unterschiedlichen Architekturen. Lesen
deutlich häufiger, Debuggen von optimierten Code -O2/-O3/-Os ist ja
manchmal etwas schwierig ohne Blick ins Disassembly, aber das kann ich
zeitlich schlecht beziffern.
*Was mir sehr gut gefallen hat:*
.section .VectorTable, "a" + nachfolgende Beschreibung.
Vielleicht ergänzend:
Wenn man die Section hart auf eine Adresse setzt klappt es ohne
allocable (übrigens ist da ein Tippfehler), wenn man die Section nur
einem "MEMORY" zuweist fliegt es raus.
-> das schöne "a" fehlt leider schon mal im Code von ARM :(
Zum Schluss Daumen hoch
Mistel schrieb:> Ich wollte es nicht nochmal alles zitieren, aber ich sehe es zu 97% wie> du.
Danke :)
Mistel schrieb:> Wir hatten hier schon Bewerber> Embedded Abschlussarbeit die auf die Frage nach dem verwendeten Compiler> Eclipse gesagt haben :(. Was ein elf/hex/bin File oder Assembler ist> haben die auch nicht gewusst.
Oje... Ja genau darum ging es.
Mistel schrieb:> Lesen> deutlich häufiger, Debuggen von optimierten Code -O2/-O3/-Os ist ja> manchmal etwas schwierig ohne Blick ins Disassembly, aber das kann ich> zeitlich schlecht beziffern.
Ja, es kommt bei mir auch deutlich häufiger vor dass Disassembly-Code
gelesen wird. IMO lernt man Sprachen aber am Besten via
Learning-By-Doing, daher kann man auch selber ein Paar Dinge in
Assembler programmieren um es zu lernen, auch wenn man später nur noch
Code liest.
Mistel schrieb:> Wenn man die Section hart auf eine Adresse setzt
Wie meinst du das denn genau? Das Problem taucht nur auf wenn man der
Section im Linkerscript eine eigene Output-Section zuweist, weil sonst
das "Alloc"-Bit von anderen Input Sections kommt.
Mistel schrieb:> übrigens ist da ein Tippfehler
Ups :)
Mistel schrieb:> -> das schöne "a" fehlt leider schon mal im Code von ARM :(
Ja, ST hat ja teilweise auch Fehler in Linkerscripten - das ganze Thema
ist wohl doch noch nicht so weit bekannt...
Christoph db1uq K. schrieb:> Der Nucleo446 sieht gut aus, bei Conrad derzeit sogar etwas billiger> (17,99€ im Laden) als Reichelt. Jedenfalls bei Händlern weit verbreitet.
Jo, wobei ich sagen würde dass es für Hobby nicht auf den letzten Euro
ankommt. Das Tutorial ist für den STM32F4 aber nur bedingt anwendbar,
die GPIO- und RCC-Peripherie ist anders (u.a.).
Christoph db1uq K. schrieb:> jeweils über 200 Seiten, das werde ich nicht ausdrucken.
Die Tabelle mit den Condition Codes liegt immer ausgedruckt neben dem PC
;-)
Viel Spaß beim Lesen!
Niklas G. schrieb:> ich habe (mal wieder :) ) ein Tutorial geschrieben und würde mich über> Feedback hier im Thread freuen.
Wow, das ist ja richtig ausführlich, und sogar inklusive Toolchain!
Gerade wo GCC manchmal etwas hakelig einzurichten ist, ist das
hilfreich.
> Fragen und Anregungen können hier abgegeben werden :)
Nur ein paar Typos hätte ich im Angebot:
2.1 Mikrocontroller -> microcontroller
Debug adapter: JTAG oder SWD -> JTAG or SWD
Writing GPIO pins: dafult -> default
Address space: addresses where used -> addresses were used
objcopy: createed -> created
Interfacing C and C++ code: neccessary -> necessary
Danke :)
Nop schrieb:> Nur ein paar Typos hätte ich im Angebot:
Ups, sind behoben!
Nop schrieb:> Gerade wo GCC manchmal etwas hakelig einzurichten ist, ist das> hilfreich.
Ja genau, da sind bestimmt schon ein paar Anfänger dran gescheitert.
Jatzt kann ich das auch in der Bahn lesen, was mir schon aufgefallen
ist, der Cortex-M kann nur den T32 Thumb, nicht A32. Ich dachte das sind
nur 16Bit-Instruktionen. Aber die DSP-Befehle (Multiply-accumulate) sind
für 32 Bit.
Christoph db1uq K. schrieb:> Ich dachte das sind> nur 16Bit-Instruktionen. Aber die DSP-Befehle (Multiply-accumulate) sind> für 32 Bit.
Eine Sache, die ARM nicht kann, Dinge sinnvoll benennen :-)
T32 ist der Thumb-Instruction Set, welcher sich genau wie A32 auf eine
32bit-CPU mit 32bit-Registern und 32bit-Adressraum bezieht.
Die meisten der T32-Befehle selbst sind 16bit groß, aber manche sind
32bit. Als Programmierer merkt man von der Größe des Befehls selbst
nicht so viel, die erkennt man im disassemblierten Code.
Christoph db1uq K. schrieb:> Aber die DSP-Befehle (Multiply-accumulate) sind> für 32 Bit.
Kommt drauf an welcher genau gemeint ist. Der "MLA" Befehl (Eine 32bit
Multiplikation + Addition) ist auf ARMv7-M verfügbar, also
Cortex-M3/4/7.
Der "SMLAD" Befehl (Zwei 16bit-Multiplikationen und Addition auf ein
32bit-Register/Integer) ist Teil der DSP-Extension, und die gibt's nur
auf ARMv7E-M, d.h. Cortex-M4/7.
Dann gibt's noch VMLA für Floating-Point, was nur auf ARMv7M + FPU
verfügbar ist, also Cortex-M4/7 - mit 32bit "float", bei manchen M7 auch
mit 64bit "double".
Alles etwas unübersichtlich, die Details entnimmt man dem ARMv7M
Architecture Reference Manual. Damit hab ich mich auch noch nicht so
genau auseinander gesetzt.
Auf A32 (ARMv7-A, Cortex-A), ggf. mit NEON-Extension, ist das alles
nochmal anders...
> auf die Frage nach dem verwendeten Compiler Eclipse gesagt haben
wir haben auch Kunden (Programmierer!) die beim Support anrufen und
fragen zu was man einen Stack braucht ...
Christoph db1uq K. schrieb:> der Cortex-M kann nur den T32 Thumb, nicht A32. Ich dachte das sind> nur 16Bit-Instruktionen. Aber die DSP-Befehle (Multiply-accumulate) sind> für 32 Bit.
In Thumb1 konnte man nur die ersten 7 Register direkt adressieren und
alle Befehle waren 16Bit.
Bei Thumb2 gibts, wie richtig erkannt, auch 32Bit Befehle.
Die sind sogar unaligned über eine 4 Byte Grenze hinweg anzutreffen.
Ein load/store multiple zB ist auch ein 32Bit THumb2 Befehl, der sogar
1zu1 wie das ARM32 pendant aufgebaut ist.
@Niklas G:
Wirklich ein sehr gutes Tutorial!
Jetzt könnt man noch die MPU in Betrieb nehmen falls man mal ausversehen
auf NULL zugreift ;)
Exceptions kommen zwar als Überschrift vor, aber ich sehe keinen
HardFault Handler?
Mw E. schrieb:> Die sind sogar unaligned über eine 4 Byte Grenze hinweg anzutreffen.
Aber immer mindestens 2-Byte-Aligned.
Mw E. schrieb:> In Thumb1 konnte man nur die ersten 7 Register direkt adressieren und> alle Befehle waren 16Bit.
"mov" kann immer alle Register adressieren, zählt das als "indirekt"?
"bl" war immer 32bit, aber auf Thumb1 ein Sonderfall und eine Art
Kombination aus "add" und "b".
Mw E. schrieb:> Wirklich ein sehr gutes Tutorial!
Danke ;-)
Mw E. schrieb:> Jetzt könnt man noch die MPU in Betrieb nehmen falls man mal ausversehen> auf NULL zugreift ;)
Die Adresse "0" ist aber gültig und ein Alias für das 0. Byte im
Flash/SRAM (abhängig von den BOOT-Pins und/oder dem Remap-Register). Es
gibt noch jede Menge Dinge die man vom Cortex-M erläutern könnte. Das
würde aber IMO etwas zu weit führen für so ein Tutorial - wenn man
erstmal die Grundlagen hat, kann man sich da auch selbst einarbeiten.
Mw E. schrieb:> Exceptions kommen zwar als Überschrift vor, aber ich sehe keinen> HardFault Handler?
Den könnte man noch einbringen, ja. Auf ARM ist "Exception" der
Oberbegriff für (durch Peripherie ausgelöste) Interrupts und
Unterbrechungen durch den Core selbst, wie eben HardFault. Daher ist die
Überschrift "Exception" nicht falsch, nur weil die Fehler-Exceptions
nicht behandelt werden :)
Ich habe mal das Tutorial mit Google Translate übersetzen lassen. Es
funktioniert großenteils ordentlich, da könnte man was draus machen.
Ein paar Erkenntnisse, falls es jemand auch brauchen kann:
Per copy&paste kann man maximal 5000 Zeichen eingeben, mit ca. 200k Text
wären das etwa 42 Einzeldateien geworden. Als Textdatei hochgeladen
werden die ersten ca. 32k übersetzt, der Rest ist daran noch im Original
angehängt. Mit 6-7 Teilen war der Aufwand erträglich.
Störend sind vor allem zusätzlich vom Übersetzer eingefügte Leerzeichen,
die die Wiki-Anweisungen verhackstücken, z.B. in "</ source", aber das
ist mit Suchen%Ersetzen schnell erledigt.
Und die Quelltextstücke werden leider auch übersetzt. Aus "kill-exit"
wird "Töten - Verlassen". Da ist ein Rückgriff auf das Original nötig,
also Handarbeit angesagt. Auch Tabellen werden durch Leerzeichen
beschädigt.
Dass "Assembly" auch mal zur "Montage" wird, oder die
"Uhrenkonfiguration" und ähnliche Stilblüten, da hilft auch nur
manuelles Nacharbeiten.
Zum Ausprobieren gibt es hier unter "Artikel" die "Testseite", da kann
man auch die Vorschau benutzen, ohne es dauerhaft zu speichern.
https://www.mikrocontroller.net/articles/Testseite
Einfach neben einer Überschrift "bearbeiten" klicken und da den Text
reinkopieren, dann unten auf "Vorschau".
Ich hänge das vorläufige Ergebnis hier an, wenn Interesse besteht,kann
ich es fortsetzen.
... ein ASM-Tutorial in dem auf die Nutzung der sehr reichhaltigen
OnChip-Pripherie eingegangen wird wäre sehr hilfreich ...
... und befenkt ... die ARM-Familie hat nur eine sehr eingeschränkte
DSP-Funktionalität ... so fehlen RechenOperationen mit 2 gleichzeitigen
Speicherzugriffen oder ein Schleifenkontrolle ohne Overhead ... oder
.........
... wer sich für wirklich leistungsstarke DSPs mit einer interessanten
Architektur interessiert muß sich die BlackFin Familie von Analog Device
anschauen ... leider im Hobbybereich recht unbekannt ...
Willi S. schrieb:> ... ein ASM-Tutorial in dem auf die Nutzung der sehr reichhaltigen> OnChip-Pripherie eingegangen wird wäre sehr hilfreich ...
Das wäre dann ziemlich aufwendig. Mein Tutorial geht ein bisschen auf
Peripherie ein, den Rest müsste man sich selbst anlesen. Zur Peripherie
gibt es ja schon einige C-Tutorials, die kann man sich ja "übersetzen".
Willi S. schrieb:> so fehlen RechenOperationen mit 2 gleichzeitigen> Speicherzugriffen
Also Rechnen und Speicherzugriff gleichzeitig? Das widerspricht halt
ziemlich dem Load-Store-Prinzip. Ansonsten können die DSP-Extensions und
auch die NEON-Extensions schon einige Rechnungen parallel. Es gibt auch
Intruktionen zum schnellen Laden/Speichern mehrerer Register.
Willi S. schrieb:> ... wer sich für wirklich leistungsstarke DSPs mit einer interessanten> Architektur interessiert
Darum ging's ja auch gar nicht.
hallo @erlkönig!
Erstmal danke für das Tutorial!
Ich hatte mich vor langer Zeit hobbymässig mit mobilen Robots
beschäftigt und will das mal wieder aufnehmen.
Als uC Board verwendete ich damals die C Control II von Conrad mit der
etwas speziellen Programmiersprache C Basic
Ich wollte das Ganze jetzt mal vernünftig programmieren und habe mich
eine zeitlang mit den AVRs beschäftigt (Assembler + C mit der AVR GNU
Toolchain und Arduino Uno)
Aber nun dachte ich, nehme ich mal lieber was ganz Modernes, also ARM
Cortex-M und bin so auf dieses Tutorial gestossen.
Ich will natürlich nichts wirklich in Assembler programmieren, aber für
tiefere Verständnis ist das Tutorial vielleicht ganz gut.
Linker Skripte, Makefiles und so sind Neuland für mich
Ich verwende wie vorgeschlagen das STM32F103RB Nucleo Board und die GNU
ARM Embedded Toolchain + OpenOCD. Ein LED Blink Demo und einfache I/O
über Push Button und LED laufen schon.
Aber so allmählich kommen bei mir die Fragezeichen.
Also frag ich mal:
Using RAM: Example RAMVariables
Es wird Speicher alloziert und initialisiert durch .word 0x20000400
In welcher Section bzw in welchem Speicherbereich findet das statt?
.text (Flash), .data (SRAM)???
Wenn keine Section explizit angegeben wird, kann man dann von .text
ausgehen?
Es handelt sich ja wohl um die Startadresse des Stackpointers, die man,
wie ich durch Herumspielen herausgefunden habe, auch direkt ins Register
r13 (sp) schreiben könnte (wird bei den AVRs ja auch so gemacht, aber
bei den Cortex-M läuft das wohl anders?)
Volker A. schrieb:> Es wird Speicher alloziert und initialisiert durch .word 0x20000400> In welcher Section bzw in welchem Speicherbereich findet das statt?
Da das ganz am Anfang steht, geht das nach ".text", d.h. in den Flash.
Die .word und .space Direktiven am Anfang erzeugen die Vector Table, die
am Anfang im Flash stehen muss. Das wird erläutert in den Abschnitten
https://www.mikrocontroller.net/articles/ARM-ASM-Tutorial#Defining_symbols_in_linker_scriptshttps://www.mikrocontroller.net/articles/ARM-ASM-Tutorial#Improved_vector_tableVolker A. schrieb:> Es handelt sich ja wohl um die Startadresse des Stackpointers
Ja.
Volker A. schrieb:> auch direkt ins Register r13 (sp) schreiben könnte
Kann man auch. Es ist gewissermaßen eine Komfort-Funktion, dass der
Prozessor automatisch dieses erste Wort in das Stack Pointer Register
lädt. Dadurch kann man den Startup-Code auch in C schreiben, weil der
Stack sofort funktioniert. Man kann aber auch mit "mov" oder "ldr" werte
in den SP laden, was man aber normalerweise nur für RTOS o.ä. braucht
Danke für die Antwort!
Ich muss leider englischsprachige Texte immer sehr konzentriert
durcharbeiten. Mal eben auf die Schnelle querlesen funktioniert bei mir
nicht.
Meine nächste Frage wäre gewesen, warum Du den Stack an Beginn des SRAM
einrichtest. Aber ich sehe schon, im Kapitel The Stack wird das geklärt.
Ich bekomme das Beispiel "RamVariables" nicht zum Laufen. Object- und
ELF File werden angelegt. aber das Flashen scheint nicht zu
funktionieren
Hardware: STM Nucleo F103RB
Assembler Code ist wie im Tutorial
Ich verwende folgendes Build Skript
Der Aufruf von openocd liefert u.a.
Warnung: no flash bank found for 0x20000000
Error: Verify failed
Test mit dem Debugger liefert
Reading symbols from ram_variable_demo.elf ...
Remote Debugging localhost:3333
0x2000002e in ?? ()
Um zu sehen, ob da überhaupt was Lauffähiges übertragen wird, habe ich
ein funktionierendes led_link_demo so verändert, das der
Zähler-Startwert für die delay-Schleife in den RAM gespeichert und
anschliessend von dort wieder gelesen wird. Dasselbe Problem, die LED
blinkt leider nicht mehr.
Das OpenOCD habe ich von der xPack Seite, der Download von der
gnu-mcu-eclipse Seite ist depreciated
Ersetzen von stlink-v2.cfg durch stlink.cfg (wg. Warnung stlink-v2.cfg
is depreciated please use stlink.cfg) ändert auch nichts.
vasx schrieb:> Der Aufruf von openocd liefert u.a.
Und was noch?
Klingt als würde er versuchen den RAM zu "flashen". Eigentlich müsste
OpenOCD erkennen dass das RAM ist. Versuche es mal unter Verwendung
eines Linker Script wie in weiteren Kapiteln erläutert. Da wird der RAM
mit dem "NOLOAD" Attribut versehen, wodurch der dann nicht "geflasht"
wird. Kann es jetzt gerade selbst nicht prüfen...
Hallo erlkoenig!
Vielen Dank für dein Tutorial, das ich jetzt weitgehend durchgearbeitet
habe. :-)
Mit über 30 Jahren Erfahrung im Assemblerprogrammieren, waren die
Erklärungen des Befehlssatz für mich sehr leicht zu verstehen und eine
sehr gute Ergänzung zum ARM-Manual, auch wenn der Cortex-M ein paar
ungewöhnliche Eigenheiten hat (IT, BL ohne PUSH des PC).
Besonders hilfreich für mich war die Einführung in die Toolchain
inklusive der Downloadlinks, da ich bisher noch nie mit der
GNU-Toolchain gearbeitet habe (6502 am C=64, 68HC05 mit IAR, MC9S12X mit
CodeWarrior, div. Microchips mit MPLAB).
Ein Satz ist mir besonders aufgefallen:
"The ISR first checks whether the interrupt flag in the timer register
is set - this is necessary, since exceptions can sometimes occur
“spuriously”, i.e. without an actual event causing it."
Gibt's diese Glitches beim ARM bzw. ST wirklich? Ich hab' in den letzten
Jahrzehnten keine solchen Sicherheitsabfragen drinn und es sind keine
Probleme aufgetreten (und die hätte ich sicher bemerkt, bei der Menge an
Interrupts die ich pro Anwendung verwende).
Bei einer externen PIN-Quelle (also "normaler" Interrupt-Pin) ist es
selbverständlich, nochmal zu prüfen ob da wirklich eine Flanke war. Aber
gibt es wirklich Interrupts von internen Quellen, wobei des
entsprechende Interruptflag nicht mal gesetzt ist?
Ist das eine Vorsichtsmassnahme von dir, oder gibt's da sonst noch
irgendwelche Hinweise von Hersteller oder Nutzern?
Grüsse, Gernot Schreiner
Gernot S. schrieb:> Vielen Dank für dein Tutorial, das ich jetzt weitgehend durchgearbeitet> habe. :-)
Danke, gern ;-)
Gernot S. schrieb:> Gibt's diese Glitches beim ARM bzw. ST wirklich?
Ich hatte das so noch im Hinterkopf und nicht mehr genau nachgeprüft.
Wenn überhaupt tritt das sowieso nur selten und vermutlich nur mit
bestimmten Peripherie-Modulen/Konfigurationen auf, aber ich würde nicht
garantieren dass es in "normalen" Anwendungsfällen absolut nie passiert,
weshalb ich das zur Sicherheit immer einbaue.
Zudem sind bei vielen Peripherien (inkl. Timer) mehrere Ereignisse auf
den selben IRQ gemappt, weshalb man, wenn man mehrere nutzt, ohnehin
abfragen muss, welches Ereignis jetzt genau eingetreten ist. In
Assembler ist das ganze natürlich etwas lästiger als in C, aber das ist
dann eben so :-)
Gernot S. schrieb:> auch wenn der Cortex-M ein paar> ungewöhnliche Eigenheiten hat (IT, BL ohne PUSH des PC)
Das liegt daran, dass ARM allgemein eine Load and Store Architektur hat,
also alle Befehle arbeiten nur auf Registern, AUßer eben spezielle Lade
und Speicherbefehle.
Deswegen packt BL den PC ins Linkregister und wenn eine Unterfunktion
selber BL nutzt muss der das aben auf den Stack packen.
IT ist son Spezialfall um die bedingte AUsführung der großen ARM Kerne
auch auf den C-M eingeschränkt anzubieten.
Damit ein kleines if else nicht die Pipeline stallt durch Sprünge.
Christoph db1uq K. schrieb:> Ich habe mein altes DSP-Projekt schon mehrfach erwähnt, ein IIR-Hilpert> als Breitband 90 Grad Phasenschieber zur SSB-Erzeugung. Passt mit Mühe> noch in einen Arduino, aber 2 Bit mehr ADC und viel mehr Power in> derselben Preislage wäre interessant. Das sind 8 IIR-Allpassfilter mit> jeweils nur einer Multiplikation und ein paar Additionen.
Aha aha! das klingt interessant. Kann man das irgendwo anschauen?
ich habe es mal analog gemacht. Funktioniert. Der Vergleich zur DSP
Lösung wäre spannend.
Tobias
1000 Dank für dieses hervorragende Tutorium, einfach Klasse wie es
Schritt für Schritt aufbaut. Damit ist der (sehnlichst gesuchte)
Einstieg in ARM-ASM endlich gelungen.
Dank und Gruß
Stefan
>Kann man das irgendwo anschauen?https://www.mikrocontroller.net/articles/Hilbert-Transformator_(Phasenschieber)_mit_ATmega
schon 10 Jahre her, aber die Mathematik hat sich nicht verändert.
Für QO-100 ist das wieder interessant geworden. Ein SSB-Sender
herkömmlicher Art für 2,4 GHz braucht einiges an Filtertechnik und
mehrfache Umsetzung, das wird mit der Phasenmethode wesentlich
einfacher.
Zwischen Mikrofonverstärker und IQ-Aufwärtsmischer nur ein Arduino oder
ARM als Phasensplitter, reine Niederfrequenztechnik.
Niklas G. schrieb:> Es geht um das Programmieren von ARM-Cortex-M in Assembler
Warum sollte man das tun? Ein guter Compiler optmiert 10mal besser als
du. Warum? Weil die Jungs 8h an dem Ding feilen. ;-)
Cross posting? Nein Danke.
Assembler ist wie Autofahren a la Fred Feuerstein. Obwohl, das kommt
wieder in Mode; die Leute haben zuviel lange Weile. :-(
MaWin (Gast)
24.04.2021 21:27
>Warum sollte man das tun? Ein guter Compiler optmiert 10mal besser als>du. Warum? Weil die Jungs 8h an dem Ding feilen. ;-)
Klingt nach logischem Schluss, ist aber keiner.
Man wird in C niemals die Maschine wie mit Assembler ausreizen können.
Wenn Du's nicht glaubst, programmiere das
Beitrag "17 Kanal Avr Synthesizer in Asm"
oder das
https://www.linusakesson.net/scene/craft/index.php
in C.
Fairerweise muss man sagen, dass man bei ARM-Controllern in den
allermeisten Fällen einfach einen 10% schnelleren Controller nehmen
kann, um den ggf. vorhandenen Performance-Nachteil der Hochsprache
auszugleichen, sofern denn überhaupt einer vorhanden ist. Wie im Artikel
beschrieben sind Assembler-Kenntnisse eher zum Debuggen oder Schreiben
von Startup-Codes, RTOSes o.ä. sinnvoll.
Wer in ASM programmiert denkt auch in den Strukturen des Prozesses und
wird seine Aufgabenstellung optimal auf diese Anpassen ... dabei gilt
die Regel ... je komplexer / leistungsfähiger die Architektur des
Prozessors - desto mehr EffizienzGewinn dur Assembler-Programmierung ...
als Beispiel möchte ich die BlackFin-Familie von Analog Devices erwähnen
... hier gilt es jeden Takt optimal zu nutzen - was auch möglich ist ...
wo hingegen die ARM-Familie hier "grottenschlecht" anschneidet ...
einfach viel zu viel unnütze "Penalty-Clocks" auf die der Programmier
(fast) keinen Einfluß hat ...
In ASM denken ... schrieb:> Wer in ASM programmiert denkt auch in den Strukturen des Prozesses und> wird seine Aufgabenstellung optimal auf diese Anpassen
Totaler Schwachfug! Ein Mensch denkt immer in Objekten, Dinge die er
sieht. Dinge, die in engem Zusammenhang stehen. So eine Binärmaschine
bedarf eines hohen Abstraktionsvermögen zur Umsetzung in die Relaität.
Bei den komplexen Zusammenhängen heute (ARM Cortex und der Realisierung
von mehr als elektronischem Würfel oder Modell Ampelschaltung) lässt
sich das nicht vernünftig in ASM umsetzen. Deine Vorarbeiten auf Papier
kannste gleich in eine Hochsprache stecken. Je abstrakter, desto
effizienter.
von MaWin (Gast)
>In ASM denken ... schrieb:>> Wer in ASM programmiert denkt auch in den Strukturen des Prozesses und>> wird seine Aufgabenstellung optimal auf diese Anpassen>Totaler Schwachfug! ... Je abstrakter, desto>effizienter.
Genau an dem Punkt liegst du ziemlich falsch. Optimierung findet auf der
konkreten und nicht der abstrakten Ebene statt.
In ASM denken ... schrieb:> je komplexer / leistungsfähiger die Architektur des> Prozessors - desto mehr EffizienzGewinn dur Assembler-Programmierung ...
Auf der Ebene von Mikrocontrollern kann das noch funktionieren. Auf der
Ebene von x86 oder Highend-ARM ist das mittlerweile sehr schwierig. Die
Komplexität ist zu gross, die Doku zu ungenau, die einzurechnenden
Faktoren zu vielfältig.
chris_ schrieb:> Genau an dem Punkt liegst du ziemlich falsch. Optimierung findet auf der> konkreten und nicht der abstrakten Ebene statt.
Es gibt konkrete Optimierung auf Befehls- und Registerebene. Es gibt
abstrakte Optimierung der Algorithmen (Theorie, à la Knuth/Wirth). Wurde
die abstrakte Strategie aufs falsche Gleis gesetzt, sitzt man vielleicht
so tief in der Tinte, dass konkrete Optimierung für die Katz ist.
Und es gibt dazwischen eine Optimierung der Algorithmen unter
Berücksichtigung von Speicherzugriffszeiten und -Strategien aktueller
Prozessoren (z.B. ist sequentieller Zugriff im RAM so viel schneller als
zufälliger, dass einstmals für Bandbetrieb gute Algorithmen auch im RAM
sinnvoll sein können. Das hatte Knuth nicht auf der Rechnung.
(prx) A. K. schrieb:> Auf der Ebene von Mikrocontrollern kann das noch funktionieren. Auf der> Ebene von x86 oder Highend-ARM ist das mittlerweile sehr schwierig.
Aber immer noch möglich. Und kann zu kaum glaubhaften
Performance-Vorteilen führen. Typisch natürlich vor allem dann, wenn man
Maschinen-Features verwendet, die der verwendete Compiler schlicht noch
garnicht kennt. So ist das, wenn man sich von den Werken Anderer
sklavisch ergeben abhängig macht (und das auch noch gut findet)...
Aber auch ohne solchen "unfairen" Vorteile ist der Mensch immer noch
besser als der Compiler. Wenn er halt gut genug ist.
Ja klar, es ist längst nicht mehr so einfach, richtig überragende
Vorteile zu erzielen, wie es früher(tm) mal war. Die Compiler für die
x86 und die ARMs sind wirklich in den letzten 20 Jahren sehr viel besser
geworden. Aber ein paar Prozent (einstellig) mehr mit Asm gehen auch
heute praktisch noch immer. Und das ohne allzu große Mühe. Wenn man es
halt einfach kann...
Walter T. schrieb:> Ist damit diese Tabelle (ungefähr in der Mitte der Seite) gemeint
Ja, die gibt es noch mal im ARMv7M Architecture Reference Manual, das
ist IIRC A4 Format.
@Niklas:
Sind eigentlich kleine Korrekturen/Ergänzungen gewünscht, oder willst Du
das Tutorium lieber komplett unter Deinen Fittichen behalten?
Ich bin noch nicht ganz durch, aber war mir schon aufgefallen ist:
- Links zu den entsprechenden Dokumenten des Instructions Sets wären
sinnvoll
- Bei den Immediates jeweils die Grenze benennen (um schnell ein Gefühl
für die Größenordnung zu bekommen)
- Das Verb "utilized" an unpassender Stelle ist mir ja immer ein Dorn
im Auge :-)
Oder Änderungsvorschläge auf die Diskussionsseite?
Ansonsten finde ich bis jetzt alles ziemlich gut aufeinander aufgebaut
(bin jetzt grob bei der Hälfte).
Walter T. schrieb:> Sind eigentlich kleine Korrekturen/Ergänzungen gewünscht
Klar, deswegen ist es ja ein Wiki 😉 Größere Änderungen sollte man
vielleicht vorher hier absprechen.
Nachtrag: Die Sachen, die mich am Anfang gestört haben, tun es im
Nachhinein nicht mehr.
An vielen Stellen war das, was mich gestört hat, wenn im Quelltext
Konstrukte standen, die noch nicht erklärt waren. Das hat dann immer
etwas Suche in den von ARM bereitgestellten Materialien gekostet, nur um
es dann am Ende des jeweiligen Kapitels doch noch einmal erklärt zu
finden.
Erst nutzen - dann erklären oder andersherum ist wohl eine Frage des
persönlichen Stils und hat deswegen keinen Verbesserungsbedarf. Im
Nachhinein ist das auch keine verschwendete Zeit gewesen. So ist man
eben schon recht zügig mit der Doku von ARM vertraut gemacht worden und
hat auch direkt seinen eigenen Spickzettel geschrieben. (Einen eigenen
Spickzettel zu schreiben halte ich immer noch für einen wichtigen Faktor
beim Lernerfolg.)
Ein wenig fehlt mir am Ende noch ein "Und jetzt ...", aber das wird wohl
darauf hinauslaufen, Joseph Yius "Definitive Guide to ARM Cortex-M3 and
Cortex-M4 Processors" noch einmal zu inhalieren.
Deswegen an Niklas: Danke für dieses nützliche Tutorial!
Walter T. schrieb:> Erst nutzen - dann erklären oder andersherum ist wohl eine Frage des> persönlichen Stils und hat deswegen keinen Verbesserungsbedarf.
Ich find's immer etwas blöd erst alle Details haarklein zu erläutern und
dann auf das "big picture" zu kommen - so blickt man auch nicht schnell
durch, worum es geht. Wenn ein Hello World in C erläutert wird, kommt
auch nicht zuerst eine Erklärung des "#include <stdio.h>".
Walter T. schrieb:> Ein wenig fehlt mir am Ende noch ein "Und jetzt ...",
Stimmt, ein "Literatur"-Kapitel wäre nicht schlecht, vielleicht auch am
Anfang.
Walter T. schrieb:> Deswegen an Niklas: Danke für dieses nützliche Tutorial!
Danke ;-)
Niklas G. schrieb:> Ich find's immer etwas blöd erst alle Details haarklein zu erläutern und> dann auf das "big picture" zu kommen - so blickt man auch nicht schnell> durch, worum es geht.
Ich bin auch ein entschiedener Fan von "erst die Übersicht - dann der
Kleinkram". Die sinnvolle Reihenfolge hängt auch immer ein wenig vom
Lerntyp ab.
Ich habe immer versucht, den Assembler-Quelltext nach der Beschreibung
vom Anfang erst einmal selbst zu schreiben, und habe deswegen auch die
Teile immer in der Reihenfolge angegangen, wie ich normal eine
Programmieraufgabe angegangen wäre. Wenn ich nicht weiterkam, wurde dann
ein Blick auf die Vorlage geworfen. Und da stand dann (fast) immer ein
Konstrukt, was ich nie zuvor gesehen habe.
Andere werden wahrscheinlich anders vorgehen.
Niklas G. schrieb:> Wenn ein Hello World in C erläutert wird, kommt> auch nicht zuerst eine Erklärung des "#include <stdio.h>".
Und das "Hello World" ist natürlich die Ausnahme von der Regel "erst
selbst versuchen - dann abgucken.". Da geht es ja erst einmal darum, die
Entwicklungsumgebung am Laufen zu haben.
Niklas G. schrieb:> Stimmt, ein "Literatur"-Kapitel wäre nicht schlecht, vielleicht auch am> Anfang.
Die Quick Reference Card wäre noch eine sinnvolle Ergänzung bei den
Manuals am Anfang. Ich habe mir mal erlaubt, diese zu ergänzen, und die
nicht mehr funktionierenden Links auf static.docs.arm.com wieder zu
füllen.
Wieso ist bei Hex-Konstanten , die mit #0x... beginnen, eigentlich "#0"
in grau geschrieben und alles ab dem 'x' in rot?
Im Gegensatz dazu sind Hex-Konstanten, die nicht in einem
Assemblerbefehl stehen, sondern als Datenwort auftauchen (also ohne #),
komplett in grau.
Auch Zahlen in Assemblerbefehlen, die nicht in Hex sind, z.B. "#1234",
sind komplett in grau.
Nop schrieb:> Wieso ist bei Hex-Konstanten , die mit #0x... beginnen, eigentlich "#0"> in grau geschrieben und alles ab dem 'x' in rot?
Wenn ich raten müsste: Die Foren-Software hat keine ASM-Formatierung,
sondern nur "code" allgemein. Die "#" werden dann als Anfang einer
HTML-Farbe interpretiert und ab dem "x" weiss der Interpreter, dass er
falsch liegt.
Wow. Vielen Dank für dieses sehr aufschlussreiche, äußerst verständlich
geschriebene und sehr gut aufgebaute Tutorial!!!
Ich selbst komme aus der Webentwicklung und beschäftige mich nur privat
mit dem STM32G0. Meine kleinen Projekte basieren nicht auf kommerzielle
Interesse, sondern auf dem Interesse an der Technologie und der
Funktionsweise.
ST versucht mit CubeMX den Einstieg leicht zu machen und das geht nunmal
nur, wenn man stark abstrahiert und automatisiert. Selbst bei Verzicht
auf HAL wird man von dem generierten Projektordner erstmal erschlagen.
Nach dem Motto: Hier ist der End-User-Bereich, tippe da dein Code rein
und ignoriere alles, was oben und unten steht. Was wurde generiert,
warum und wie genau hängt das alles zusammen? Warum habe ich das Gefühl,
dass in dem Projektordner weit mehr Zeug generiert wurde, als ich für
mein einfaches Projekt benötige?
Ich habe viele Tutorials gelesen, um solche Fragen für mich beantworten
zu können. Mit Hilfe deiner Ausführungen bin ich jetzt endlich in der
Lage, den LL-Bereich grundlegend nachzuvollziehen zu können.
Insbesondere der Startup-Prozess des Controllers und die Zusammenhänge
beim Kompilierprozess sind sehr verständlich dargestellt.
Vielen Dank für die Arbeit, die Du da reingesteckt hast. Für mich ist
das das bisher beste Tutorial zum Thema.
P. S.: Dass hier teilweise über Sinn/Unsinn von ASM diskutiert wird,
führe ich darauf zurück, dass einige Leute mit dem genannten
End-User-Bereich entweder komplett OK sind oder es einfach nicht gerne
sehen, wenn ihr mühsam erarbeitetes Know-how auf eine derart einfache
Art beschrieben werden kann.
Andre schrieb:> Wow. Vielen Dank für dieses sehr aufschlussreiche, äußerst verständlich> geschriebene und sehr gut aufgebaute Tutorial!!!
Danke für die Blumen ;-)
Andre schrieb:> ST versucht mit CubeMX den Einstieg leicht zu machen und das geht nunmal> nur, wenn man stark abstrahiert und automatisiert. Selbst bei Verzicht> auf HAL wird man von dem generierten Projektordner erstmal erschlagen.
Beim STM32 geht es eigentlich noch. Im Wesentlichen ist das auch nur ein
Linkerscript, Startup-Code (der praktisch nur ein memcpy, ein memset und
eine Schleife für die Konstruktoren enthält), und Clock-Initialisierung.
Die HAL oder LL-Library kann man dann optional aufrufen, entweder mit
eigenem oder generiertem Code.
Bei anderen Controller-Familien ist das noch viel schlimmer, wo man mal
ein paar Wochen brauchen kann bis man eine Hello World (in C) kompiliert
und geflasht hat, weil man erstmal über den Support herausfinden muss,
welche der ganzen komplexen Tools überhaupt wie miteinander spielen und
weil selbst der Demo-Code erstmal nicht kompiliert. Da sehnt man sich
nach so einem handlichen genügsamen STM32H7 :)
Ich programmiere ja wirklich gerne in ASM, aber nachdem ich mir die
ARM-Architektur angeschaut habe, musste ich zum Schluss kommen, dass
dort ASM eine noch wesentlich masochistischere Ader vorraussetzt als
AVR-ASM.
Beim AVR kann man durchaus darüber diskutieren, ob es sinnvoll ist oder
nicht, Projekte komplett in Assembler zu schreiben, aber beim ARM sehe
ich da wirklich keine Sinnhaftigkeit mehr.
In ASM bekommt man bei komplexeren Routinen immer schnell das Problem,
dass es zu wenig Register gibt, so dass man gezwungen wird, Register
doppelt zu belegen, also wiederzuverwenden. Sowas ist einem C-Compiler
natürlich völlig egal, aber für das menschliche Gehirn wirds dann
langsam kompliziert.
Glücklicherweise hat der AVR ja 32 Register. Da kann man als Mensch noch
gut mit arbeiten. Der ARM hat, wenn ich das in meiner relativ kurzen
Recherche richtig rausgefunden habe, jedoch nur 16, von denen man nur 12
wirklich frei nutzen kann.
Mit 12 Registern haste net viel Spass...
Jan schrieb:> Beim AVR kann man durchaus darüber diskutieren, ob es sinnvoll ist oder> nicht, Projekte komplett in Assembler zu schreiben, aber beim ARM sehe> ich da wirklich keine Sinnhaftigkeit mehr.
Ja, darum ging es auch nie. Das wäre wenn schon nur eine Knobelei "just
for fun". Ich finde den ARM-Assembler allerdings angenehmer als den
AVR-Assembler, einfach weil man viel mehr auf einmal erledigen kann. Das
wird allerdings durch die üblicherweise komplexere Peripherie der
meisten Cortex-M ausgeglichen, die mehr Register-Zugriffe braucht.
Jan schrieb:> Der ARM hat, wenn ich das in meiner relativ kurzen> Recherche richtig rausgefunden habe, jedoch nur 16, von denen man nur 12> wirklich frei nutzen kann.
Es sind 13, es sei denn man belegt eines fix als Frame Pointer oder
Basispointer für PIC o.ä. Die schräge Zahl kommt daher, dass viele
Befehle einen 4bit-Wert für Register-Operanden haben, und es eben drei
Spezial-Register gibt (r13=SP, r14=LR, r15=PC). Weil man alle Register
einheitlich (mit Ausnahmen) über Instruktionen ansprechen möchte, sind
diese drei Register eben Teil der möglichen 16, sodass 13 übrig bleiben.
Dabei ist es so, dass r13 und r14 im Prinzip nahezu beliebig auch für
Berechnungen genutzt werden können - wenn man aber sein Programm
"normal" mit Funktionen, Stack, Rücksprüngen & Co strukturiert, darf man
den r13=SP natürlich nicht "verlieren". Das r14=LR hingegen kann man auf
dem Stack sichern, wenn man 14 Register braucht. Beim Zurückkehren kann
man dann mit POP die Rücksprungadresse direkt ins PC holen.
z.B. die Funktion
1
.type test, %function
2
test:
3
push { r4-r11, lr }
4
5
@ Inhalt...
6
7
pop { r4-r11, pc }
Kann alle 14 Register nutzen von r0-r12 sowie r14=LR, und kann mit der
Standard ARM Calling Convention (AACPS) auch ganz normal von C-Code aus
aufgerufen werden.
Jan schrieb:> Mit 12 Registern haste net viel Spass...
Es geht eigentlich, schließlich braucht man ja auch nur eines für
Pointer statt zwei wie beim AVR, und man hat viel weniger
Zwischenergebnisse dank Offset-Adressierung. Für die typische
Assembler-Routine die man mal als Glue-Code, Kontextwechsel für RTOS,
Startup-Code, hochoptimiertes memcpy o.ä. braucht reicht das locker ohne
Doppelbelegung.
Jan schrieb:> Mit 12 Registern haste net viel Spass...
Von wegen! Mit 4 Registern baue ich mir eine virtuelle 2-Stack-Maschine
und mit 30 Befehlen in 1KB Assemblercode habe ich eine Hochsprache, die
vieeeel Spaß macht :-)
Man muß aber Spaß am Denken haben, das liegt nicht jedem ;-(
Gruß
Klaus (der soundsovielte)
Niklas G. schrieb:> Bei anderen Controller-Familien ist das noch viel schlimmer, wo man mal> ein paar Wochen brauchen kann bis man eine Hello World (in C) kompiliert> und geflasht hat, weil man erstmal über den Support herausfinden muss,> welche der ganzen komplexen Tools überhaupt wie miteinander spielen und> weil selbst der Demo-Code erstmal nicht kompiliert. Da sehnt man sich> nach so einem handlichen genügsamen STM32H7 :)
Puh, zum Glück muss ich nicht soweit gehen :)
Die Idee ist, sich komplett auf eine Mainstream-Familie einzuschießen,
von der man sich vorstellen kann, dass sie sämtliche eventuelle
Anforderungen im Hobbybereich erfüllen kann (Gartenbewässerung,
Rolladen- und Lichtsteuerung, etc.). Für diese dann eine sehr minimale
und wiederverwendbare Grundstruktur in Hard- und Software aufzubauen und
bedarfsgesteuert mit eigenentwickelten, stark zugeschnittenen und
minimalistischen Bibliotheken zu erweitern. Angefangen von der Idee über
die Platinenerstellung bis hin zur hoffentlich nützlichen
Steuerungseinheit will ich den gesamten Prozess tiefgreifend verstehen
und für meine Zwecke beherrschen können.
Der Weg ist das Ziel. Ich erwarte mir davon hunderte von Abendstunden
voller freudebringender Erfolgsmomente und zu knackender Nüsse.
In dem Teilprozess der Softwareentwicklung halte ich die Beherrschung
oder zumindest ein weitreichendes Verständnis des Low-Levels für
unumgänglich. Ich werde in diesem Sinne in dem Tutorial immer und immer
wieder nachschlagen, bis alle offenen Fragen geklärt und verinnerlicht
sind.
Beste Grüße
Andre
Andre schrieb:> Anforderungen im Hobbybereich erfüllen kann (Gartenbewässerung,> Rolladen- und Lichtsteuerung, etc.).
äääh.... und dafür brauchst du einen ARM? Selbst mein
selbstprogrammiertes Smart-Home Steuersystem über Funk, was nun wirklich
alles notwendige hat (AES, CRC, EEPROM Raid1, time-sync, definierter
Protokollstack) kommt noch mit einem attiny84A aus.
Andre schrieb:> Die Idee ist, sich komplett auf eine Mainstream-Familie einzuschießen,
Das würde ich nicht unbedingt so machen, früher oder später werden
andere Controller vielleicht doch interessant. Das ist ja gerade das
Tolle an ARM - man kann mit den selben Tools eine riesige Menge an den
unterschiedlichsten Controllern abdecken. Die LPC11Cxx wären z.B. auch
interessant wegen des integrierten CAN.
Einen Haken hat es: Die unterschiedlichen Controller haben
unterschiedliche Befehlssätze, der genannte LPC ist ein Cortex-M0 mit
ARMv6M-Befehlssatz. Wenn man den selben Code auf den unterschiedlichen
Cortex-M laufen lassen möchte, muss man sich entweder auf ARMv6M
beschränken (und Effizienz-Einbußen auf den größeren Controllern
hinnehmen) oder halt eine Hochsprache verwenden.
Daher ist das mit "eine ganze komplexe Anwendung in Assembler schreiben"
nicht so optimal.
Jan schrieb:> äääh.... und dafür brauchst du einen ARM? Selbst mein> selbstprogrammiertes Smart-Home Steuersystem über Funk, was nun wirklich> alles notwendige hat (AES, CRC, EEPROM Raid1, time-sync, definierter> Protokollstack) kommt noch mit einem attiny84A aus.
Nein. Brauche ich natürlich nicht, möchte ich aber :)
Mit dem atmega8 hatte ich vor einigen Jahren viel Spaß und habe ihn nie
wirklich ausreizen können. Mir ist also vollkommen bewusst, dass
Cortex-M selbst mit dem kleinsten Vertreter für den Moment ein Overkill
ist.
Es ist so eine Abwägungssache: In welche Architektur oder in diesem Fall
in welchen spezifischen Mainstream-Controller will man viel Zeit
investieren, um möglichst bis über das Rentenalter hinaus von dem
Gelernten zu profitieren ohne switchen zu müssen?
Und da sagt das Bauchgefühl einfach, dass man bei ARM besser aufgehoben
ist. Die STM32G0-Reihe übertrifft den AVR in jeglicher Hinsicht. Ob es
nun die Peripherie ist, die Performance oder das P/L-Verhältnis
(zumindest vor der Chip-Krise). Dass der MC dann in den meisten Fällen
komplett unterfordert ist, stellt für mich jetzt erstmal kein größeres
Problem dar. Besser haben als brauchen (z.B.: RTC, DMA u.Ä.).
Was mich bspw. am AVR auch stört, ist die Quasi-Monopolstellung von
Microchip seit Übernahme. Das ARM-Lizenzmodell scheint mir
markttechnisch sehr viel robuster, da man sich aufgrund eines ganzen
Netzwerks von Abhängigkeiten davor hüten wird irgendwelche
einschneidenden Entscheidungen zu treffen. Wer weiß schon, was die
Zukunft so bringt und wenns hart auf hart kommt, dann stelle ich mir ein
Switch von ST zu bspw. NXP einfacher vor, als auf Architekturebene von
AVR zu ARM.
Zudem werde ich einfach das Gefühl nicht los, dass die
Daseinsberechtigung der ATMegas überwiegend nur noch auf Arduino
zurückzuführen sind. Damit möchte ich niemandem auf die Füße treten,
aber ich denke einfach, dass die Blütezeit der AVRs vorbei ist.
Beste Grüße
Andre
Andre schrieb:> in welchen spezifischen Mainstream-Controller will man viel Zeit> investieren, um möglichst bis über das Rentenalter hinaus von dem> Gelernten zu profitieren ohne switchen zu müssen?
Naja, wenn du jetzt schon 60 bist, kannst du vielleicht so rechnen, aber
es gibt sich mehrende Stimmen, die behaupten, dass RISC-V das neue ARM
wird.
Andre schrieb:> Zudem werde ich einfach das Gefühl nicht los, dass die> Daseinsberechtigung der ATMegas überwiegend nur noch auf Arduino> zurückzuführen sind.
[] Du weisst, wie der Halbleitermarkt funktioniert.
Andre schrieb:> Was mich bspw. am AVR auch stört, ist die Quasi-Monopolstellung von> Microchip seit Übernahme.
Die können aktuelle Typen aber liefern.
Im Gegensatz zu STM
Beitrag "STM32 - ST - Hinhaltetaktik oder Insolvenzverschleppung?"Andre schrieb:> Damit möchte ich niemandem auf die Füße treten, aber ich denke einfach,> dass die Blütezeit der AVRs vorbei ist.
Das haben hier schon lange viele gedacht (gewünscht). Fakt ist aber, was
langt, demzufolge eingesetzt wird, bleibt in Produktion. Ob das Jahr nun
2000, 2022 oder 2042 heisst.
Walter T. schrieb:> Perfekt. So eine "AVR vs. ARM"-Diskussion hat in diesem Thread über> ARM-Assembler absolut gefehlt. Weiter so!
Uups, das war gar nicht die Absicht. Das werde ich nicht mehr anfeuern
;)
Niklas G. schrieb:> Einen Haken hat es: Die unterschiedlichen Controller haben> unterschiedliche Befehlssätze, der genannte LPC ist ein Cortex-M0 mit> ARMv6M-Befehlssatz. Wenn man den selben Code auf den unterschiedlichen> Cortex-M laufen lassen möchte, muss man sich entweder auf ARMv6M> beschränken (und Effizienz-Einbußen auf den größeren Controllern> hinnehmen) oder halt eine Hochsprache verwenden.
Auf jeden Fall Hochsprache. Aber eben erst, wenn die grundlegenden
Abläufe (Startup, Linker, Funktionsweise des Prozessors, Aufbau des
Address-Space etc.) keine offenen Fragen mehr aufwerfen.
Ich habe mal gelesen, dass Startup-Scripts von Projekt zu Projekt
"blind" kopiert werden und der Entwickler nicht wirklich weiß, wofür es
da ist, solange es irgendwie damit funktioniert. Das ist nicht schön.
Ausserdem habe ich in vielen Scripten und Beispielen "subs" und "adds"
gesehen und habe das nie hinterfragt. Jetzt weiß ich, dass in einigen
davon auch "sub" und "add" ihren Zweck erfüllt hätten, da der APSR
anschließend weder direkt noch indirekt ausgewertet wird. Auch das ist
nicht schön.
Jan schrieb:> Naja, wenn du jetzt schon 60 bist, kannst du vielleicht so rechnen, aber> es gibt sich mehrende Stimmen, die behaupten, dass RISC-V das neue ARM> wird.
Ja, dem kann man wohl nicht widersprechen. Bis zum Rentenalter sind es
bei mir noch 30 Jahre plusminus, je nach dem, wo das
Renteneintrittsalter dann sein wird. Also eher plus. Eventuell lohnt
sich irgendwann dann auch ein Blick über den Tellerrand in Richtung
RISC-V. Mein aktuelles Problem ist, dass ich als Laie (noch) gar keinen
Teller habe und mit einer Architektur anzufangen, über deren zukünftige
Dominanz aktuell nur spekuliert wird, wäre suboptimal.
Jan schrieb:> [] Du weisst, wie der Halbleitermarkt funktioniert.
Neee. Ist nur so n Bauchgefühl.
Ron T. schrieb:> Die können aktuelle Typen aber liefern.> Im Gegensatz zu STM
Bei Mouser gab es hin und wieder einige kurze Zeitfenster, in denen man
abgreifen konnte und bei Ali habe ich letztens noch den G031F8P6 zum
Vorkrisenzeitenpreis bestellt. Ich habe mindestens für die kommenden 5
Jahre vorgesorgt ;)
Andre schrieb:> Ich habe mal gelesen, dass Startup-Scripts von Projekt zu Projekt> "blind" kopiert werden und der Entwickler nicht wirklich weiß, wofür es> da ist, solange es irgendwie damit funktioniert. Das ist nicht schön.
Das ist definitiv so, aber ich kann es den Leuten nicht verdenken - zum
Assembler lernen hat keiner Zeit, Projekte haben Zeitpläne, oft vergeht
schon genug Zeit bis die erste LED blinkt, da muss man nicht auch noch
die Details vom schon fertigen Startup-Code (der übrigens so ziemlich
das Gegenteil von einem Script ist) auseinander nehmen. Das Verhalten
des Linkers wird sowieso in der Bildung und Literatur meistens
ausgelassen.
Andre schrieb:> Jetzt weiß ich, dass in einigen> davon auch "sub" und "add" ihren Zweck erfüllt hätten, da der APSR> anschließend weder direkt noch indirekt ausgewertet wird. Auch das ist> nicht schön.
Na das ist verglichen mit den üblichen Problemen die viele Projekte so
haben größenordnungstechnisch aber eher mit dem Mikroskop zu suchen!
Niklas G. schrieb:> Das ist definitiv so, aber ich kann es den Leuten nicht verdenken - zum> Assembler lernen hat keiner Zeit, Projekte haben Zeitpläne, oft vergeht> schon genug Zeit bis die erste LED blinkt, da muss man nicht auch noch> die Details vom schon fertigen Startup-Code (der übrigens so ziemlich> das Gegenteil von einem Script ist) auseinander nehmen. Das Verhalten> des Linkers wird sowieso in der Bildung und Literatur meistens> ausgelassen.
Die Motivationen und die Umstände gehen da bei Amateuren (wie mir) und
Profis weit auseinander. Da habe ich auch vollstes Verständnis für.
Ich kenne den Bildungsgang leider nicht, finde es aber sehr schade, dass
der Linker und somit vermutlich auch der Rest des Kompilierprozesses
nicht im Detail gelehrt wird.
Das würde vermutlich im Berufsleben viel Troubleshooting und etliche
Fragezeichen einsparen.
Das mit dem "Script" sehe ich ein und nehme das zurück :)
Niklas G. schrieb:> Na das ist verglichen mit den üblichen Problemen die viele Projekte so> haben größenordnungstechnisch aber eher mit dem Mikroskop zu suchen!
Das ist in der Tat sehr penibel und ich bin sicherlich der letzte, der
das beurteilen dürfte. Aber solche Momente motivieren umso mehr, bei den
Details genauer hinzuschauen.
Ich kann meinen Urlaub kaum abwarten! Das Steckboard ist bereits fertig
bestückt :)
Niklas
>Das würde ich nicht unbedingt so machen, früher oder später werden>andere Controller vielleicht doch interessant. Das ist ja gerade das>Tolle an ARM - man kann mit den selben Tools eine riesige Menge an den>unterschiedlichsten Controllern abdecken. Die LPC11Cxx wären z.B. auch>interessant wegen des integrierten CAN.
Der einzige Grund Assembler machen zu wollen ist maximale
Rechenzeitperformance aus einem Controller herausholen zu wollen.
Assembler für alles andere kann man als Denksporthobby betreiben, was
ansonsten unter Codeentwicklungszeitgesichtspunkten völlig unsinnig ist
(das schreibe ich mit einiger Erfahrung. Ich habe mehr als 4
verschiedene MCU- und DSP Architekturen und deren
Assemblerprogrammierung hinter mir inclusive einiger
selbstprogrammierter virtueller Maschinen der MCUs).
Andre
>Es ist so eine Abwägungssache: In welche Architektur oder in diesem Fall>in welchen spezifischen Mainstream-Controller will man viel Zeit>investieren, um möglichst bis über das Rentenalter hinaus von dem>Gelernten zu profitieren ohne switchen zu müssen?
Wenn auf maximale Performance ankommt, ist das Arduino-Framework die
einzig sinnvolle Wahl. Für keine andere Umgebung gibt es für so viele
verschiedene Controllerfamilien so viele Libraries. Und die wird es auch
in 10 Jahren noch geben, weil das Ganze immer noch auf der
Wachstumskurve ist.
Andre schrieb:> Bei Mouser gab es hin und wieder einige kurze Zeitfenster, in denen man> abgreifen konnte und bei Ali habe ich letztens noch den G031F8P6 zum> Vorkrisenzeitenpreis bestellt. Ich habe mindestens für die kommenden 5> Jahre vorgesorgt ;)
Schön für Dich aber hier gibt es inzwischen einige Verzweifelte
Threads...
chris_ schrieb:> Der einzige Grund Assembler machen zu wollen ist maximale> Rechenzeitperformance aus einem Controller herausholen zu wollen.> Assembler für alles andere kann man als Denksporthobby betreiben
Das mag für Dich und mag für 32bittige Controller gelten.
chris_ schrieb:> Wenn auf maximale Performance ankommt, ist das Arduino-Framework die> einzig sinnvolle Wahl.
Und wieder viel zu absolut.
chris_ schrieb:> Der einzige Grund Assembler machen zu wollen ist maximale> Rechenzeitperformance aus einem Controller herausholen zu wollen.
Unfug.
Asm hat in Zeiten sprach- und anwendungsbürokratisch völlig außer Rand
und Band geratener Hochsprachen wieder das Potential, die Dinge zu
vereinfachen und auf den Punkt zu bringen. Mit der Beschränkung auf
wenige Controller-Typen, fertigen Code-Basics für vielbenötigte
Schnittstellen I/O und etwas Erfahrung gelingt das durchaus in
vergleichbarer Entwicklungszeit. Mit maximaler Gestaltungsfreiheit- ohne
sich in Denkschablonen pressen lassen zu müssen.
Das kennt ja der typische Hochsprachen- Programmierer heutzutage meist
gar nicht mehr...