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?
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.
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
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
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
@ 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
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?
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 ...'
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
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.
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
:)
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
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
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
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
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.
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.
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
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.
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
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.
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
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.
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
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.
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
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."
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.
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.
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
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).
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:
>> 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.
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.
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
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.
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_tx=1;
4
5
intmain()
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
return0;
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.
>'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?
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 */;
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).
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 ...
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.
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?
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:
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.
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
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.
@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.
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:
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.
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
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.
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
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".
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.:
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...
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
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
@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 ...
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.
@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.
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.
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.
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.
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);
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."
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.
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?
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.
>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).
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.
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.
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.
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. ;-)
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. :)
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.
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.
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. ;)