Forum: Mikrocontroller und Digitale Elektronik Assembler oder C


von Paul L. (Gast)


Lesenswert?

Hallo! Was meint ihr, welche Sprache für Atmel-Mikrocontroller ich 
lernen sollte? Ich schwanke zwischen Assembler und C, wobei ich eher zu 
C tendiere, da es doch etwas einfacher zu verstehen ist :) Welche 
Sprache ist außerdem in Firmen gefragter?
Gruß, Paul
PS: Welche Programme bräuchte ich für C?

von Der E. (rogie)


Lesenswert?

Am besten ist es, wenn du beides lernst, da C ja letztendlich in 
Assembler übersetzt wird, kannst du dann auch lernen, wie der Compiler 
gewisse Sachen übersetzt.

Für die AVR's reicht das AVR- Studio, da kann man auch C bzw. C++ mit 
einbinden.

von Reinhard Kern (Gast)


Lesenswert?

Paul L. schrieb:
> Welche Sprache ist außerdem in Firmen gefragter?

Hallo,

naturgemäss ist das proportional zur Schwierigkeit: C ist gefragter als 
Basic, und Assembler ist gefragter als C. Aber als professioneller 
mC-Entwickler ist mindestens C UND Assembler nötig.

Gruss Reinhard

von oldmax (Gast)


Lesenswert?

Hi
lernen wirst du früher oder später beides. C halte ich bei weitem nicht 
für einfacher, wenn man es lernen muß. Ich hab mich jedenfalls da sehr 
schwer getan, aber das liegt vermutlich mal auch ein wenig an meinem 
Alter...
Assembler wird immer so als sehr schwierig hingestellt.. na ja, meine 
Erfahrung ist das nicht, aber ich hab schon den Z80 noch von Hand 
assembliert. Später zu Zeiten des PC hatte ich dann schon mit Borlands 
Turbo Pascal einen richtigen Assembler eingebaut. Und ja, es gab 
Programmteile, da war Turbo zu langsam und es mußten Routinen in 
Assembler sein. Ähnliches wirst du möglicherweise auch auf Controllern 
bekommen und dann ist es gut, wenn du dir mit Assembler behelfen kannst.
Gruß oldmax

von Paul L. (Gast)


Lesenswert?

Danke für eure Antworten! Ich werde erstmal mit C anfangen und dann mir 
mal Assembler angucken.
Kann ich auch mit Codeblocks als IDE und irgendeinem Compiler die 
hex-Datei erzeugen? Diese würde ich mit Ponyprog auf den µC flashen (der 
USB-Programmer war mir bisher zu teuer :D )
Gruß, Paul

von Falk B. (falk)


Lesenswert?

@  Paul L. (Gast)

>Hallo! Was meint ihr, welche Sprache für Atmel-Mikrocontroller ich
>lernen sollte? Ich schwanke zwischen Assembler und C, wobei ich eher zu
>C tendiere, da es doch etwas einfacher zu verstehen ist :)

Nimm C, damit kannst du deutlich mehr machen. Nicht nur auf dem AVR und 
Mikrocontrollern.

> Welche Sprache ist außerdem in Firmen gefragter?

C.

>PS: Welche Programme bräuchte ich für C?

AVR-Studio und WinAVR.

MfG
Falk

von Düsendieb (Gast)


Lesenswert?

Falk Brunner schrieb:
> Nimm C, damit kannst du deutlich mehr machen.

100% ACK

von Paul L. (Gast)


Lesenswert?

Noch eine Frage: Darf ich PONYPROG und den C-Compiler zu kommerziellen 
Zwecken benutzen, also die damit beschriebene µCs in Geräte einbauen und 
diese verkaufen?

von Ralf (Gast)


Lesenswert?

Falk Brunner schrieb:
> Nimm C, damit kannst du deutlich mehr machen. Nicht nur auf dem AVR und
> Mikrocontrollern.

Mit Assembler beginnen, ist schon nicht schlecht. Falls Du in C mal 
Fragen hast, kommen öfter solche Tipps: 'Da musst Du Dir mal das 
Assemblerlisting anschauen ...'

von Peter D. (peda)


Lesenswert?

C ist deutlich komfortabler, aber man hat es schwer, die Ressourcen 
vernünftig einzuteilen.
So verschwenderisch wie auf nem PC sollte man nicht programmieren.


Peter

von Programist (Gast)


Lesenswert?

Egal welche Sprach du brauchst Jahre um das alles richtig durchzuschauen 
und zu verstehen.Besonders, wenn du keinen guten Lehrer hast denn du 
immer fragen kannst.Im inet hilft dir keiner so richtig, es gibt ein 
paar tutorials ond Bücher, die decken aber nicht alle 
Kleinigkeiten.Deswegen ist das sehr schwer das selber zu lernen.Man 
braucht viel Zeit und Geduld.

von Sebastian H. (sh______)


Lesenswert?

Peter Dannegger schrieb:
> C ist deutlich komfortabler, aber man hat es schwer, die Ressourcen
> vernünftig einzuteilen.
> So verschwenderisch wie auf nem PC sollte man nicht programmieren.


Im Hobbybereich lässt sich doch meistens noch auf nen größeren µC 
umsteigen. Daher finde ich das mit den Ressourcen nicht so wirklich 
tragisch. Assembler braucht man daher im Normalfall wenig bis gar nicht 
:)

von Mirko H. (m1rk0)


Lesenswert?

Es ist manchmal praktisch, sich das Assemblerlisting anzusehen und 
einigermaßen zu verstehen, aber das ist etwas anderes, als Assembler 
richtig zu lernen um damit Programme von Grund auf zu entwickeln. Ich 
würde auf jeden Fall mit C anfangen und nach einiger Zeit mal einen 
Blick auf ein Einsteigertutorial zu Assembler und die Befehlsliste 
werfen, damit Du ungefähr weißt, was die Befehle so machen. Das hier ist 
sehr nett zum Schmökern (auch wenn der Autor noch von der alten Schule 
ist und meint, man solle erst richtig Assembler lernen): 
http://www.avr-asm-tutorial.net

Mirko

von Paul Lendtscheid (Gast)


Lesenswert?

Wie gesagt, ich fange mal mit C an und wenn ich das einigermaßen 
beherrsche Asembler.
Nochmal zurück zu meiner anderen Frage ;) Wisst ihr ob man Ponyprog und 
den AVR-GCC-Compiler aus WinAVR zu kommerziellen Zwecken nutzen darf?
Gruß, Paul

von user (Gast)


Lesenswert?

avr-gcc darf man komerziell benutzen

von Peter D. (peda)


Lesenswert?

Sebastian H. schrieb:
> Im Hobbybereich lässt sich doch meistens noch auf nen größeren µC
> umsteigen. Daher finde ich das mit den Ressourcen nicht so wirklich
> tragisch.

Nö, das ist schon sehr tragisch, wenn Du gedankenlos alle 10µs aufs LCD 
schreibst, schlimmstenfalls sogar im Interrupt. Dann läuft nämlich 
garnichts mehr.

Man sollte schon wissen, daß UART, LCD, printf, 64Bit, float usw. 
exorbitant teuer sind und daher nur so oft zu tun sind wie unbedingt 
nötig. Kein Mensch kann ein LCD alle 10ms neu ablesen.

Und es ist auch gut zu wissen, daß C default 16Bit (int) nimmt und man 
daher mit uint8_t Variablen (8Bit) die Rechenleistung quasi verdoppelt.
Also int nur dann nehmen, wenn man es auch braucht.


Peter

von Reinhard Kern (Gast)


Lesenswert?

Mirko Horstmann schrieb:
> aber das ist etwas anderes, als Assembler
> richtig zu lernen um damit Programme von Grund auf zu entwickeln.

Das ist ein Missverständnis! ein Programm nur in Assembler zu schreiben 
ist eher eine seltene Ausnahme, eine optimale Kombination besteht aber 
darin, Hardware-Zugriffe in Assembler zu programmieren und vom 
C-Hauptprogramm aus aufzurufen. Auch Interrupt-Service-Routinen schreibe 
ich lieber in Assembler, weil ich da Befehl für Befehl weiss, was da 
läuft - in C geht das schon auch, aber um Bescheid zu wissen über die 
relevanten Verzögerungen muss ich dann analysieren, was der C-Compiler 
draus gemacht hat, da bleibe ich lieber gleich beim Original. Ausserdem 
kann ich mich da nach besonderen Notwendigkeiten richten, beim 
C-Compiler ist der Eintriit in den Interrupt immer der gleiche.

Leider kommt das mangels Qualifikation aus der Mode, aber bisher ist 
eigentlich jedes existierende komplexe System in mehr als einer Sprache 
(mixed language) realisiert, auch DOS oder Windows. Einsprachige Systeme 
zu Lehrzwecken wie Pascal-Engine oder native Java-Prozessoren sind eher 
zurechtgequälte Exoten. Prozessoren die C direkt ausführen gibt es mit 
guten Gründen auch nicht, aber das führt hier dann doch zu weit.

Gruss Reinhard

von Programist (Gast)


Lesenswert?

Genau, deswegen sollte man zuerst assembler lernen.Dummerweise sind die 
Befehle und die Architektur anders bei verschieden Prozessoren.
Trotzdem, wenn du assembler richtig kannst, dann brauchst du nichts mehr 
zu lernen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Reinhard Kern schrieb:
> Leider kommt das mangels Qualifikation aus der Mode

Es kommt vor allem wegen des schlechten Aufwand-Nutzen-Verhältnisses
aus der Mode.

Was glaubst du, warum Cortex-M3 damit wirbt, dass man für das
Komplettsystem nicht mehr zwingend überhaupt den Assembler anfassen
muss?  Selbst Dinge, die traditionell immer noch in Assembler liefen
wie die Laufzeitinitialisierung oder eben Interrupts lassen sich dort
komplett in C abwickeln, und auch der Anteil an Inline-Assembler
(der als zur Entwicklungsumgebung bestehend betrachtet wird) ist
vergleichsweise gering.

Ich sehe das genauso wie Mirko: als Controller-Programmierer sollte
man sehr wohl den Assemblercode seiner Architektur lesen können
(über kurz oder lang, für den Einstieg selbst ist das nicht zwingend
nötig), aber deshalb muss man noch lange nicht in der Lage sein, ihn
auch selbst zu schreiben.  Das impliziert beispielsweise, dass man
nicht sämtliche Randbedingungen für die Operanden der einzelnen
Befehle im Kopf haben muss (Beispiel: beim AVR sind viele Operation
nur auf der oberen Hälfte der Register zulässig), da einem dieses
Wissen der Compiler abgenommen hat.

von Reinhard Kern (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> als Controller-Programmierer sollte
> man sehr wohl den Assemblercode seiner Architektur lesen können
> ..., aber deshalb muss man noch lange nicht in der Lage sein, ihn
> auch selbst zu schreiben.

also sozusagen als Read-Only-Programmierer :-)

Dass du keinen Assembler schreibst, heisst ja nicht, dass keiner 
gebraucht wird. Ich benutze ja auch Floating Point aus einer C-Library 
in der Überzeugung, dass die Leute, die das programmiert haben, einen 
optimalen Kompromiss aus Platzbedarf und Geschwindigkeit gefunden haben, 
und das natürlich in Assembler. M.a.W. du kannst drauf verzichten, 
Ahnung zu haben, weil du die Arbeit von Leuten benutzt, die die nötige 
Ahnung hatten.

Das ist als Arbeitsteilung auch vollkommen in Ordnung, rechtfertigt aber 
nicht die Verachtung, die heute der Assemblerprogrammierung als 
überflüssig und veraltet entgegengebracht wird, die beruht einfach auf 
Unkenntnis und Ignoranz. Wie glaubst du denn tragen Befehlserweiterungen 
wie SSE oder neue Floating Point Befehle bei PC-Prozessoren zur 
Leistungssteigerung bei? Durch Neukompilieren und dabei geschieht ein 
unfassbares Wunder?

Gruss Reinhard

von Mark B. (markbrandis)


Lesenswert?

Reinhard Kern schrieb:
> und Assembler ist gefragter als C.

Das halte ich für ein Gerücht. Es sei denn Du hast bessere Quellen als 
ich :-)

http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html

Auf die Schnelle mal z.B. auf monster.de oder ähnlichen Jobbörsen 
erhalte ich auch nicht den Eindruck, dass dort mehr Assembler-Entwickler 
als C-Entwickler gesucht würden.

von oldmax (Gast)


Lesenswert?

Hi
Immer wieder interessant, wie ihr Experten die Frage angeht.... Wer sich 
eine Programmiersprache im Selbststudium beibringt, wird's schwer haben, 
einen Job damit zu finden. Nach wie vor zählt da Ausbildung, sprich 
Studium. Mag sein, das es vielleicht Glückspilze gibt, die den 
Quereinstieg geschafft haben, aber das ist selten. Dann kommt es auch 
auf die "Bude" an, welcher Schwerpunkt den Programmierern (oder 
Bewerbern) abgefordert wird. Lassen sichdie Programme komplett in einer 
Hochsprache verfassen, wird wohl kaum ein Chef so dumm sein, 
Assemblerprofis dranzusetzen. Als ist die Hochsprache ein wichtiger 
Bestandteil in meinen Augen. Bringt der Bewerber dann auch noch 
Assembler mit, ist dies eine angenehme Zugabe und wäre für mich ein 
Bonus zur positiven Bewertung, auch wenn es scheint, das ich es nie dem 
Programmierer abfordere. Leider ist in vielen Ebenen des Managements 
dieses Verhalten abgängig und ich bin zu alt, um hier noch etwas 
bewirken zu können. Schnelle Ergebnisse sind gefragt. Die Anstrengungen 
eines Quereinsteigers, wen interessierts. Der Hobbyprogrammierer 
verliert womöglich das Pflichtenhet aus den Augen, weil hier und da eine 
Option dem Ganzen noch ein Sahnehäubchen aufsetzt....
Leider sterben die alten Unternehmer so langsam aus, die sowas noch 
geschätzt haben und stolz mit ihren Produkten dem Kunden ihre Ware 
präsentiert haben.
Was ich damit sagen will, es nutzt hier nicht, darüber zu diskutieren, 
ob Assembler Out ist. Was wird denn im Studium gefordert, das ist 
wichtig. Wenn der Prof. noch Wert auf eine saubere Assemblerstruktur 
legt, könnt ihr ihm zwar sagen, das ist nicht zeitgemäss, aber dann 
bekommt ihr wahrschenlich auch nicht den erwünschten Abschluss. Und das 
ist richtig so. Programmieren ist nicht das Lesen von Listings, sondern 
die Fähigkeit, eine Aufgabe in einer Art Anweisungsliste abarbeiten zu 
lassen. Egal, welche Sprache ihr sprecht, letztlich sind es Bits, die 
ein µC abklappert... den interessiert es einen Sch... ob die Quelle C 
oder Assembler heißt.
Gruß oldmax

von Martin (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Nö, das ist schon sehr tragisch, wenn Du gedankenlos alle 10µs aufs LCD
> schreibst, schlimmstenfalls sogar im Interrupt. Dann läuft nämlich
> garnichts mehr.

Aber wenn man das in Assembler macht, ist das okay, gell?

> Man sollte schon wissen, daß UART, LCD, printf, 64Bit, float usw.
> exorbitant teuer sind und daher nur so oft zu tun sind wie unbedingt
> nötig. Kein Mensch kann ein LCD alle 10ms neu ablesen.

In Assembler sind all diese Dinge dann richtig billig. kopfschüttel

> Und es ist auch gut zu wissen, daß C default 16Bit (int) nimmt und man
> daher mit uint8_t Variablen (8Bit) die Rechenleistung quasi verdoppelt.
> Also int nur dann nehmen, wenn man es auch braucht.

Auf Acht-Bittern wie hier verwendet. Als generelle Regel ist es 
eigentlich eher andersrum: normalerweise ist int der schnellste 
Integer-Typ.

von narf (Gast)


Lesenswert?

Martin schrieb:
> Auf Acht-Bittern wie hier verwendet. Als generelle Regel ist es
> eigentlich eher andersrum: normalerweise ist int der schnellste
> Integer-Typ.

richtig

wenn man bei AVRs und anderen 8bittern bleibt...
ich schwenke gerade richtung M0 und M3 ..
da ist mit ein int lieber als ein uint8_t

zumal M0 günstiger zu haben sind als so manche AVRs ...( ab 16k flash ca 
.. )
zudem mehr features liefern und schneller sind wenn man es brauch
( max 50mhz und schnellere pipeline + DMA usw ... )

ich habe das thema AVR 8bitter für MICH abgehakt
die dinger haben keine wirkliche berechtigung
es sei denn man brauch nur nen 8pinner wie nen tiny ..
aber ansonst ... M0   wenns mehr bedarf M3

von Rolf Magnus (Gast)


Lesenswert?

Martin schrieb:
>> Man sollte schon wissen, daß UART, LCD, printf, 64Bit, float usw.
>> exorbitant teuer sind und daher nur so oft zu tun sind wie unbedingt
>> nötig. Kein Mensch kann ein LCD alle 10ms neu ablesen.
>
> In Assembler sind all diese Dinge dann richtig billig.

Nein, aber da wird der Aufwand nicht so versteckt. Schreib mal eine 
float-Multiplikation in C hin und dann eine in Assembler. Der 
C-Programmierer, der keine Ahnung von Assembler hat, schreibt das eben 
einfach mal so hin und wundert sich, warum sein µC so furchtbar langsam 
und sein Programm so riesig ist. Dem Assemblerprogrammierer kann das so 
nicht passieren. Der wird, wenn es nur irgendwie geht, versuchen, das 
anders zu lösen, was auf einem AVR meist auch der richtige Ansatz ist.

>> Und es ist auch gut zu wissen, daß C default 16Bit (int) nimmt und man
>> daher mit uint8_t Variablen (8Bit) die Rechenleistung quasi verdoppelt.
>> Also int nur dann nehmen, wenn man es auch braucht.
>
> Auf Acht-Bittern wie hier verwendet. Als generelle Regel ist es
> eigentlich eher andersrum: normalerweise ist int der schnellste
> Integer-Typ.

So ist es zumindest mal gedacht gewesen. Aber seit C99 nimmt man da 
einfach int_fast8_t und bekommt einen möglichst schnellen Typ, dessen 
Breite aber auch 8 Bit betragen darf.

von Peter D. (peda)


Lesenswert?

Martin schrieb:
> In Assembler sind all diese Dinge dann richtig billig. kopfschüttel

Auch Kopfschüttel.
Vielleicht mal Gehirn einschalten?

Rolf hat nun extra für Dich erklärt, wie das gemeint ist.


Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Reinhard Kern schrieb:
> Dass du keinen Assembler schreibst, heisst ja nicht, dass keiner
> gebraucht wird.

Das habe ich doch gar nicht behauptet.  Von mir dürfte auch das eine
oder andere inline-Assembler-Makro in der avr-libc sein, und nicht
zuletzt ist von mir auch das Assembler-Demo.  Allerdings bin ich am
Ende des Assembler-Demos (bei dem ich mir Mühe gegeben hatte, ein
wenigstens halbwegs realistisches Beispiel zu finden, bei dem der
Einsatz von Assemblercode nicht nur an den Haaren herbeigezogen ist)
dann zu dem (damals durchaus auch für mich überraschenden) Schluss
gekommen, dass bereits der nächst modernere Controller (ATtiny25 statt
ATtiny13) den ganzen Aufwand wieder überflüssig gemacht hat, denn dort
ließ sich die gleiche Aufgabe dank der besseren Hardware komplett in C
erledigen.

Mir ging es darum, dass der durchschnittliche Anwendungsprogrammierer
heutiger Controller es keineswegs mehr gewissermaßen als Einstiegs-
Voraussetzungen mitbringen muss, dass er die Maschine auch "zu Fuß"
programmieren kann.  Er kann sich erst einmal produktiveren Dingen
widmen, und bekommt auf diese Weise (so er natürlich programmieren
kann ;-) seine eigentliche Aufgabe schneller gelöst, als wenn er
erstmal sämtliche Fallen der jeweiligen Maschine auf Assemblerebene
intus haben muss.  Zweifellos ist es über kurz oder lang (spätestens,
wenn es was zu optimieren gibt) dann hilfreich, wenn er auf dem Weg
zum Ziel zumindest das Verständnis für den Assembler-/Maschinencode
allmählich bekommt, sodass er den vom Compiler generierten Code deuten
kann.  Aber um all die hässlichen Details mag sich erstmal der
Compiler kümmern, dafür ist er geschrieben worden.

narf schrieb:
> ich schwenke gerade richtung M0 und M3 ..
> da ist mit ein int lieber als ein uint8_t

Und wenn du's richtig machen willst, benutzt du einen uint_fast8_t,
wenn der Wert nur zwischen 0 und 255 liegt, du aber eine möglichst
schnelle Variante der Variablen brauchst.  Das ist dann auf dem ARM
halt ein 32-bit-Typ, auf dem AVR jedoch platz- und zeitsparend ein
8-bit-Typ.

von oldmax (Gast)


Lesenswert?

Hi
Seid ihr immer noch nicht fertig ? Manchmal hab ich das Gefühl, nur weil 
man Assembler nicht kann, wird hier auf Teufel komm raus C 
beschworen....  Zur Erinnerung:
>Hallo! Was meint ihr, welche Sprache für Atmel-Mikrocontroller ich
>lernen sollte? Ich schwanke zwischen Assembler und C, wobei ich eher zu
>C tendiere, da es doch etwas einfacher zu verstehen ist :) Welche
>Sprache ist außerdem in Firmen gefragter?
>Gruß, Paul
 Da steht nix von M0 oder gar M3 und da ist auch nicht gefragt, was 
brauch ich überhaupt nicht lernen... ! Er hat eine Tendenz, ja und 
früher oder später wird er die ersten kleinen Routinen in Assembler 
schreiben wollen oder müssen. Wie auch immer, Assembler bring den 
Programmierer näher an die Hardware. Was ist daran schlimm ? Ich habe 
bspw. von C nicht viel Ahnung, gut, damit kann ich leben. Wenn nicht, 
mache ich C nicht schlecht, sondern lern diese Sprache eben. Trotzdem 
kann ich doch hinterher immer noch sagen:" Nee, ich bleib bei 
Assembler..."
Paul will lernen, was ist falsch, erst das Alphabet und dann die Wörter 
und Sätze zu lernen? Trotzdem, es gab auch gute Ergebnisse mit anderen 
Methoden.
In der Mathematk ist es ähnlich, alle fangen bei den Grundrechenarten 
an, nicht beim Wurzelziehen.
Also, hört endlich auf mit dem Verdammen von Sprachbereichen. Es ist 
viel wichtiger, Probleme und Aufgaben analysieren zu können. Die Sprache 
ist letztlich das Werkzeug, um zum Ziel zu gelangen.
Gruß oldmax

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

oldmax schrieb:
> Manchmal hab ich das Gefühl, nur weil
> man Assembler nicht kann, wird hier auf Teufel komm raus C
> beschworen.

Du darfst deine Unterstellung gern für dich behalten und meinen
Beitrag zumindest lesen.  Dann wüsstest du, dass dem ganz gewiss
nicht so ist.

Ich könnte es auch krass formulieren: "Wer Assembler wirklich kann,
nimmt lieber C."

von Ich (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Und es ist auch gut zu wissen, daß C default 16Bit (int) nimmt und man
> daher mit uint8_t Variablen (8Bit) die Rechenleistung quasi verdoppelt.

Das stimmt so nicht ganz, der Typ int ist für unterschiedliche Systeme 
auch schon mal unterschiedlich definiert.

Diese System-abhängige Definition ist aber erst recht ein Argument dafür 
die uintN_t Typen zu benutzen, denen sieht man auf den ersten Blick auch 
gleich an wie breit sie sind.

Das einzige was mir dazu im AVR-Studio "fehlt" ist, dass diese Typen 
nicht im Syntax-Highlighting markiert werden, weil es eben nur Defines 
sind.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ich schrieb:

> Das einzige was mir dazu im AVR-Studio "fehlt" ist, dass diese Typen
> nicht im Syntax-Highlighting markiert werden, weil es eben nur Defines
> sind.

Nein, es sind typedefs.  Aber so weit muss man gar nicht gehen, da der
Suffix _t ein de-fakto-Standard für definierte Datentypen ist, kann
man diese Konvention bedenkenlos dazu benutzen, einen entsprechenden
Bezeichner im Syntaxhighlighting als Datentyp auszuzeichnen.

von Peter D. (peda)


Lesenswert?

Jörg Wunsch schrieb:
> Und wenn du's richtig machen willst, benutzt du einen uint_fast8_t,
> wenn der Wert nur zwischen 0 und 255 liegt, du aber eine möglichst
> schnelle Variante der Variablen brauchst.  Das ist dann auf dem ARM
> halt ein 32-bit-Typ, auf dem AVR jedoch platz- und zeitsparend ein
> 8-bit-Typ.

Welchen Wert hat uint_fast8_t bei einem Unterlauf?
Kann ich immer mit 255 vergleichen?


Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:

> Welchen Wert hat uint_fast8_t bei einem Unterlauf?

UINT_FAST8_MAX

> Kann ich immer mit 255 vergleichen?

Natürlich nicht.  Das kann nur mit fest vorgegebenen Bitbreiten gehen,
also uint8_t (UINT8_MAX muss letztlich immer 255 sein).

von Stapelfahrer (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Welchen Wert hat uint_fast8_t bei einem Unterlauf?
> Kann ich immer mit 255 vergleichen?

Aus Neugier hab ich kurz ins Header-File (stdint.h) geschaut - hab noch 
nie einen "fast"-Typen verwendet. Da gibt's auch defines für den 
Wertebereich, womit sich das Problem entschärfen lässt:
1
#define INT_FAST8_MAX INT8_MAX
2
#define INT_FAST8_MIN INT8_MIN
3
#define UINT_FAST8_MAX UINT8_MAX

von Bernd N (Gast)


Lesenswert?

>> Ich könnte es auch krass formulieren: "Wer Assembler wirklich kann,
>> nimmt lieber C."

Da ist was dran :-) aber wer daraus schlußfolgert das es in C nicht 
krass zugeht der liegt auch falsch :-)

Die Konsequenz daraus kann nur sein, geb dir die volle Dröhnung :-) 
C+ASM.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Bernd N schrieb:
> aber wer daraus schlußfolgert das es in C nicht
> krass zugeht der liegt auch falsch :-)

Das würde ich auch nie behaupten. ;-)  C ist keine gute Programmier-
sprache, aber ein relativ brauchbarer Kompromiss, für den sich die
Programmierergemeinde mittlerweile ausreichend viel Knoffhoff
angeeignet hat, um um die Klippen herum zu schiffen und trotzdem
einigermaßen produktiv damit arbeiten zu können.

von Peter D. (peda)


Lesenswert?

Bernd N schrieb:
> Da ist was dran :-) aber wer daraus schlußfolgert das es in C nicht
> krass zugeht der liegt auch falsch :-)

Stimmt, ich hab ne ganze Weile gebraucht, das volatile-Konzept des GCC 
zu verstehen.
Das Problem ist, daß der GCC ständig versucht, durch unerwartetes 
Inlining vermeintlich sichere Zugriffsfunktionen auszuhebeln.
Volatile darf man daher nie einsparen (aber auch nicht mit der Gießkanne 
ausschütten).

Und der GCC vertauscht gerne mal die Reihenfolge von Operationen, auch 
wenn dadurch mehr Code entsteht.


Peter

von Uwe (Gast)


Lesenswert?

Ich finde man sollte sich mit dem Mikrocontroller beschäftigen. Also 
CPU, Register, Speicherbusse, Peripherie, Stack, grundoperationen die 
auf jeder CPU möglich sind wie mov(e.l), and, or, add, inc, dec, bra bzw 
jmp jnz jz usw. Grundprinzipien der Programmierung wie Sprungtabellen 
Zahlensysteme usw.
Danach oder davor Hochsprache ist egal aber Zahlensysteme und logische 
Operationen kommt man nicht drum herum und es lassen sich viele Sachen 
einfacher verstehen wenn man weiß wie der Mikrocontroller intern 
aufgebaut ist.

von Ralf (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Stimmt, ich hab ne ganze Weile gebraucht, das volatile-Konzept des GCC
> zu verstehen.

Hätte von mir sein können!
Allerdings habe ich es immer noch nicht begriffen ... volatile- 
Konzept ???

Ich versuch es immer mal wieder, wenn ich in Assembler hänge. Komme aber 
immer wieder zurück.

Hier mal ein Beispiel (jetzt nichts Sinnvolles):
1
#include <avr/io.h>
2
3
uint8_t x=1;
4
5
int main()
6
{
7
 DDRA=0xFF;
8
 PORTA=0x00;
9
10
 UCSR0A|= (1 << MPCM0);
11
12
 while (1)
13
 {
14
  PORTA=x;
15
  x=x << 1;
16
 }
17
 return 0;
18
}
was macht der Compiler draus? Erstmal 182 Bytes Code. Das toleriere ich. 
Aber 2 Bytes Daten?? Deklariere ich 'x' als uint16_t sind's auch 2 
Bytes.
Die Konstruktion 'UCSR0A|= (1 << MPCM0);' ist (bei allen?) so nicht 
zulässig. Datenblatt:
'Do not use Read-Modify-Write instructions (SBI and CBI) to set or clear 
the MPCM bit. The MPCM bit shares the same I/O location as the TXC Flag 
and this might accidentally be cleared when using SBI or CBI 
instructions.'
Doch was steht im Assembler-Code?
1
 UCSR0A|= (1 << MPCM0);
2
  a4:  58 9a         sbi  0x0b, 0  ; 11
Müsste der Compiler das nicht wissen? Ich schaue doch auch nicht nach, 
was mir der C++Compiler auf dem PC als Assemblercode gebastelt hat.

von Ich (Gast)


Lesenswert?

>'Do not use Read-Modify-Write instructions (SBI and CBI) to set or
>clear the MPCM bit.

Mal davon ab das der Compiler sowas nicht wissen soll.
SBI und CBI sind doch gerade keine read-modify-write Befehle, oder?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ralf schrieb:

> Hier mal ein Beispiel (jetzt nichts Sinnvolles):

Genau, und wie bei allen nicht sinnvollen Beispiele kommt auch nichts
Sinnvolles raus. ;-)  Sprich: nicht sinnvolle Beispiele taugen
absolut nicht für einen sinnvollen Vergleich.

> was macht der Compiler draus? Erstmal 182 Bytes Code. Das toleriere ich.

Wovon der größte Teil ohnehin die Interrupttabelle sein dürfte
(du schreibst den Controller nicht dazu) plus der Startup-Code,
also "Einmalkosten".

> Aber 2 Bytes Daten?? Deklariere ich 'x' als uint16_t sind's auch 2
> Bytes.

Der Compiler macht 1 Byte draus, der Linker fügt dann offenbar noch
ein Padding dazu.  Letztlich also völlig irrelevant, denn den
Controller hast du sowieso mit 512 Byte oder so SRAM gekauft, du
kannst Atmel den Rest nicht zurückgeben. ;-)

> Die Konstruktion 'UCSR0A|= (1 << MPCM0);' ist (bei allen?) so nicht
> zulässig.

"Doctor, it hurts when I do this." — "Don't do this."

> Doch was steht im Assembler-Code?

Das, was du dem Compiler aufgetragen hast.

> Müsste der Compiler das nicht wissen?

Nein.  Selbst wenn er es wüsste, könnte er dir bestenfalls deinen
Code um die Ohren schmeißen und sagen: "Don't do this."  Du hast die
Bemerkung im Datenblatt nämlich völlig falsch verstanden: du sollst
da keine read-modify-write-Operation verwenden, und es ist dabei
völlig schnuppe, ob diese ein SBI ist oder ein explizites Lesen des
Registers, Modifizieren des Werts und Zurückschreiben: beide diese
Operationen haben das gleiche Problem.  Du darfst also einfach kein
"|=" darauf verwenden (auch nicht die ausgeschriebene Langform),
sondern du sollst bitteschön schreiben:
1
UCSR0A = (1 << MPCM0) /* | andere Bits hier, die du setzen willst */;

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ich schrieb:

> SBI und CBI sind doch gerade keine read-modify-write Befehle, oder?

Doch, sind sie, nur halt atomar als ein Befehl (der in zwei Takten
abläuft).

von Ralf (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Wovon der größte Teil ohnehin die Interrupttabelle sein dürfte
> (du schreibst den Controller nicht dazu) plus der Startup-Code,
> also "Einmalkosten".

Eben. Deshalb geht das in Ordnung.

Jörg Wunsch schrieb:
> Der Compiler macht 1 Byte draus, der Linker fügt dann offenbar noch
> ein Padding dazu.  Letztlich also völlig irrelevant, denn den
> Controller hast du sowieso mit 512 Byte oder so SRAM gekauft, du
> kannst Atmel den Rest nicht zurückgeben. ;-)

Also ich hab' hier einen Tiny2313: 128Bytes RAM
In meinem aktuellen Projekt (Assembler) sollen dort ein paar 
Zeichenketten abgelegt werden. Und natürlich noch anderes Zeug. Jetzt 
muss ich aufpassen, dass mir der SP da nicht reinhaut. Und wenn ich das 
jetzt in C mache, haut mir der Compiler noch lustig ein paar Bytes mehr 
rein?

Jörg Wunsch schrieb:
> UCSR0A = (1 << MPCM0) /* | andere Bits hier, die du setzen willst */;

Das ist eben was völlig anderes. Ich will ja nicht irgendwelche Bits 
setzen, sondern nur eins ändern. Der Rest soll so bleiben. Also: erstmal 
einlesen, dann ändern, dann wieder schreiben. Ich hätte den Compiler für 
so schlau gehalten ...

von Simon H. (simi)


Lesenswert?

Jörg Wunsch schrieb:
>> Müsste der Compiler das nicht wissen?
>
> Nein.  Selbst wenn er es wüsste, könnte er dir bestenfalls deinen
> Code um die Ohren schmeißen und sagen: "Don't do this."

... Und dann müsste der Compiler auch verhindern, dass Du z.B. den PLL 
so konfigurierst, dass - in Verbindung mit verwendeten Quartz - die 
Anzahl Wait-States, die Du im Flash-Controller konfiguriert hast, nicht 
mehr ausreichen.

Uwe schrieb:
> Ich finde man sollte sich mit dem Mikrocontroller beschäftigen.

Genau. Und dazu ist es sicher sinnvoll, ein bisschen was über Assembler 
gelesen zu haben. Aber eigentlich ist Assembler viel einfacher als C, 
zumindest, was das grundlegende Verständnis betrifft. Es ist eine sehr 
primitive Sprache, deren Regeln man im Nu gelernt hat.

Wichtig finde ich, wie oben zitiert, dass die Arbeitsweise des Prozis 
verstanden wird, und dass man versteht, wie C und Assembler 
zusammenhängen. Also nicht erst Assembler lernen, und dann C lernen, 
auch nicht C lernen, und dann Assembler lernen, sondern

- lernen, wie der Prozi arbeitet (Assembler-Befehle lernen sich dabei 
gratis mit)
- lernen, C zu programmieren
- lernen, wie C in Assembler umgesetzt wird, wie die Arbeitsweise des 
Prozis von C benutzt wird etc.

von Ralf (Gast)


Lesenswert?

Simon Huwyler schrieb:
> ... Und dann müsste der Compiler auch verhindern, dass Du z.B. den PLL
> so konfigurierst, dass - in Verbindung mit verwendeten Quartz - die
> Anzahl Wait-States, die Du im Flash-Controller konfiguriert hast, nicht
> mehr ausreichen.

Na gut...
Irgendwo muss da sicher eine Grenze sein. Aber, Beispiel MPCM: Wer 
nichts von Assembler versteht, könnte im Datenblatt nachsehen und 
meinen: 'sbi?, cbi? - ich mach das in C'. Wer soll den Fehler finden?

von Peter D. (peda)


Lesenswert?

Ralf schrieb:
> Allerdings habe ich es immer noch nicht begriffen ... volatile-
> Konzept ???

Wenn mans kann, ist es ganz einfach:

Alle Variablen zum Datenaustausch zwischen Main und Interrupt müssen im 
Main immer volatile zugegriffen werden!

Bequem geht das mit einem Macro:
1
#include <avr/interrupt.h>
2
3
// force access of interrupt variables
4
#define IVAR(x)         (*(volatile typeof(x)*)&(x))
5
6
7
uint8_t val;
8
9
ISR( INT0_vect )
10
{
11
  TCNT0 = val;
12
}
13
14
int main( void )
15
{
16
  for(;;){
17
    IVAR(val) = ADCH;           // volatile access needed !
18
  }
19
}

Peter

von Ich (Gast)


Lesenswert?

Jörg Wunsch schrieb:
>> SBI und CBI sind doch gerade keine read-modify-write Befehle, oder?
>
> Doch, sind sie, nur halt atomar als ein Befehl (der in zwei Takten
> abläuft).

Okay, hab damit ja kein Problem soweit, das muss halt in C schon richtig 
da stehen.

Aber wo steht sowas? Aus der AVR Instruction-Set Beschreibung bin ich an 
der Stelle gerade soweit nicht schlau geworden.
Weil der Zugriff atomar auf ein Bit passiert habe ich bisher angenommen 
das die anderen Bits dabei nicht geschrieben werden.

von Ralf (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Alle Variablen zum Datenaustausch zwischen Main und Interrupt müssen im
> Main immer volatile zugegriffen werden!

Sowas hab' ich mir schon gedacht. 'volatile' kenne ich aus der Zeit, wo 
man noch heimlich sich Werte direkt aus der Hardware geholt hat. (Damit 
der Compiler die Variable nicht wegoptimiert)
Aber bei Softwarezugriffen? Global definieren. Sollte das nicht reichen?

Nochmal 2 Bytes für uint8_t:
Hab noch mal gespielt:
uint8_t x=1; -> ergibt 2 Bytes
uint8_t x=0; -> ergibt 1 Byte
uint8_t x;   -> ergibt 1 Byte
  = verwunderlich bis ärgerlich

von Simon H. (simi)


Lesenswert?

Ralf schrieb:
> Aber, Beispiel MPCM: Wer
> nichts von Assembler versteht, könnte im Datenblatt nachsehen und
> meinen: 'sbi?, cbi? - ich mach das in C'.

Kurz vorweggenommen: Ich kenne AVR nicht wirklich. Aber so wie ich das 
verstehe, ist das Problem nicht sbi/cbi per se. Sondern eben das 
Konstrukt des Read-Modify-Write. Da offenbar dieses Bit irgendwie 
hardwaremässig noch mit was anderem verknüpft ist, sind genau bei diesem 
Bit solche Dinge gefährlich. Das hat nichts mit dem Assemblerbefehl, 
sondern mit dessen hardwaremässiger Auswirkung zu tun.
(Erinnert mich irgendwie an die Krüppel-Ports der PICs - lang ist's her)

Und in C siehst Du hier genau dasselbe, wie in Assembler. Nämlich, dass 
dieses Bit gesetzt wird (der Aspekt des Read-Modify-Write ist hier sogar 
noch deutlicher). Alleine aufgrund der Tatsache, dass im Datasheet 
explizit sbi und cbi erwähnt sind, macht den Fehler offensichtlicher. 
Dazu musst Du aber eigentlich auch gar nicht wissen, was die tun.

Aber auf die Finger klopfen darf C Dir da auf keinen Fall. Denn C hat 
nur einen Job: Dem Prozi genau diese Anweisungen zu geben, die dem 
C-Code entsprechen. Wenn der C-Code in sich nicht stimmig ist, muss er 
moosen. Aber wenn korrekter C-Code etwas vorschreibt, das die Peripherie 
nicht zulässt, geht das den Compiler nichts an. Darf ihn nichts angehen.

von Ralf (Gast)


Lesenswert?

@Simon Huwyler
Die 'Aufgabenverteilung' zwischen Programmierer, Compiler, Linker und 
wie sie alle heißen, ist vielleicht verbesserungswürdig, aber manchmal 
eben einfach so festgelegt, weil es nicht anders geht.

Wichtig ist mir hier:
Paul L. schrieb:
> Hallo! Was meint ihr, welche Sprache für Atmel-Mikrocontroller ich
> lernen sollte? Ich schwanke zwischen Assembler und C, wobei ich eher zu
> C tendiere, da es doch etwas einfacher zu verstehen ist :) Welche
> Sprache ist außerdem in Firmen gefragter?
> Gruß, Paul

Wer mit C anfängt, kommt irgendwann an so einen Punkt. Der Quelltext ist 
syntaktisch o.K., das Programm muss eigentlich laufen. Im Datenblatt 
werden ein paar Assemblerbefehle erwähnt, die man nicht versteht und um 
die man sich doch eigentlich nicht kümmern muss, weil man ja in C 
programmiert. Schöner Mist.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ralf schrieb:

>> Der Compiler macht 1 Byte draus, der Linker fügt dann offenbar noch
>> ein Padding dazu.  Letztlich also völlig irrelevant, denn den
>> Controller hast du sowieso mit 512 Byte oder so SRAM gekauft, du
>> kannst Atmel den Rest nicht zurückgeben. ;-)
>
> Also ich hab' hier einen Tiny2313: 128Bytes RAM

Der kennt weder MPCM0 noch UCSR0A.

> Und wenn ich das
> jetzt in C mache, haut mir der Compiler noch lustig ein paar Bytes mehr
> rein?

Nein.  Erstens ist es nicht der Compiler, sondern der Linker, und
zweitens ist das Padding: du bekommst nur maximal ein Byte mehr
in den .data-Bereich, weil da irgendwo ein

. = ALIGN (0x2)

im Linkerscript steht (warum auch immer).  Aber: das interessiert dich
eigentlich gar nicht, denn niemand benutzt das auf diese Weise
allozierte Byte jemals: der Compiler weiß ja gar nichts davon,
folglich greift er auch nicht drauf zu.

> Jörg Wunsch schrieb:
>> UCSR0A = (1 << MPCM0) /* | andere Bits hier, die du setzen willst */;
>
> Das ist eben was völlig anderes. Ich will ja nicht irgendwelche Bits
> setzen, sondern nur eins ändern. Der Rest soll so bleiben.

Du hast es nach wie vor nicht kapiert: es ist die Hardware, die
dieses dein Ansinnen nicht umsetzen kann.  Egal, wie du's drehst und
wendest, ob du ein SBI oder ein LDS/ORI/STS nimmst, jegliche Form von
read-modify-write auf dieses IO-Register riskiert, dass du
versehentlich eins der Interruptflag-Bits löschst, die ebenfalls im
Register enthalten sind.

Das ist letztlich ein Kompromiss: ursprünglich war dieses Register ein
reines IRQ-Status-Register, da wurde also höchstens drauf geschrieben
zu dem Zweck, ein solches IRQ-Flag zu löschen.  Später kam dann das
U2Xn-Bit dazu als Konfigurationsbit, das geschrieben werden muss.
Kein großes Problem, das Bit wird in der Regel ja nur einmal während
der Initialisierungsphase der UART angefasst, und da sollten ohnehin
noch keine IRQ-Flags gesetzt sein.  Außerdem war es dazumals das
einzige Steuerbit, braucht man ohnehin kein read-modify-write dafür,
das kann man immer direkt schreiben.  Nun ist mit dem MPCMn-Bit da
noch eins dazu gekommen, das regelmäßig im Betrieb geschrieben werden
muss, da muss man einfach aufpassen, dass man sich dabei kein IRQ-Flag
zerdonnert.  Daher der Hinweis im Datenblatt (der allerdings meiner
Meinung nach nicht ganz glücklich formuliert ist).

Also nochmal: don't do this.  Wenn du partout mit read-modify-write
arbeiten willst, dann maskiere die IRQ-Flags raus:
1
  UCSR0A = (UCSR0A & (1 << U2X)) | (1 << MPCM0);  // setzen
2
  ...
3
  UCSR0A = UCSR0A & (1 << U2X); // löschen

von Paul (Gast)


Lesenswert?

Aus Lehrbetriebssicht:

Zum Programmieren eines (ersten) µC muß man erst mal das 
Programmiermodell verstehen, Adressierungsarten kennen usw., um 
überhaupt die Funktionsweise zu verstehen. Hierfür bietet sich Assembler 
geradezu an. Auch wird man beim Debuggen ohne Assemblerkenntnisse auch 
beim C-Programm nicht allzuweit kommen. Danach kann man C als 
Vereinfachung und wegen der Portabilität lernen. So geschieht es auch an 
der Uni/FH. Einen Controller/DSP in Assembler. Dann Ausweitung auf C 
Danach: "Kennste einen, kennste alle". Jedenfalls in der Funktionsweise.

Aber: Für das Erlernen von Assembler ist der Atmel relativ ungeeignet. 
Diese Controllerfamilie hat einen relativ untypischen Assemblersyntax 
und Vorrat an Befehlen. Sehr gut für die Schulung sind die Motorola HC 
12 oder MSP 430. Das sind gängige Assemblerkonzepte. C-Syntax ist auf 
allen ähnlich (Ansi).

Als professioneller µC-Programmierer braucht man Assembler und C. Die 
weitaus größere Anwendung findet jedoch C.

von Peter D. (peda)


Lesenswert?

Jörg Wunsch schrieb:
> Nun ist mit dem MPCMn-Bit da
> noch eins dazu gekommen, das regelmäßig im Betrieb geschrieben werden
> muss, da muss man einfach aufpassen, dass man sich dabei kein IRQ-Flag
> zerdonnert.

In der Regel wird aber der Master warten, bis der Slave zuende gesendet 
hat, eh er ihn neu adressiert bzw. der Slave wird erst senden, nachdem 
er adressiert wurde.
Es wird also praktisch niemals was gesendet, wenn Du umschalten mußt und 
daher darfst Du ruhig SBI/CBI nehmen. Dein Programm wird trotzdem 
einwandfrei laufen.
Das TXC-Bit braucht man eh nur am Ende, um die Richtung des RS-485 
umzuschalten.

Das vermeintliche Problem löst sich also ganz von selber in Nichts auf.


Peter

von Ralf (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Der kennt weder MPCM0 noch UCSR0A.

das war noch das Original vom mega162. Um den 'Fehler' mal einzugrenzen, 
hab ichs für den tiny2313 übersetzt. Natürlich ohne Nullen. Vielleicht, 
so dachte ich: großer Speicher, da ist der Compiler etwas großzügiger 
;-)

Jörg Wunsch schrieb:
> Daher der Hinweis im Datenblatt (der allerdings meiner
> Meinung nach nicht ganz glücklich formuliert ist).
>
> Also nochmal: don't do this.

Ich mach's doch gar nicht. Ich wollte nur mal sehen, ob der Compiler das 
auch weiß. (Weiß er nicht; akzeptiere ich mittlerweile auch) Die 
Formulierung im Datenblatt ist schon in Ordnung. Es fehlt aber der 
Hinweis für die (Ausschließlich-)C-Fraktion: 'UCSR0A|= (1 << MPCM0);' -> 
bitte nicht nachmachen!

Jörg Wunsch schrieb:
> weil da irgendwo ein
>
> . = ALIGN (0x2)
>
> im Linkerscript steht (warum auch immer).

Und sowas will ich nicht schulterzuckend hinnehmen.

von Peter D. (peda)


Lesenswert?

Ralf schrieb:
> uint8_t x=1; -> ergibt 2 Bytes
> uint8_t x=0; -> ergibt 1 Byte
> uint8_t x;   -> ergibt 1 Byte
>   = verwunderlich bis ärgerlich

Nö, sondern vollkommen klar.
Das Vorbelegen erfolgt aus dem Flash und der hat nunmal Wortbreite.
Um 1 oder 2 Byte zu laden brauchst Du ein Wort im Flash, der Compiler 
kann keine halben Worte im Flash verwalten.


Peter

von Simon H. (simi)


Lesenswert?

Ralf schrieb:
> Peter Dannegger schrieb:
>> Alle Variablen zum Datenaustausch zwischen Main und Interrupt müssen im
>> Main immer volatile zugegriffen werden!
>
> Sowas hab' ich mir schon gedacht. 'volatile' kenne ich aus der Zeit, wo
> man noch heimlich sich Werte direkt aus der Hardware geholt hat. (Damit
> der Compiler die Variable nicht wegoptimiert)
> Aber bei Softwarezugriffen? Global definieren. Sollte das nicht reichen?

Das Problem bei Interrupts ist, dass der Compiler hier auch vermeintlich 
Unnötiges wegoptimieren kann. Denn er sieht ja nirgens einen Aufruf der 
Interrupt-Routine.

Ralf schrieb:
> @Simon Huwyler
> Die 'Aufgabenverteilung' zwischen Programmierer, Compiler, Linker und
> wie sie alle heißen, ist vielleicht verbesserungswürdig, aber manchmal
> eben einfach so festgelegt, weil es nicht anders geht.

Ich weiss jetzt nicht, ob ich Dich oder Du mich falsch verstanden hast - 
Ich bemängle das nicht an C, im Gegenteil, eben, für mich ist das 
perfekt stimmig! Den Compilder geht die Peripherie nichts an.

Ralf schrieb:
> Wer mit C anfängt, kommt irgendwann an so einen Punkt. Der Quelltext ist
> syntaktisch o.K., das Programm muss eigentlich laufen. Im Datenblatt
> werden ein paar Assemblerbefehle erwähnt, die man nicht versteht und um
> die man sich doch eigentlich nicht kümmern muss, weil man ja in C
> programmiert. Schöner Mist.

Ja, aber eben: Assemblerbefehle lernen hat für mich nichts mit Assembler 
lernen zu tun. "Assembler lernen" gibt es für mich eigentlich gar nicht. 
"Lernen, wie ein Prozi funktioniert" gibt es. Und "Assemblerbefehle im 
Datenblatt nachschlagen" gibt es. Und dann halt noch "Assemblerbefehle 
nicht mehr nachschlagen müssen, weil man sie inzwischen auswendig 
kennt".

Und dann natürlich "Lernen, mit dieser Primitivsprache nicht-primitive 
Programme zu schreiben".

Und dann eben noch (halte ich erstmal für wichtiger als der letzte 
Punkt): "Lernen, wie der Compiler Assembler programmiert".

von Ralf (Gast)


Lesenswert?

Paul schrieb:
> Auch wird man beim Debuggen ohne Assemblerkenntnisse auch
> beim C-Programm nicht allzuweit kommen.

Das ist es!

Übrigens habe ich auch vom C-Compiler für Assembler was gelernt: Dass 
man 16-Bit-Werte einer Funktion in r25:r24 übergibt. Da kann man auch 
mit Konstanten addieren/ subtrahieren. z.B.:
1
adiw r25:r24, 1 ; für einen 16-Bit Zähler

@Jörg Wunsch
Weil wir gerade dabei sind:
1
x=UCSR0A;
2
x|=(1 << MPCM0);
3
UCSR0A=x;
Geht das so? Für höchste Sicherheitsstufe ;-)

von Ralf (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Das Vorbelegen erfolgt aus dem Flash und der hat nunmal Wortbreite.
> Um 1 oder 2 Byte zu laden brauchst Du ein Wort im Flash, der Compiler
> kann keine halben Worte im Flash verwalten.

Klingt logisch. Wenn's so sein muss...

von Ralf (Gast)


Lesenswert?

... aber: Ich kann mir doch mit Assembler auch ein Byte aus dem Flash 
holen. Kann das niemand dem C-Compiler beibringen?

von Peter D. (peda)


Lesenswert?

Ralf schrieb:
> Klingt logisch. Wenn's so sein muss...

Muß so sein, der AVR kann ja nicht mitten in ein Wort springen und einen 
halben Befehl ausführen.
Das halbe Wort muß daher auch in Assembler ungenutzt bleiben.

Um n Byte SRAM vorzubelegen brauchst Du (n+1)/2 Worte Flash.


Peter

von spess53 (Gast)


Lesenswert?

Hi

>... aber: Ich kann mir doch mit Assembler auch ein Byte aus dem Flash
>holen. Kann das niemand dem C-Compiler beibringen?

... aber: Ein einzelnes Byte belegt auch in Assembler ein Word im Flash. 
Das hat nichts mit der Programmiersprache zu tun.

MfG Spess

von Ralf (Gast)


Lesenswert?

@Spess
Jetzt sehe ich ein Missverständnis:
Im Flash werden einzeln abgelegte Bytes ausgerichtet (oder 
Zeichenketten mit ungerader Anzahl von Bytes).
Zugreifen kann ich (muss ich) aber byteweise.
'Meine' zwei Bytes werden aber für den RAM angezeigt.
Data: 2 bytes ...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ralf schrieb:

> 'Meine' zwei Bytes werden aber für den RAM angezeigt.
> Data: 2 bytes ...
1
  .data   : AT (ADDR (.text) + SIZEOF (.text))
2
  {
3
     PROVIDE (__data_start = .) ;
4
    *(.data)
5
    *(.data*)
6
    *(.rodata)  /* We need to include .rodata here if gcc is used */
7
    *(.rodata*) /* with -fdata-sections.  */
8
    *(.gnu.linkonce.d*)
9
    . = ALIGN(2);
10
     _edata = . ;
11
     PROVIDE (__data_end = .) ;
12
  }  > data

Das ALIGN hier ist es.  Danach kommt noch BSS, es wird also wirklich
ggf. ein Byte hier verplempert, aber eben wirklich auch immer nur
maximal dieses eine, nie zwei oder noch mehr.

Warum das so ist, müsstest du ggf. aus den SVN-Logs der AVR-
Linkerscripts in den GNU binutils rausfinden, indem du den zuständigen
Entwickler fragst.

Ralf schrieb:
> Weil wir gerade dabei sind:x=UCSR0A;
> x|=(1 << MPCM0);
> UCSR0A=x;
> Geht das so?

Nein, hat immer noch genau das gleiche Problem.  Wenn da vorher in
UCSR0A ein IRQ-Flag gesetzt war, wird es hinterher gelöscht (durch
Schreiben auf sich selbst).

Einen Vorschlag, wie man es "für höchste Sicherheitsstufe" schreiben
kann (wenn man unbedingt read-modify-write braucht, also an dieser
Stelle nicht mehr weiß, ob U2Xn gesetzt war oder nicht), habe ich
weiter oben bereits geschrieben.

von Ralf (Gast)


Lesenswert?

@Jörg Wunsch

UCSR0A = (UCSR0A & (1 << U2X)) | (1 << MPCM0);  // setzen

mal laut nachgedacht:
U2X aus UCSR0A rausfilten
MPCM0 setzen
alles UCSR0A zuweisen
-------------------------
und hier:

x=UCSR0A;
x|=(1 << MPCM0);
UCSR0A=x;

alles merken in 'x'
MPCM0 setzen
'x' UCSR0A zuweisen

und das geht nicht? Muss ich mal noch drüber nachdenken.

von asmhobbyist (Gast)


Lesenswert?

Paul L. schrieb:
> Hallo! Was meint ihr, welche Sprache für Atmel-Mikrocontroller ich
> lernen sollte? Ich schwanke zwischen Assembler und C, wobei ich eher zu
> C tendiere, da es doch etwas einfacher zu verstehen ist :)

Ich denke, man sollte, wenn einem etwas leicht fällt, diesen Weg als 
Geschenk betrachten und es dankbar entgegennehmen. Dann hängen die 
Lernergebnisse von den verfügbaren Materialien ab, von den 
Ansprechpartnern, Entwicklungsumgebungen, Schnittstellen usw.

Man kann (mindestens) beides lernen, aber wichtig ist auf jeden Fall 
viel und gründlich. Ich würde sagen 0815AVRtuts/C + fette Vertiefung 
(u.a. K+R?). Asm dann nachholen auf Unix mit HLA und dem gdb (u.a. wegen 
der einfachen Hardwareschnittstelle). C-Progs nach Asm übersetzen und 
dann machts auch keine Mühe mehr, die paar Befehle der Microprozessoren 
und ein bißchen c++ und Java zu lernen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ralf schrieb:
> und das geht nicht?

Ja, das geht nicht.

Guck dir doch mal bitte die Mechanik hinter den IRQ-Flags eines AVRs
an: wenn das Bit gesetzt ist, ist der Interrupt anhängig (aber noch
nicht abgearbeitet).  Gelöscht wird ein IRQ-Flag aber, indem man
das Flag mit 1 beschreibt.  Wenn du nun ein Register mit
(potenziellen) IRQ-Flags auf sich selbst schreibst, löschst du diese
allesamt.  Das ist hier nicht gewollt.

Mein Codebeispiel hingegen blendet alle IRQ-Flags aus, indem nur
noch das U2Xn-Bit rausgefiltert wird (das außer MCPMn und den IRQ-
Flags das einzige Bit ist, das noch durch den Anwender gesetzt
worden sein könnte) und danach das MCPMn-Bit neu reingesetzt oder
eben nicht.

von F. T. (acerpower)


Lesenswert?

Wenn ich das alles so durchlese schliesse ich daraus, dass 90% der 
Poster hier
1. das Datenblatt des Prozessors studieren sollten und
2. Assembler lernen und anwenden sollten.
Und dann kann man in C reinschnupperen.
Dann wäre dieser Thread nur 5 Einträge lang!!!

1 oder 2 Byte?? Wir reden hier von einem 8-Bit-Mikrocontroller, der das 
RAM und das EEPROM WORD-Organiersiert! Also es ist immer eine gerade 
Anzahl Bytes.

Ich progge ausschlieslich in Assembler und von C verstehe ich nur 
Bahnhof.
Wenn mann Assembler einmal begriffen hat, dann interessiert einem eine 
anderer Sprache nicht mehr.

von Ralf (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Wenn du nun ein Register mit
> (potenziellen) IRQ-Flags auf sich selbst schreibst, löschst du diese
> allesamt.

Ja richtig, und das hatte ich ausgeblendet...
Jetzt ist mir der Einzeiler verständlich.
Nur noch mal nebenbei: Bei mir hätte dann die Zeile so sein müssen?
x=(x & (1 << U2X)) | (1 << MPCM0);

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:

> Das ALIGN hier ist es.  Danach kommt noch BSS, es wird also wirklich
> ggf. ein Byte hier verplempert, aber eben wirklich auch immer nur
> maximal dieses eine, nie zwei oder noch mehr.
>
> Warum das so ist, müsstest du ggf. aus den SVN-Logs der AVR-
> Linkerscripts in den GNU binutils rausfinden, indem du den zuständigen
> Entwickler fragst.

http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/scripttempl/avr.sc?rev=1.1&content-type=text/x-cvsweb-markup&cvsroot=src

Das ist seit revision 1.1 da drin, du müsstest Marek Michalkiewicz
fragen, warum er das vor knapp 10 Jahren da eingebaut hat.  Ich
kann es mir leider nicht vorstellen, was das soll.

Ralf schrieb:
> Nur noch mal nebenbei: Bei mir hätte dann die Zeile so sein müssen?
> x=(x & (1 << U2X)) | (1 << MPCM0);

Ja.

Hermann Klotz schrieb:
> Ich progge ausschlieslich in Assembler und von C verstehe ich nur
> Bahnhof.
> Wenn mann Assembler einmal begriffen hat, dann interessiert einem eine
> anderer Sprache nicht mehr.

Dein zweiter Satz passt zu deinem ersten.  Wenn du von C genauso viel
Ahnung hättest wie von Assembler, dann würdest du mein oben gemachtes
Statement dagegen verstehen: "Wer Assembler wirklich kennt, nimmt C."

von Martin (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Rolf hat nun extra für Dich erklärt, wie das gemeint ist.

Wäre schön, wenn du dich so ausdrücken könntest, daß man versteht, was 
du willst.

von Martin (Gast)


Lesenswert?

Peter Dannegger schrieb:
> // force access of interrupt variables
> #define IVAR(x)         (*(volatile typeof(x)*)&(x))
>
>
> uint8_t val;

Und warum nicht gleich "volatile uint8_t val;"?

Und warum glaubst du, daß du dein IVAR-Makro dann in der ISR nicht 
brauchst?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Martin schrieb:

> Und warum nicht gleich "volatile uint8_t val;"?

Weil ein Zugriff darauf dann immer "pessimiert" wird.

> Und warum glaubst du, daß du dein IVAR-Makro dann in der ISR nicht
> brauchst?

Weil die ISR nicht unterbrechbar ist.

Ich lege in solchen Fällen innerhalb der ISR eher eine shadow-
Variable an.  Der Wert der volatile-Variablen wird beim Eintritt
in die ISR in die shadow-Variable gelesen und vor dem Austritt
wieder zurück geschrieben.

Welche der Varianten man wählt, ist sicher Geschmackssache.

von Paul (Gast)


Lesenswert?

>Ich progge ausschlieslich in Assembler und von C verstehe ich nur
>Bahnhof.
>Wenn mann Assembler einmal begriffen hat, dann interessiert einem eine
>anderer Sprache nicht mehr.

Im professionellen Umfeld ist das sehr kurzsichtig. Assemblerprogramme 
sind fehlerträchtiger, kaum portierbar und nicht in Teams zu bearbeiten. 
Wiederverwendbarkeit der Routinen ist auch fast unmöglich. Bei jedem 
Architektuswechsel muß der Programmierer neu lernen. C ist der Standard 
im Embedded-Bereich. Assembler nur bei Codeoptimierung (Platz/Speed). 
Manche Firmen verbieten regelrecht das Coden in Assembler (wenn der 
Coder mal kündigt).

von Paul (Gast)


Lesenswert?

>Weil die ISR nicht unterbrechbar ist.

Beim AVR nicht. Bei anderen Architekturen sehr wohl. Ein C-Code sollte 
portierbar sein.

von ... (Gast)


Lesenswert?

Paul schrieb:
> Beim AVR nicht.

Doch, beim AVR auch (wenn man es denn will).

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Paul schrieb:
>>Weil die ISR nicht unterbrechbar ist.
>
> Beim AVR nicht. Bei anderen Architekturen sehr wohl. Ein C-Code sollte
> portierbar sein.

Wann hast du das letzte Mal portierbaren Interruptcode gesehen?

Auch bei anderen Architekturen wirst du hier eine Einzelfallbetrachtung
brauchen.  Es interessiert nämlich nicht die Bohne, ob eine andere,
höher priorisierte ISR diese hier unterbricht, sofern die nicht gerade
auch noch auf der gleichen Variable herumopert (was von der Natur der
Sache her eher sehr selten der Fall sein wird).  Damit ist der Ansatz
an sich erstmal so unportabel nicht.

von Paul (Gast)


Lesenswert?

>Wann hast du das letzte Mal portierbaren Interruptcode gesehen?
Mit Atomic-Befehlen geht das.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Paul schrieb:
>>Wann hast du das letzte Mal portierbaren Interruptcode gesehen?
> Mit Atomic-Befehlen geht das.

Ach?  Und welche zwei Controller mit unterschiedlicher Architektur
haben die gleiche Hardware?  Oder wofür (wenn nicht Hardware) benutzt
du Interrupts (und damit ISRs) so?

Man kann sicher vieles abstrahieren mit einer vernünftigen Software-
architektur, und vieles auch so, dass es trotz Abstraktion keinen
oder nur einen geringen Overhead kostet, aber alles lässt sich nun
wirklich nicht maschinenunabhängig bauen.

von Paul (Gast)


Lesenswert?

Hier ging es ja nicht um den Code, sondern um die Logik der Software 
(ISR können nicht unterbrochen werden, also muß dieser Fall nicht 
betrachtet werden -> Seiteneffekt)

Nach einer Portierung (mit unterschiedlichem ISR Aufruf) ist zwar der 
Code angepaßt, die auf dem AVR richtige Logik führt jedoch zum Fehler 
auf einem System mit ISR-Prio-Vektortabelle (z. B. C167 von 
Siemens/Infineon). Den Fehler muß man dann erst mal finden. Code Ok, 
Logik falsch.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Paul schrieb:
> Hier ging es ja nicht um den Code, sondern um die Logik der Software
> (ISR können nicht unterbrochen werden, also muß dieser Fall nicht
> betrachtet werden -> Seiteneffekt)

Nein, es ging um ein völlig theoretisiertes Beispiel.  Eine ISR muss
man jedoch immer in ihrem Kontext betrachten, in dem sie benutzt
wird, und bei dieser Betrachtung sollte auch klar werden, welche
Maßnahmen man gegen Datenkorruption treffen muss.

Um auf den Anfang zurück zu kommen: in dieser Hinsicht unterscheidet
sich die Programmierung in C und Assembler kein Stückchen.  Diese
Gedanken zum Konzept muss man sich überall machen, danach kommt die
Umsetzung.  Gut, bei Assemblerprogrammierung braucht man sich dann
auch gar nicht erst groß Gedanken zur potenziellen Portierbarkeit
mehr machen. ;-)

von greg (Gast)


Lesenswert?

C ist eine sehr universelle Sprache. Für nahezu jeden Controller und 
jede CPU gibt es einen C-Compiler. Meistens ist aber auch sinnvoll, 
etwas Assembler zu verstehen und schreiben zu können - aber nicht 
Pflicht.

Zur Portabilität: C ist immer wesentlich portabler als 100% 
CPU-spezifischer Assembler. :)

von Ralph (Gast)


Lesenswert?

Eigentlich ist die ganze Diskussion ziemlich sinnfrei.

Nehmen wir mal das, was Sprachenunabhängig ist:
* Wissen wie der µC aufgebaut ist : Brauchst du für jede Sprache
* Wissen wie Register/Ports/.. gelesen und geschrieben werden können : 
Brauchst du für jede Sprache
* Einen Entwurf für dein Programm  : Brauchst du für jede Sprache
* Eine Entwicklungsumgebung passend zum µC : Brauchst du für jede 
Sprache

Kommen wir zum Unterschied zwischen den Sprachen:
* Assembler : Kümmer dich selbst um jedes Detail, Vergiss keine Zeile 
Fleißabeit mit Register retten, umkopieren, wer benutzt gerade was, 
Welche Befehlsoption mit welchen Parameter....... und natürlich deinen 
Programmentwurf
* Hochsprache, zb C: Kümmer dich um deinen Progammentwurf, achte darauf 
das Du Ports/Register,... so ansprichst wie der µC es fordert (steht im 
Datenblatt ), z.b. R/W Zugriffe und lass dann den Compiler/Linker die 
Fleißarbeit erledigen.

Der Compiler macht gerade diese Fleißarbeit garantiert besser als jeder 
Mensch.

Am Ende macht der Compiler genau das was du ihm sagst. Nur wissen WAS du 
ihm sagst, das musst du unabhängig von der Sprache.

Und ein Compiler kann auch nicht aus einem besch.... C Code einen guten 
Assemblercode erzeugen.
Der erzeugt Assemblercode kann nur so gut wie der zu übersetzende C Code 
sein.

Wenn du also gerade als Einsteiger zu einem "schnellen" Erfolgserlebnis 
kommen willst, dann verwende C.
Willst du ein gewaltiges Frustpotential aufbauen starte mit Assembler.
In Assembler freiwillig mehr als ein "Hello World" zu programmieren 
grenzt an Masochismus.

Assembler kannst du dir im Lauf der Zeit etwas anlernen mit Debuggen bei 
Fehlern.


Ich arbeite jetzt seid etlichen Jahren beruflich mit µC und hab in der 
Zeit tausende von Zeilen C - Code geschrieben.
An AssemblerCode waren es mal gerade 10 Zeilen zum Debuggen.
Diese Zeilen waren nötig um zu einem bestimmten Zeitpunkt definierte 
Register zu retten.
==> Ergebnis war dann ein Bug im µC Core, Ja auch so etwas gibt es ( 
Errata Listen)

Also wenn du am Ende Assembler lesen kannst , und in der Lage bist mit 
dem Handbuch ein paar Zeilen einzubauen, dann reicht das völlig.

von asmhobbyist (Gast)


Lesenswert?

Ralph schrieb:


> Also wenn du am Ende Assembler lesen kannst , und in der Lage bist mit
> dem Handbuch ein paar Zeilen einzubauen, dann reicht das völlig.

Das kann man oft lesen. Aber was soll das denn sein, Assemblerbefehle 
"lesen können?" Das ist oft genau das, was in der typischen Literatur 
gängig ist: Wenn du die Befehle kennst, dann kannst du Assembler. Man 
braucht aber viel Übung, theoretisches Know How, undokumentiertes 
Wissen, Standards und "Lerngruppen" usw. , um mehr zu verstehen oder den 
C-Compiler zu überbieten. Das gilt ähnlich für C: Viel Übung hilft 
verstehen, nur C-Befehle lesen können, bringt nicht so sehr weit. Man 
muss schon ein "Gefühl" dafür haben, wohin eine Schleifenverschachtelung 
und ein Zeigewirwarr führen, oder welche Ansätze ineffizient sind u.s.w.

So leidet Assembler nicht nur unter fehlenden Standarts, 
einsteigerfreundlichen Materialien oder schlechten Dokumentationen usw, 
sondern meist auch unter abstrusen Vorurteilen. Asmprogramme sind aber 
kaum fehlerträchtiger als andere Programme, eher weniger (warum?) und 
sie lassen sich i.d.R. wesentlich besser debuggen als Hochsprachen, und 
das ist etwas ziemlich Anfängerfreundliches, abgesehen, von der besseren 
Übersicht, was überhaupt vor sich geht.

von ... (Gast)


Lesenswert?

asmhobbyist (Gast) schrieb:

> Ralph schrieb:


>> Also wenn du am Ende Assembler lesen kannst , und in der Lage bist mit
>> dem Handbuch ein paar Zeilen einzubauen, dann reicht das völlig.

> Das kann man oft lesen. Aber was soll das denn sein, Assemblerbefehle
> "lesen können?" Das ist oft genau das, was in der typischen Literatur
> gängig ist: Wenn du die Befehle kennst, dann kannst du Assembler.

Nein, so ist das nicht bzw. so muss das lange nicht sein. Das ist wie 
mit einer Fremdsprache: Wenn man eine davon fast fließend lesen kann, 
kann man sie noch lange nicht genauso gut sprechen oder schreiben. Das 
geht mir selber so. Es gehört viel praktische Übung dazu auch in 
Assembler programmieren zu können.

> Man
> braucht aber viel Übung, ..

Eben, eben. ;)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.