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
Ueber welche Sprache reden wir denn? C oder C++? In C++ koennte vielleicht was mit constexpr gehen. Constexpr - Generalized Constant Expressions in C++11 http://www.cprogramming.com/c++11/c++11-compile-time-processing-with-constexpr.html constexpr specifier http://en.cppreference.com/w/cpp/language/constexpr
Beitrag #4972486 wurde von einem Moderator gelöscht.
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 | constexpr auto a = 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
1 | auto a = foo(); |
nicht zwingend zur Compilezeit ausführen.
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.
Nop schrieb: > Oder Du baust Dir ein kleines CLI-Tool, Dann kann ich es als constexpr auch im Programm machen (sofern wir von C++ reden).
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.
so zaubert man z.B. auf einem AVR mit gcc6.2 eine 1-wire ID ins Flash:
1 | template <uint64_t V> |
2 | struct OwID { |
3 | uint8_t value[8] = {byte(6), byte(5), byte(4), byte(3), |
4 | byte(2), byte(1), byte(0), calcCrc() }; |
5 | |
6 | // access the single bytes of V at compile time
|
7 | static constexpr uint8_t byte(int idx) { return (V) >> (idx * 8); } |
8 | |
9 | static constexpr uint8_t crc_polynom = 0x8c; |
10 | |
11 | // calculate CRC8 of first 7 bytes of V at compile time
|
12 | static constexpr uint8_t calcCrc() { |
13 | |
14 | // value is not accessable/ready at compile time,
|
15 | // so we replicate it here
|
16 | uint8_t v[7] = {byte(6), byte(5), byte(4), byte(3), |
17 | byte(2), byte(1), byte(0)}; |
18 | |
19 | uint8_t _crc = 0x0; |
20 | |
21 | for (int i = 0; i < 7; i++) { |
22 | for (int bit = 1; bit < 256; bit *= 2) { |
23 | uint8_t _actbit = ((v[i] & bit) == bit) ? 1 : 0; |
24 | |
25 | if ((_crc & 1) != _actbit) |
26 | _crc = (_crc >> 1) ^ crc_polynom; |
27 | else
|
28 | _crc = (_crc >> 1); |
29 | }
|
30 | }
|
31 | return _crc; |
32 | }
|
33 | const uint8_t operator[](const uint8_t idx) const { |
34 | return pgm_read_byte(&value[idx]); |
35 | }
|
36 | };
|
37 | |
38 | const OwID<0x28A2D984000002> myOwId PROGMEM; |
39 | |
40 | ...
|
41 | // access ID's 1st byte
|
42 | auto id0 = myOwId[0]; |
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.
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.