Forum: Compiler & IDEs ARM-Assembler-Tutorial


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Niklas G. (erlkoenig) Benutzerseite


Bewertung
12 lesenswert
nicht lesenswert
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 :)

: Bearbeitet durch User
Beitrag #5998633 wurde von einem Moderator gelöscht.
von PSblnkd (Gast)


Bewertung
-15 lesenswert
nicht lesenswert
@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

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
12 lesenswert
nicht lesenswert
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.

von Wilhelm M. (wimalopaan)


Bewertung
9 lesenswert
nicht lesenswert
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.

von Walter T. (nicolas)


Bewertung
1 lesenswert
nicht lesenswert
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.

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
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...

von Roland F. (rhf)


Bewertung
-4 lesenswert
nicht lesenswert
Hallo
Niklas G. schrieb:
> und würde mich über Feedback hier im Thread freuen.

Vielen Dank für deine Arbeit. Ich persönlich halte allerdings ein 
weitere englische Anleitung zur Assemblerprogrammierung von 
ARM-Prozessoren für überflüssig. Für mich ist deine Arbeit daher leider 
nutzlos.

https://azeria-labs.com/writing-arm-assembly-part-1/
Youtube-Video "Assembly Language Tutorial"
Youtube-Video "ARM Assembly Language Tutorial - Part 1 - Setup ARM Tools"
http://infocenter.arm.com/help/topic/com.arm.doc.dui0068b/DUI0068.pdf
http://www.peter-cockerell.net/aalp/html/frames.html
u.s.w.

rhf

von Gerd (Gast)


Bewertung
-5 lesenswert
nicht lesenswert
Ja danke ganz nett und interessant.
Bin trotzdem der Meinung dass Asm bei den 8Bittern viel besser 
aufgehoben ist.

von Bernd (Gast)


Bewertung
0 lesenswert
nicht lesenswert
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

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
4 lesenswert
nicht lesenswert
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.

von Markus M. (adrock)


Bewertung
0 lesenswert
nicht lesenswert
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.

: Bearbeitet durch User
von Christoph db1uq K. (christoph_kessler)


Bewertung
1 lesenswert
nicht lesenswert
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.

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
2 lesenswert
nicht lesenswert
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 :)

von Christoph db1uq K. (christoph_kessler)


Bewertung
0 lesenswert
nicht lesenswert
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?

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
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€.

von Christoph db1uq K. (christoph_kessler)


Bewertung
0 lesenswert
nicht lesenswert
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.

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
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 ;-)

von Mistel (Gast)


Bewertung
2 lesenswert
nicht lesenswert
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

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
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...

von Christoph db1uq K. (christoph_kessler)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Danke für das Tutorial, ich habe es mir ausgedruckt und geheftet. Wer es 
auch lieber in Papierform hat, hier das PDF.

Der Nucleo446 sieht gut aus, bei Conrad derzeit sogar etwas billiger 
(17,99€ im Laden) als Reichelt. Jedenfalls bei Händlern weit verbreitet.

Die Datenblatt-Links speziell zu diesem Controller:

PM0214 Programming manual
https://www.st.com/content/ccc/resource/technical/document/programming_manual/6c/3a/cb/e7/e4/ea/44/9b/DM00046982.pdf/files/DM00046982.pdf/jcr:content/translations/en.DM00046982.pdf

Zum Mikrocontroller STM32F446
https://www.st.com/en/microcontrollers-microprocessors/stm32f446.html
->Resources->Technical Literature->Datasheet.

jeweils über 200 Seiten, das werde ich nicht ausdrucken.

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
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!

von Nop (Gast)


Bewertung
0 lesenswert
nicht lesenswert
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

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
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.

von Christoph db1uq K. (christoph_kessler)


Bewertung
0 lesenswert
nicht lesenswert
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.

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
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...

von Janvi (Gast)


Bewertung
0 lesenswert
nicht lesenswert
> 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 ...

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Bewertung
0 lesenswert
nicht lesenswert
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?

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
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 :)

von W. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Danke! Das hat bestimmt Tage gekostet.

(Muss aber auch gestehen, dass es mir auf deutsch lieber wäre).

von Christoph db1uq K. (christoph_kessler)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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.

: Bearbeitet durch User
von Willi S. (willi_s)


Bewertung
-2 lesenswert
nicht lesenswert
... 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 ...

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
2 lesenswert
nicht lesenswert
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.

von Volker A. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
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?)

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
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_scripts
https://www.mikrocontroller.net/articles/ARM-ASM-Tutorial#Improved_vector_table

Volker 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

von Volker A. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
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.

von vasx (Gast)


Bewertung
0 lesenswert
nicht lesenswert
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
   rem   Assembler + Linker
   arm-none-eabi-as -g ram_variables_demo.s -o ram_variables_demo.o 
   arm-none-eabi-ld ram_variables_demo.o -o ram_variables_demo.elf -Ttext=0x08000000 -Tdata=0x20000000 
   
   rem   Flashen via ST-LINK
   openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c "program ram_variables_demo.elf verify reset exit"

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.

von Niklas Gürtler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
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...

von Niklas Gürtler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Du könntest auch mal versuchen das Programm via GDB zu flashen (OpenOCD 
als GDB-Server), der ist da vielleicht cleverer.

von vasx (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Niklas Gürtler schrieb:
> Und was noch?


Der Aufruf

  > openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c 
"program linker_skript_demo_01.elf verify reset exit"


liefert:
xPack OpenOCD, 64-bit Open On-Chip Debugger 0.10.0+dev (2019-07-17-11:28)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
WARNING: interface/stlink-v2.cfg is deprecated, please switch to interface/stlink.cfg
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
Info : clock speed 1000 kHz
Info : STLINK V2J29M18 (API v2) VID:PID 0483:374B
Info : Target voltage: 3.272871
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : Listening on port 3333 for gdb connections
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08000008 msp: 0x20005000
** Programming Started **
Info : device id = 0x20036410
Info : flash size = 128kbytes
Warn : no flash bank found for address 0x20000000
** Programming Finished **
** Verify Started **
Error: checksum mismatch - attempting binary compare
** Verify Failed **
shutdown command invoked

Ich werde mich mal zwischen den Feiertagen mit dem Thema Linker-Skripte 
näher befassen. Vielen Dank erstmal!

von vasx (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Sorry, der Aufruf lautet

> openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c "program 
ram_variables_demo.elf verify reset exit"

von vasx (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Folgendes etwas umständliches Verfahren funktioniert jetzt (ohne Linker 
Skript)


Erstmal die beteiligten Dateien



ram_variables_demo.s (wie im Tutorial)
   // ***   ram_variable_demo.s   ***
   
   
   .syntax unified
   .cpu cortex-m3
   .thumb
   

   .word 0x20000400                   // startwert sp
   .word 0x080000ed                   // adresse reset handler
   .space 0xe4
   

   // data segment ->  sram
   .data                              
      var1:
            .space 4                  // Reserve 4 bytes for memory block “var1”
      var2:
            .space 1                  // Reserve 1 byte for memory block “var2”
   
   
   // code segment ->  flash rom
   .text                              
             
            ldr r0, =var1             // Get address of var1
            ldr r1, =0x12345678
            str r1, [r0]              // Store 0x12345678 into memory block “var1”

            ldr r1, [r0]              // Read memory block “var1”
            and r1, #0xff             // Set bits 8..31 to zero
            ldr r0, =var2             // Get address of var2
            strb r1, [r0]             // Store a single byte into var2

            b .   


build.bat
   rem  ***   build.bat   ***
   
   rem Assembler + Linker
   arm-none-eabi-as -g ram_variables_demo.s -o ram_variables_demo.o 
   arm-none-eabi-ld ram_variables_demo.o -o ram_variables_demo.elf -Ttext=0x08000000 -Tdata=0x20000000
   
   rem Flashen (Vrsg.: OpenOCD als GDB Server läuft)
   arm-none-eabi-gdb --eval-command="target remote localhost:3333" --ex="load" --ex="detach" ram_variables_demo.elf

   pause



openocd_gdb_server.bat
   rem  ***   openocd_gdb_server.bat   ***

   rem  OpenOCD als GDB Server starten (GDB: Debugger)
   rem  ->  Listening on Port 3333 for gdb Connections ... 
   openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg



gdb_debug.bat
   rem  ***   gdb_debug.bat   ***
   
   rem  Neues Terminal Fenster öffnen um eine GDB Session zu starten ...
   rem  GDB kommandos eingeben ...
   arm-none-eabi-gdb  --eval-command="target remote localhost:3333" ram_variables_demo.elf


Ablauf:

openocd_gdb_server.bat starten
build.bat

Alles schliessen

openocd_gdb_server.bat wieder starten
gdb_debug.bat  zum Debuggen

Fertig

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
So, habe es bei mir mal nachgestellt und es geht tatsächlich nicht 
direkt per OpenOCD. Habe daher einen entsprechenden Hinweis im Text 
ergänzt. Danke!

von Gernot S. (Firma: Ing. Gernot Schreiner) (leuchtspirale)


Bewertung
0 lesenswert
nicht lesenswert
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

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
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 :-)

von Tom (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Great tutorial!!!

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Bewertung
0 lesenswert
nicht lesenswert
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.

von Traveler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Thank you for writing this tutorial. It was exactly the low level, 
progressive content I needed.

von Tobias P. (hubertus)


Bewertung
0 lesenswert
nicht lesenswert
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.