Hallo, kann mir bitte jemand sagen, wie man in C (gcc) ein Bit eines Vektors auf eine bestimmte Bitbreite weitet? Sinn ist ein Bit eines Vektors zu extrahieren, dass als Gate für ein Byte dienen soll. Z.B. uint8_t vect = 0b00000001; uint8_t gate = "Hier soll Bit 0 von vect auf 8 Bit vergrößert werden" uint8_t output = input & gate; Ich weiß, dass man das über eine if-Abfrage nach dem gesetzten Bit machen könnte. Ich möchte hier aber ein explizites Gate haben.
du könntest das bit nach links shiften so oft wie du es eben brauchst. in assembler geht das mit lsl, in c wirds auch vermutlich ähnlich gehen.
bit-te schrieb: > Hallo, > > kann mir bitte jemand sagen, wie man in C (gcc) ein Bit eines Vektors > auf eine bestimmte Bitbreite weitet? > Sinn ist ein Bit eines Vektors zu extrahieren, dass als Gate für ein > Byte dienen soll. > > Z.B. > > uint8_t vect = 0b00000001; > > uint8_t gate = "Hier soll Bit 0 von vect auf 8 Bit vergrößert werden" > Da das betreffende Bit nur 0 ode 1 sein kann if( vect & 0x01 ) gate = 0xFF; else gate = 0x00; > uint8_t output = input & gate;
Danke für eure Antworten. Einen expliziten Befehl scheint es also nicht zu geben, aber das sind auch gute Möglichkeiten. Sind die Ausführzeiten vom if- und else-Zweig eigentlich gleich (vorausgesetzt es steht etwas gleicher Ausführungslänge innerhalb der Zweige) oder benötigt der Sprung zum else z.B. länger?
bit-te schrieb: > Ich weiß, dass man das über eine if-Abfrage nach dem gesetzten Bit > machen könnte. Ich möchte hier aber ein explizites Gate haben. Was den für ein Gate? Außer das du durch diese Aktion ein paar Befehle extra brauchst hast du überhaupt nix gewonnen....
1 | if( vect & 0x01 ) |
2 | output = input; |
3 | else
|
4 | output = 0x00; |
Ist genau gleichwertig sparrt aber die zusätzliche Verknüpfung wenn der Compiler die nicht schon selbst verwirft. Und ja if/else haben u.U. verschiedene Ausführungszweige, obige else/if KÖNNTE der compiler aber in sbis/sbic übersetzen wodurch man eine gleiche ausführungszeit zwischen else und if erhält.
Gut, dann andere Frage: Wie muss ich es anstellen, dass ich gleiche Ausführungszeiten bekomme?
Das Bit normieren und dann einfach multiplizieren. Der Totschläger, aber eben ohne conditions (if/else, cond?a:b):
1 | #define BIT_AUFBREITEN(value,bitnum,breite) ((((value >> bitnum) & 1) * ((1 << breite) - 1))
|
Die Konstanten werden entsprechend optimiert, wenn bitnum, breite konstant sind. Das vector Beispiel von oben übersetzt sich dann mit
1 | vector = BIT_AUFBREITEN(vector,0,8) ; |
Was nach der Konstantenevaluierung zu
1 | vector = (value & 1) * 0xFF ; |
Ich möchte zwei uC genau synchron halten, auf denen dasselbe Programm laufen soll. Beide bekommen ein gemeinsames IRQ von außen, alles was dann folgt, soll ohne weitere Signale von außen synchron laufen. Ich gehe also davon aus, dass ab dem Eintritt in die ISR beide bei t_0 sind und dass sie nach ein paar Befehlen (alle in der ISR ohne andere IRQs), in denen sie genau dasselbe machen sollen nur mit teilweise anderen Werten (hierfür eben if-else), sie bei einem bestimmten Befehl immer noch synchron sind und diesen gleichzeitig bearbeiten. Meine nächste Idee ist nun, die verschiedenen Werte schon vorher in einer FSM auf eine gleiche Variable zu legen, wo es noch nicht auf Synchronität ankommt, und dann einfach zuzuweisen. Damit fällt if-else im zeitkritischen Teil weg.
Die uC haben den gleichen Takt, nicht dieselbe Quelle. Die dadurch entstehende Verschiebung von max. 1 Takt ist okay, möchte aber nicht durch den Programmcode zusätzliche Verschiebungen erzeugen.
Lieber würde ich aber mal über die Forderung "zwei unsynchronisierte µCs sollen freiwillig eine Zeitlang absolut synchron laufen" nachdenken. Warum müssen die das tun, welche maximale Abweichung ist dabei zulässig, und was würde in diesem Fall passieren?
> Die uC haben den gleichen Takt, nicht dieselbe Quelle. > Die dadurch entstehende Verschiebung von max. 1 Takt ist okay... Wie kommst du darauf, dass das nur 1 Takt sein könnte/sollte/dürfte?
tuppes schrieb: > Lieber würde ich aber mal über die Forderung "zwei unsynchronisierte > µCs sollen freiwillig eine Zeitlang absolut synchron laufen" > nachdenken. Warum müssen die das tun, welche maximale Abweichung > ist dabei zulässig, und was würde in diesem Fall passieren? Yep. Sehe ich auch so. > Beide bekommen ein gemeinsames IRQ von außen, alles was > dann folgt, soll ohne weitere Signale von außen synchron laufen. Wenn die beiden µC vor dem IRQ nicht absolut synchron im Programm auf dem exakt gleichen Maschinenbefehl liefen, dann ist diese Forderung sowieso illusorisch. Wie lange ein Einstieg in die ISR dauert, hängt auch davon ab, welcher Befehl gerade in der Bearbeitung war. Fragt sich jetzt nur, wozu man 2 µC benötigt, die das exakt gleiche Programm taktsynchron abarbeiten müssen. Alle Ausgänge führen immer identische Pegel. Alle Eingänge verhalten sich absolut gleich. Warum nimmt man nicht gleich nur einen µC anstelle des Aufwands 2 µC miteinander zu synchronisieren. Also entweder ist das eine teuflisch gut durchdachte Aufgabenstellung oder es ist der größte Mumpitz der hier im Forum seit einiger Zeit aufgetaucht ist. (Hat das irgendetwas mit Ausfallsicherheit zu tun?)
Hi Ich glaube nicht, das du es schaffen wirst, mit einem Interrupt etwas Syncron zu bekommen, es sei denn, der Interrupt startet die Prozessoren neu. Wenn du aber zwei Prozessoren Redundant betreiben willst, würde ich folgendes vorschlagen: Einfach beschrieben Loop: Lese_Input Bearbeite_Input Merke_Ergebnis Setze_Fertigbit ; für Partner Warte_auf_Partner Vergleiche_Ergebnis Setze_Err_Flag ; 0 = ok, 1= Error und Errorhandling Loop Entweder weden die Ergebnisse getuscht, oder diese werden in Einen für beide µC erreichbare Speicher gesschrieben (Dualport RAM) Bis zum Warte auf Partner ist die Laufzeit jedes Programmes unabhängig. Vielleicht ist eine Laufzeitrechnung und auch ein Vergleich beider Controler denkbar, um einen "müden" Prozess aufzudecken. Auch muß ein Errorhandling bei Ausfall eines Prozessors möglich sein. Allerdings sehe ich noch nicht zwingend einen Interrupt, höchstens für einen Timer. Das ist jetzt mal so aus dem Stegreif zusammengedacht und nichts Ausgereiftes. Gruß oldmax
Die uC verständigen sich über Funk, daher gibt es keine gemeinsame Taktquelle. Dafür, dass die IRQs von den Funkmodulen zum gleichen Zeitpunkt kommen ist gesorgt. Der uC befindet sich zu der Zeit in einem Zustand der FSM, in der er nichts macht außer Schleifen drehen. Der längste Befehl ist also ein 2-Takt Assemblerbefehl für den Schleifenrücksprung, das gibt evtl. eine kleine Ungenauigkeit, wenn die ISR erst danach greift. Die Zeit vom Erkennen der IRQ-Flanke am Pin bis zum Aufruf der ISR sollte auf beiden uC bis auf +-1 Takt gleich sein, oder habe ich etwas übersehen? Mein uC läuft mit 8MHz und ich möchte, dass ein Befehl auf beiden uC mit +-1us Genauigkeit ausgeführt wird, also 8 clk-cycles. Davon ausgehend, dass die ISRs gleichzeitig aufgerufen werden (wobei 1 Takt Unterschied auftreten könnte, wenn die Takte für das Samplen ungünstig zueinander liegen), arbeite ich danach ein paar Befehle innerhalb der ISRs ab, die letztendlich auf beiden uC die gleiche Ausführungszeit in Anspruch nehmen sollen, damit Befehl x anschließend möglichst genau gleichzeitig ausgeführt wird. Sieht da erstmal jemand größere Probleme, die ich nicht beachtet habe? Bin noch nicht so firm in uC-Programmierung. Problem ist unter anderem, dass auf beiden uC die gleiche Firmware laufen soll, allerdings arbeiten die uC unterschiedliche Zweige darin ab, wenn man es so ausdrücken will. Sinn ist, dass die Rollen getauscht werden können. Wenn also innerhalb der ISR z.B. verschiedene Werte geschrieben werden sollen, je nachdem welcher uC angesprochen ist (Identität wird vorher zur Laufzeit bekannt), dann bekomme ich Schwierigkeiten mit der Ausführungszeit, insbesondere wenn ich jedesmal if (uC1) {} else if (uC2) {} mache, da dass unterschiedliche viele Takte brauchen kann. Mein erster Gedanke war etwas wie ein Gate und ein Multiplexer (da ich aus der FPGA-Ecke komme) speicher = (datum_uC1 & gate) | (datum_uC2 & ~gate); wobei Gate (uC1=0x11 oder uC2=0x00) die Identität des uC darstellt. Ich sehe ein, dass der Compiler da seine Optimierungen ansetzt und letztendlich möglicherweise doch nichts anderes als ein if/else rauskommt. Dafür brauche ich eine Lösung.
Ich würde hier einen anderen Ansatz wählen. Das Funksignal triggert keinen IRQ sondern eine Zeitmessung über den Capture timer. Beide µC verarbeiten ihre Daten und schalten bei Timer wert + x den Ausgang. Je nach µC Architektur ( ich kenne die AVR hier nicht im Detail) kann der Ausgang auch hardwaregetriggert vom Timer geschaltet werden. Erreichbare Genauigkeit wäre Timerauflösung +-1 und zusätzlich der Taktdrift durch 2 getrennte Takterzeugungen.
> ... oder habe ich etwas übersehen?
Ich würde sagen: Ja, das hast du :-o
Denn 1 Takt Unterschied kannst du schon haben, wenn alle Befehle gleich
lang sind. Das ist erst mal die Abtastungenauigkeit aufgrund der beiden
unabhängigen Oszillatoren (die ja auseinanderdriften).
Und dann kommt noch dein 2-Zyklen-Jitter von 1 Takt dazu.
Für mich können das bezogen auf den jeweils ersten der beiden uC also 0
(Glück gehabt) bis +2 Takte (spät abgetstet und durch 2-Zyklen-Befehl
verzögert) sein.
Bezogen auf irgendeinen der beiden uC ist m.E. die Ungenauigkeit also
-2..+2 Zyklen.
Warum müssen die uC überhaupt "Taktsyncron" laufen? > Wenn also innerhalb der ISR z.B. verschiedene Werte geschrieben werden > sollen, je nachdem welcher uC angesprochen ist (Identität wird vorher Wenn du den Platz im flash hast: Mach zwei Funktionen draus, lad an der stelle wo die umschaltung geschieht einen Funktionspointer und ruf diesen dann in der ISR auf --> jeder uC führt nur "seinen" Code aus. Löst aber immer noch nicht das Problem das der Compiler verschiedene Codeblöcke ggf anders übersezt/optimiert.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.