Hallo,
eins vorweg: ich bin ein Newbie was Mikrocontroller
betrifft.
Nun habe ich mir die Frage gestellt, ob es
möglich ist, einen Teil eines Programms in c zu programmieren
und einen (zeitkritischen) Teil, des gleichen Programms in Assembler??
Tobi schrieb:> ob es> möglich ist, einen Teil eines Programms in c zu programmieren> und einen (zeitkritischen) Teil, des gleichen Programms in Assembler??
Ja es geht.
Aber warum ?????
Wenn ein Teil so zeitkritisch ist , das es auf einzelne Takte ankommt,
ist im Projekt von Anfang an etwas total falsch gelaufen.
Eine solche Software wird nie und nimmer auf Dauer stabil und
zuverlässig laufen. Dafür gibt es durch Interrupts, unterschiedliche
Ausführungszeiten von Maschinencode, Latenzen beim
Interrupteinstieg,...... viel zu viele mögliche Verzögerungen die nicht
kalkulierbar sind.
Abhilfe :
Die Zeitkritischen Teile so entwickeln das sie nicht mehr zeitkritisch
sind.
Also zb , nur Daten sammeln aber nicht verarbeiten. Das Verarbeiten hat
meist Zeit.
Oder einen µC mit mehr Leistung auswählen.
Tobi schrieb:> ob es> möglich ist, einen Teil eines Programms in c zu programmieren> und einen (zeitkritischen) Teil, des gleichen Programms in Assembler??
Von einigen ideologischen Eiferern abgesehen, ist das eigentlich im
Embedded-Bereich der Normalfall. Nicht nur bei zeitkritischen Teilen,
der Zugriff auf Hardware ist oft in Assembler eher einfacher als in C -
so man denn Assembler kann.
Du brauchsr aber eine sehr gute Dokumentation, besonders wenn Assembler
und C-Compiler nicht aus einer Hand sind - man muss schon genau wissen,
wie eine Assembler-Prozedur von C aus aufgerufen wird, und manchmal auch
umgekehrt, obwohl das eher selten vorkommt. Im Handbuch gibt es dafür
einen Abschnitt "Interfacing to Assembler" oder so ähnlich. Beherrscht
man das, kann man einfach alles machen, auch 5 verschiedene Sprachen
gemischt einsetzen, vorausgesetzt, alle Compiler produzieren Files, die
der Linker verarbeiten kann (z.B. .OBJ). Wenns sein muss, geht es auch
ohne das, mit Sprungtabellen, aber das ist dann schon mühsam.
Gruss Reinhard
Ralph schrieb:> Ja es geht.> Aber warum ?????>> Wenn ein Teil so zeitkritisch ist , das es auf einzelne Takte ankommt,> ist im Projekt von Anfang an etwas total falsch gelaufen.
Du hast wohl noch nie was DSP-mäßiges (Filter, FFT ..) programmiert.
Da kann es durchaus passieren, dass nur ein paar Routinen (komplexe
Schleifen) die meiste Prozessorzeit verbrauchen. Der Unterschied
zwischen nichtoptimiertem C, optimiertem C und Assembler kann gewaltig
sein und hängt oft stark mit den Möglichkeiten der CPU zusammen.
Ein Vorteil bei selbstgeschriebenen Assemblerroutinen ist auch, dass man
im C nichtoptimiert laufen kann, was das Debugging wesentlich
vereinfacht.
Ein weiterer Vorteil ist die Arbeitsplatzsicherung: wenn sich in dem
Programm sonst keiner mehr auskennt, dann fällt es dem chef schwerer
dich zu feuern. Aber Vorsicht: dabei nicht die kritische Masse
überschreiten...
http://xkcd.com/323/
Tobi schrieb:> einen Teil eines Programms in c zu programmieren> und einen (zeitkritischen) Teil, des gleichen Programms in Assembler??
Diese Frage kommt eigentlich immmer nur von Anfängern.
C ist nämlich nicht so langsam, wie manche denken. D.h. oftmals gibt es
gar keinen so zeitkritischen Teil, wo Assembler wirklich helfen würde.
C hat nur bestimmte Vorlieben, die manchmal auf einem 8-Bitter etwas
umständlichen Code erzeugen können. Aber dazu gibt es reichlich
Optimierungstips, wie man es dem Compiler richtig sagt.
Wenn man Assembler kann, dann sieht man auch leicht im Listing, wo man
sich unglücklich ausgedrückt hat.
Peter
Peter Dannegger schrieb:> Diese Frage kommt eigentlich immmer nur von Anfängern.
Das ist mir nun doch ein wenig zu einfach. Ich denke da an Projekte hier
im Forum mit Video-Signalen, die per Software generiert werden oder auch
der v-usb-Treiber, der USB1.1 in Software implementiert. Das sind nun
wirklich keine Projekte von Anfängern. Meiner Meinung nach kommt es
immer darauf an, wie weit man die Code-Generierung kontrollieren muss.
Und eine Antwort auf die ursprüngliche Frage: Es dürfte kaum einen
C-Compiler geben, der nicht die Möglichkeit bietet, Teile des Codes in
Assembler zu erstellen.
Ralph schrieb:> Wenn ein Teil so zeitkritisch ist , das es auf einzelne Takte ankommt,> ist im Projekt von Anfang an etwas total falsch gelaufen.
Einfaches Beispiel, was man in C nicht lösen kann:
Der 8051 hat einen Timer 0, den man im 16-bit-Mode betreiben kann.
Verwendet man ihn als Systemtakt, dann muß man ihn nach einem Überlauf
im Interrupt präzise mit dem errechneten Wert nachladen. Und das geht
nur mit genau aufeinander abgestimmten Assemblerbefehlen.
Für sowas habe ich neben dem C-Code dann auch ein Assemblerfile.
Wohl sah ich schon Leute, die das ganz pragmatisch mit dem Oszi machen,
und die Zahl durch Probieren ermitteln. Das geht natürlich auch, mehr
oder weniger fehlerbehaftet, gehört aber zum Thema "Bastelei".
Detlev T. schrieb:> Ich denke da an Projekte hier> im Forum mit Video-Signalen, die per Software generiert werden oder auch> der v-usb-Treiber, der USB1.1 in Software implementiert. Das sind nun> wirklich keine Projekte von Anfängern.
O.k., dann eben von Anfängern und Bastlern.
Man ist vielleicht stolz, daß man es geschafft hat, aber es hat
keinerlei praktische Bedeutung.
In einem professionellen Gerät wird niemand VGA oder USB zu Fuß
programmieren. Dafür nimmt man einfach die richtigen Controller, die
sowas intern haben.
Peter
>Ja es geht.> Aber warum ?????>> Wenn ein Teil so zeitkritisch ist , das es auf einzelne Takte ankommt,> ist im Projekt von Anfang an etwas total falsch gelaufen.
Was ist denn, wenn eine Interuptroutine besonders schnell sein muss?
Die hat dann nichts mit der Laufzeit des Hauptprogramms zu tun, und das
Programm wird sehr wohl stabil laufen
>C ist nämlich nicht so langsam, wie manche denken. D.h. oftmals gibt es>gar keinen so zeitkritischen Teil, wo Assembler wirklich helfen würde.>C hat nur bestimmte Vorlieben, die manchmal auf einem 8-Bitter etwas>umständlichen Code erzeugen können.
Sehr richtig. Nur dem einem fällt das eine leichter, eimem anderen die
Assembler Methode.
Deshalb ist es ja schön, dass man beide Möglichkeiten hat.
Reinhard Kern schrieb:> Von einigen ideologischen Eiferern abgesehen, ist das eigentlich im> Embedded-Bereich der Normalfall. Nicht nur bei zeitkritischen Teilen,> der Zugriff auf Hardware ist oft in Assembler eher einfacher als in C -> so man denn Assembler kann.
So kenne und sehe ich das auch, immer noch fast täglich.
PS: Ralph hat keine Anhnung
Wilhelm Ferkes schrieb:> Wohl sah ich schon Leute, die das ganz pragmatisch mit dem Oszi machen,> und die Zahl durch Probieren ermitteln.
Das ist aber auch eine typische Anfänger-Vorgehensweise, mit dem Oszi
geht Deine Uhr dann nach dem Mond.
Man sollte schon den Simulator nehmen, der Oszi kann ja nicht eine
Sekunde auf den CPU-Zyklus genau auflösen.
Oder man schaut ins Assemblerlisting, wieviel Zyklen genau das Laden
kostet.
Der C-Profi macht das wieder anders. Er überlegt, wie groß die
Abweichung sein darf und rechnet mit gebrochenen Zahlen (verschiedene
Reloadwerte je Interrupt). Oder nimmt ganz einfach einen 8051-Typ mit
T2.
Ich geb zu, ich habe auch zu Anfang versucht, Assembler und C zu mixen.
Aber es macht mehr Arbeit, sieht häßlich aus und ist schlecht wartbar.
Es hat sich also nicht gelohnt.
Peter
Detlev T. schrieb:> Peter Dannegger schrieb:>> Diese Frage kommt eigentlich immmer nur von Anfängern.>> Das ist mir nun doch ein wenig zu einfach. Ich denke da an Projekte hier> im Forum mit Video-Signalen, die per Software generiert werden oder auch> der v-usb-Treiber, der USB1.1 in Software implementiert
Schon.
Aber wer sowas baut, muss nicht in einem (diesem) Forum nachfragen, wie
man C und Assembler mischt. Wer auf diesem Level programmiert, hat sich
schon längst die Doku dazu reingezogen.
Und er beginnt vor allen Dingen seine Frageposting nicht mit ...
> ich bin ein Newbie was Mikrocontroller betrifft.
Peter Dannegger schrieb:> Das ist aber auch eine typische Anfänger-Vorgehensweise, mit dem Oszi> geht Deine Uhr dann nach dem Mond.
Ja eben, wenn es um eine Uhr geht.
Sorry, daß ich das jetzt sagen muß, aber ich sah das genau bei einem
langjährigen Profi.
> Oder man schaut ins Assemblerlisting, wieviel Zyklen genau das Laden> kostet.
Ich verlasse mich nicht gerne auf den Compiler, der mir dann irgendwann
mal was anderes serviert, und neue Störungen einbringt. Das braucht nur
ein Versions-Update zu sein, wo was geändert wurde. Man compiliert, und
hat dann auf einmal anderen Code im Listing stehen.
Ansonsten finde ich ein Assemblerfile zwischen C-Files nicht häßlich.
Und wartbar muß die Timernachladung für den 8051 auch nicht mehr sein.
Die bleibt für alle Zeiten so, wie sie auch vor 20 Jahren schon war. Da
gibts dann nichts mehr zu optimieren.
Ein weiteres Beispiel von mir:
Keil hat für die LPC2000 ein Startup-File in Assembler. Das hat bestimmt
auch so seinen Grund. Ob das aktuell immer noch so ist, weiß ich
indessen nicht.
Oder, was ich im LPC2000 in Assembler selbst machte: Den
Spurious-Interrupt-Handler, den Surprise-Interrupt-Handler, beide ins
Startup-File an den Vektoren eingefügt, und den Nesting-IRQ-Handler.
Irgendwas war dort immer drin, was in C nicht geht.
Das LPC2000-Tutorial von Trevor Martin (von Rowley, Compilerhersteller)
hatte da auch die Assemblerbeispiele. Der müht sich sicherlich nicht
umsonst damit ab.
Wenn man das Interface zwischen Assembler und C einmal raus hat, ist
doch alles kein Problem mehr.
SDCC hat im Manual zum Compiler auch was über Assembler-Interface
stehen, aber nur minimalst. Dort mußte ich einige Zeit herum probieren,
bis es klappte. Denn mit Beispielen haben die es da nicht so. Die
Übergabe- und Rückgabeparameter waren noch beschrieben. Und wenn man
dann assembliert, hat man auf einmal die ellenlange Registersicherung
mit drin. Dann beginnt man dort wieder zu suchen. Also, es gab da so
einige Dinge zu beachten. Wenn ein anderer das dann sieht, was man
machte, sagt er natürlich: Sieht doch simpel aus, das hätte ich locker
auch gekonnt. Wie immer, wenn man was fertiges sieht. ;-)
Peter Dannegger schrieb:> Wilhelm Ferkes schrieb:>> Wohl sah ich schon Leute, die das ganz pragmatisch mit dem Oszi machen,>> und die Zahl durch Probieren ermitteln.>> Das ist aber auch eine typische Anfänger-Vorgehensweise, mit dem Oszi> geht Deine Uhr dann nach dem Mond.> Man sollte schon den Simulator nehmen, der Oszi kann ja nicht eine> Sekunde auf den CPU-Zyklus genau auflösen.
Nein, man sollte eine Sprache nehmen, mit der man die Zahl an Taktzyklen
genau kontrollieren kann. Alles andere ist Gemurkse, egal ob per Oszi,
per Simulator oder per Ausrechnen aus generiertem Assembler-Code.
Wenn es wirklich um zyklengenaue Timings geht, ist eine Implementation
in Assembler die einzige saubere Möglichkeit, und meistens sind diese
zeitkritischen Code-Teile auch sehr klein.
Es hat schon einen Grund, warum die Loops der delay-Funktionen der
avr-libc in Assembler implementiert sind und nicht in C und dann per
Austesten im Simulator auf die richtige Zeit hingefrickelt wurden.
Rolf Magnus schrieb:> Es hat schon einen Grund, warum die Loops der delay-Funktionen der> avr-libc in Assembler implementiert sind
Bei den Compiler-Bibliotheken gehe ich davon aus, daß die bestmöglichst
optimiert sind, also in Assembler.
Ich als Compiler-Benutzer sehe davon aber nichts, ich rufe sie in C nur
auf.
Ich hab nur einmal ne Lib selber in Assembler geschrieben, weil die
original Lib (64Bit-Math) den Flash explodieren ließ.
Ich hab sie dann auf AVRfreaks gepostet und ruckzuck wurde sie in den
AVR-GCC integriert.
Peter