Folgende Problemstellung :
Oft muss ich Software schreiben um unterschiedliche ASICs zu
Testzwecken anzusteuern. (Controll Register Bits setzen, Watchdog
bedienen, etc ).
Die MCU sendet über SPI 32Bit Kommandos an das ASIC. 29 Datenbits, die
letzten 3 Bits sind CRC Bits.
Da die ASICs sehr komplex sind, habe ich in der Software ca. 100
unterschiedliche Kommandos die gesendet werden. All diese 32Bits
Kommandos sind zur Kompilierzeit bekannt., es sind also Konstanten. Für
die CRC Berechnung habe ich eine Funktion, die aus dem 29Bits die 3Bits
berechnet und hinten dran hängt.
Um Zeit zu Sparren (es wird sehr viel kommuniziert, die MCU muss noch
andere Sachen erledigen), berechne ich die crc nicht zur Laufzeit,
sondern beim coden manuell.
Ich frage mich ob es möglich wäre die CRC bits mit dem Präprozessor zu
berechnen ? kann man im Präprozessor schleifen implementieren? (die crc
Berechnung wird in einer Schleife durchgeführt)
Diese Präprozessorberechnung würde man folgenderweise im Programm
nutzen:
send_spi_32Bit(0xe5342608+CALC_3Bit_CRC(0xe5342608));
CALC_3Bit_CRC() Wäre also eine schleifenfunktion die zur kompilierzeit
ausgeführt wird.
Nach dem Kompilieren würde Im listing an dieser Stelle dann folgendes
stehen :
send_spi_32Bit(0xe534260X);
X beinhaltet dann CRC plus die eine "1" (binar : 1XXX),
Ist sowas möglich?
Was kann eigentlich der Präprozessor leisten?
Das würde mir die Arbeit erleichtern, da ich oft die Kommandos verändern
muss .
Gruss,
Jan
Kaj schrieb:> Ueber welche Sprache reden wir denn? C oder C++?> In C++ koennte vielleicht was mit constexpr gehen.
Nicht nur vielleicht, die Implementierung ist banal. Sie entspricht 1:1
der Laufzeit-Implementierung inklusive constexpr specifier.
Mit dem Präprozessor bin ich mir nicht mehr so sicher. Prinzipiell kann
man mit jeder Menge Magie Schleifen und Loops hinbiegen, aber das is den
Aufwand imho nicht Wert. Mal davon abgesehn, würd ich mich nicht mehr
trauen sowas meinem Arbeitgeber zu präsentieren...
Jan schrieb:> Da die ASICs sehr komplex sind, habe ich in der Software ca. 100> unterschiedliche Kommandos die gesendet werden.Jan schrieb:> Um Zeit zu Sparren (es wird sehr viel kommuniziert, die MCU muss noch> andere Sachen erledigen), berechne ich die crc nicht zur Laufzeit,> sondern beim coden manuell.
100 CRCs einmalig beim Start zu berechnen sollte wenige Millisekunden
dauern. Ist die Power-On Zeit deines Controllers wirklich so kritisch,
dass dafür kein Zeit ist?
Wenn du die CRCs bei jedem Senden berechnest, obwohl sie ja konstant
bleiben, ist das natürlich Zeitverschwendung.
chris schrieb:> 100 CRCs einmalig beim Start zu berechnen sollte wenige Millisekunden> dauern.
Aber warum sollte man das wollen, wenn man das doch schon zur
Compiletime machen kann?
chris schrieb:>>> 100 CRCs einmalig beim Start zu berechnen sollte wenige Millisekunden> dauern. Ist die Power-On Zeit deines Controllers wirklich so kritisch,> dass dafür kein Zeit ist?> Wenn du die CRCs bei jedem Senden berechnest, obwohl sie ja konstant> bleiben, ist das natürlich Zeitverschwendung.
Nur wenn man die CRC als Bestandteil einer ID/eines Code's ins Flash
brennen will, dann muß man das zur Compiletime berechnen. Von Hand oder
mit einer Sprache, die das kann.
Carl D. schrieb:> chris schrieb:>>>>>> 100 CRCs einmalig beim Start zu berechnen sollte wenige Millisekunden>> dauern. Ist die Power-On Zeit deines Controllers wirklich so kritisch,>> dass dafür kein Zeit ist?>> Wenn du die CRCs bei jedem Senden berechnest, obwohl sie ja konstant>> bleiben, ist das natürlich Zeitverschwendung.>> Nur wenn man die CRC als Bestandteil einer ID/eines Code's ins Flash> brennen will, dann muß man das zur Compiletime berechnen. Von Hand oder> mit einer Sprache, die das kann.
Nur, was man zur Laufzeit berechnen muss(!), sollte man auch zur
Laufzeit tun. Alles andere zur Compilezeit.
Wie oben ja schon gesagt: in C++ haben wir constexpr-function und
neuerdings auch constexpr-lambda-expressions! Das ist echt schön. Man
kann zur Compilezeit suchen, sortieren, ... solange das ganze eben
insgesamt constexpr bleibt - ein reinterpret_cast<>() scheidet dann aus.
1
constexprautoa=foo();
geht nur dann, wenn foo() tatsächlich constexpr ist und wird
dementsprechend zur Compilezeit ausgeführt.
Zudem ist constexpr nur ein Hinweis an den Compiler, er muss also
Hmm, 29 Bit Daten, 3 Bit "Crc".
Gibt 2^29 Möglichkeiten, und 2^3 = 8 unterschiedliche "Crc"s dazu.
Wohl kein Standard.
>ca. 100 unterschiedliche Kommandos
Wenn diese gesammelt im "Code" stehen, sollte sich irgendwie ein Macro
erstellen lassen, das die "Crc" dazu ausrechnet und anhängt.
Wir kennen deine Programmiersprache nicht.
Alternativ über externes Programm die "Crc"s der 100 Datensätze
ausrechnen.
Für bessere Ratschläge bräuchte es mehr Details.
Gruss
Wilhelm M. schrieb:> Nur, was man zur Laufzeit berechnen muss(!), sollte man auch zur> Laufzeit tun. Alles andere zur Compilezeit.
Prinzipiell gebe ich dir Recht.
Aber wenn der Aufwand unnötig groß ist, das zur Compilezeit zu machen,
und es gleichzeitig kein Problem ist, es zur Laufzeit zu machen, sollte
man es sich leichter machen.
Wenn man jetzt stundenlang rumbasteln muss bis der Compiler es macht,
ist der Aufwand ggf. unangemessen hoch für dieses "Problem".
Oder Du baust Dir ein kleines CLI-Tool, was Du aus dem Buildscript
heraus aufrufst. Das kann die Konstanten ausrechnen und ein Textfile
ausgeben, z.B. in der gewünschten Programmiersprache. Das geht dann an
der richtigen Stelle mit einen #include oder so rein.
Ist mit Sicherheit weniger Arbeit und nachvollziehbarer als mit dem
Präprozessor.
chris schrieb:> Wilhelm M. schrieb:>> Nur, was man zur Laufzeit berechnen muss(!), sollte man auch zur>> Laufzeit tun. Alles andere zur Compilezeit.>> Prinzipiell gebe ich dir Recht.> Aber wenn der Aufwand unnötig groß ist, das zur Compilezeit zu machen,> und es gleichzeitig kein Problem ist, es zur Laufzeit zu machen, sollte> man es sich leichter machen.
Dadurch wird es nicht leichter.
Ich schreibe dieselbe Funktion / Klasse (kein Präprozessor!), nur
verwende (!) ich sich zur Compilezeit!
> Wenn man jetzt stundenlang rumbasteln muss bis der Compiler es macht,> ist der Aufwand ggf. unangemessen hoch für dieses "Problem".
Das verstehe ich nicht: ist doch unabhängig dann, ob Laufzeit oder
Compilezeit.
Danke schon mal für die Antworten, die refe ist vom C. Constexpr
funktioniert nur mit C++ wenn ich es richtig verstehe.
Vom Präprocessor lasse ich die Finger. Das wird zu kompliziert.
Ich suchte eine Lösung die auch vom jedem schnell nachvollziehbar ist.
Ich werde die CRC mit einem externen tool berechnen. Ein tool ins build
process einbinden darf ich nicht. Ich dachte an eine Lösung mit im build
process schon vorhanden tools etc.
Geht scheinbar nicht so ohne weiteres mit C.
Gruss
Jan schrieb:> Danke schon mal für die Antworten, die refe ist vom C. Constexpr> funktioniert nur mit C++ wenn ich es richtig verstehe.
Ja.
>> Vom Präprocessor lasse ich die Finger. Das wird zu kompliziert.
Gute Entscheidung, allerdings mit reinem C schwer durchhaltbar ... auch
bei C++ braucht man immer noch #include und #pragma solange es keine
Module gibt.
> Ich suchte eine Lösung die auch vom jedem schnell nachvollziehbar ist.>> Ich werde die CRC mit einem externen tool berechnen. Ein tool ins build> process einbinden darf ich nicht. Ich dachte an eine Lösung mit im build> process schon vorhanden tools etc.
Schreibst ein C Hilfs-Programm, das erzeugt eine header-datei ...
> Geht scheinbar nicht so ohne weiteres mit C.
Du kannst Deine C Sourcen einfach mit einem C++ Compiler übersetzen.
Wilhelm M. schrieb:> Jan schrieb:>> Ich suchte eine Lösung die auch vom jedem schnell nachvollziehbar ist.>>>> Ich werde die CRC mit einem externen tool berechnen. Ein tool ins build>> process einbinden darf ich nicht. Ich dachte an eine Lösung mit im build>> process schon vorhanden tools etc.>> Schreibst ein C Hilfs-Programm, das erzeugt eine header-datei ...>>> Geht scheinbar nicht so ohne weiteres mit C.>> Du kannst Deine C Sourcen einfach mit einem C++ Compiler übersetzen.
Das Konzept für Compiletime und Runtime die selbe Sprache zu verwenden,
wird sich vermutlich nicht so schnell verbreiten. Denn erst mal müssen
mentale C und C++ Hürden genommen werden. Und erst in C++14 sind
constexpr mächtig genug um Spaß zu machen.
chris schrieb:> 100 CRCs einmalig beim Start zu berechnen sollte wenige Millisekunden> dauern. Ist die Power-On Zeit deines Controllers wirklich so kritisch,> dass dafür kein Zeit ist?
Mir gefällt diese Lösung auch, noch dazu wenn der Algorithmus dafür
schon lauffähig da ist.
Kostet 100Byte RAM und winzige Zeit nach dem Reset. Wenn das beides kein
Problem ist - warum nicht? Entwicklungszeit ist auch eine Ressource,
einen Tod muss man sterben. Man kann vieles immer wieder und immer
weiter optimieren, bringt aber nichts wenn man mit den Ergebnissen der
Optimierung gar nichts anfangen kann.
Andererseits ist es natürlich trotzdem immer gut, sich auch über andere
Lösungen Gedanken zu machen. Und wenn man weiss: es geht auch anders,
aber im Moment brauche ich das nicht, behalte es aber im Hinterkopf ist
das auch ein Ergebnis.
Was ist denn in der Build-Umgebung?
Wir nehmen als externes Tool meist C mit gcc und lassen so quasi den
originalen Code auf dem PC-laufen (ggf. mit Präprozessor des µC). Mit
geringen Modifikationen und einer anderne "main" wird eine .exe erzeugt,
die einen minimalen Header mit den Checksummen schreibt.